Is it possible to make an Annotation "wrapper"? - java

To prevent an XY Problem I am gonna state my real issue first but my question focuses on my solution for that problem.
I am using Quarkus to build a controller which contains this method:
#GET
#Path("image/{user}")
#Produces("image/png")
#PermitAll
public Response getImageUser(#PathParam("user") String user)
For some implementation reasons out of my control this method needs to handle about a dozen different possible #PathParam, so I'd like to do something like this;
#Path(value = {"image/{user}", "image/{user}/{foo}", "image/{user}/{bar}"})
which is not possible in Quarkus as far as I know. For this purpose I would like to write an Annotation "wrapper" for the #Path Annotation that would accept an array of Strings and then just annotates each of them with #Path and duplicates the method which was annotated with this. Think this;
public #interface Paths {
public String[] value();
for String value : values {
#Path(value)
}
}
This, of course, does not work for many reasons, (one being that annotations need to be processed) but this question is more if this is even possible. A proof of concept so to speak.

You want multiple #PathParam annotations. You can write these directly in Java, using the repeating annotations feature. There is a slightly better explanation at Baeldung.
You will still need to make your annotation processor cognizant of the wrapper annotation. It is named as the argument to the #Repeatable meta-annotation.

Related

How to target methods declared in a controller subclass whilst avoiding ambigous mapping?

I am trying to use AspectJ for logging in a Spring Boot project. The latter has been set up with a controller class that handles the initial request for a particular document through a related REST controller. This controller class is extended by specific classes for each document, which assemble the end product; inheritance was not my idea.
To measure performance I want to log execution time for individual methods by using an #Around advice. However, even when the functions are individually annotated, those in the subclass are not advised. Methods further in the call stack that are not inherited from the initial controller class are not ignored. The relevant subclass methods are public and they are not inherited from the superclass.
Logging the execution time of the controller method is meant to provide the overall duration. Information with respect to subsequent functions is supposed to indicate possible bottlenecks. How can I include the methods declared in the subclass?
Confidentiality precludes sharing specifics, but the relevant aspects of the class structure can be conveyed using generic names:
[
To follow best practices I always intended to implement custom annotations to be used in pointcuts. Nevertheless, initially, I used signature based pointcuts and their combinations. Ignoring package elements of the pointcut declaration:
#Pointcut("execution(public String Controller.*(..)")
public void controllerPointcut() {}
This approach captures the controller methods, as do similar declarations for the reader classes. However such pointcuts are simply ignored in the case of the subclass. Using the + symbol to target child classes does not help. The documentation indicates that inherited or declared methods in a subclass can be targeted by signature. In the specific case this results in an IllegalStateException due to ambiguous mapping, as does the use of a class level annotation, unsurprisingly.
I only need to log two methods in the child classes, so I hoped to target them directly with a common annotation, which I also added to the controller and reader methods. The pattern, excluding package elements is:
#Pointcut("#annotation(LoggableDuration)")
public void readerControllerPointcut() {}
The functions in the latter two are being advised, so the annotation itself is not the problem. Nevertheless, the implementation has been added below. For thoroughness, I used a combined approach as well. The controller methods were targeted with the kind of signature approach shown above and for the rest an annotation was used. The result is the same. The problem seems to be some element of how AspectJ deals with inheritance that I have not been able to discover. However, I did expect that annotating individual methods could possibly allow me to avoid any such considerations.
#Component
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface LoggableDuration {}
Edit: It seems that Spring Boot was not picking up the subclass. Adding the #Component annotation allows AspectJ to advise the desired methods as does a class level custom annotation with ElementType.Type as the #Target value. However, both lead to an IllegalStateException: ambiguous mapping, presumably because of the inheritance of the Rest controllers. I managed to target the subclass methods with execution based pointcuts, which were not ignored. But, this caused the aforementioned exception to appear again.

Can I use annotation to call method after the annotated one?

I am wondering if I can use custom annotation to call some method right after annotated one. For example I have a class that holds some settings that can also notify objects that something has changed (for example user changed something in settings panel). Not all listeners are interested in all types of events, so MyEvent is enum. Now I have structure like this:
class Settings
{
private ArrayList<Listeners> listeners;
private void notifyListeners(MyEvent e)
{
// notify all listeners that something was changed
}
public void setSomeOption(int value)
{
// validate parameter, store it etc.
notifyListeners(MyEvent.SOME_INTEGER_SETTING_CHANGED);
}
}
Of course listening object has to check type of event and ignore it or perform some action, but it is not the case here.
I am interested if I can achieve this with annotations, like this
#NotifyAnnotation(MyEvent.SOME_INTEGER_SETTING_CHANGED)
public void setSomeOption(int value)
{
// validate parameter, store it etc.
// NO NEED TO CALL NOTIFY HERE - WILL BE HANDLED BY ANNOTATION
}
In JUnit for example, we have #Before or #After annotations, and I am wondering if JUnit has own annotations parser that handles method annotated this way, or this kind of behavior can be done simpler, since annotations can be #Retention(value=RUNTIME).
I know that in this example it might look over-complicated and calling notifyListeners() is much simper, but I wan't to know if annotation can be used the way I described, and if yes, can i get some tips? I don't expect ready solution, just a hint if this is possible and what should I take in consideration.
yes, you can do it but you have to use a framework or write one by yourself. you can use for example spring aspects and #After advice (or any other proxy mechanism). you can also use full aspectj for this. another option is to write it by yourself using reflection api. in last case you will need some kind of inversion of control - some mechanism that will launch your method and then the other method
In annotations you need a class that checks for it. they don't work on themselves.
The way systems check for them are with reflection.
Annotation<NotifyAnnotation> a = method.getAnnotation();
And explicitly call their methods
a.notifyListeners(a.evt);
I can't see any advantage with your case. but I see full of disadvantages. They should not be used in actual coding, just for test systems or similar scenarios, where an external system has control on your class.
It could be do that using bytecode manipulation (JAssist, Asm, Java Rocks ...). All the classes would be instantiated thru a Factory that would identify annotated methods and would inject in the first line of this method a call to the method specified in its annotation.

Accessing spring annotation attribute in method

This might be a strange request but is there a way to access Spring annotation attribute in the method itself.
In the example below one can define "user.success" as a constant and use it in the Annotation and the method but I would really like use whats defined in my annotation(#MySecurity).
One way I guess would be get a handle of the executing method to use AnnotationUtils. Is there a better more elegant way of doing this?
#MySecurity(action="user.success")
#RequestMapping("/userSuccess.htm")
public String redirect()
{
// Code here to access #MySecurity Annotation
return "userSuccess";
}
No, it is not possible without reflection. And even then, you need to know the name of the method. Executing code in it doesn't tell you that (except stack trace but don't go that path). Honestly, the annotation should be used by a HandlerInterceptor (with HandlerMethod where you would have access to the annotation) or some kind of BeanPostProcessor.

Inherit from field/method targeted annotation

I'm annotating my classes here and there and I find myself repeating the following:
public class Example
{
#Basic
#Convert("converter")
private AnotherExample ae;
}
To save me some hassle and to ensure correct usage I came up with the idea to create an annotation that inherits from both #Basic and #Convert("converter"). The problem is that both annotations have #Target(value={FIELD, METHOD}) and thus I cannot annotate my custom annotation with them.
Is there any other way to achieve my goal or is this a limitation of Java's annotations?
This is literally the diamond problem from multiple inheritance.
I would argue against trying to merge these annotations together. The point of inheritance is not to save typing. These two annotations are separate for a reason.
Most IDEs can create code from macros which will cut down on your typing. Otherwise, a search and replace regex would definitely work as well.

Java Annotation Processing Tool #NoNull

I want to create an annotation that restricts a developer from specifying null as a parameter, which has been annotated with #NoNull
For example, if I create this method:
public void printLine(#NoNull String line) {
System.out.println(line);
}
On a method call, I want an error to appear if the user specifies null for line: printLine(null);
I have been using APT for only a little bit of time, and am wondering how to do this (if possible)?
This is the annotation I have created so far:
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.SOURCE)
public #interface NoNull {}
Compile time will be tough to check, since you're really dealing with runtime values. If you want to create annotations to automatically add code to check this stuff, you should look at project lombok:
http://projectlombok.org/
It uses an annotation processor to add code to your beans to do various things.
For example:
#Getter #Setter
private int id;
The annotation processor would automatically add get/set methods to your bean.
I don't think it has null checks, but you should be able to add this in and contribute it.
Another option is to use the validation jsr, though this requires you to explicitly validate at runtime, but you could accomplish this with proxies or AOP.
#NotNull #Min(1)
public void setId(Integer id)
The point isn't to use the annotation only for readability, but to enforce the annotation at compile-time with APT
Considering that null is a runtime artifact, I don't see how you will enforce a null check at "compile time."
Instead, you'll have to modify your classes, and apt is not the tool to do this, at least not by itself. It exists to extract information about annotated elements from source files. But to enforce your #Null restriction, you need to modify the running class.
One thing that you could do is use apt to extract information about annotated parameters, then use a tool like aspectj to modify those classes at runtime to check the parameter value.
But that's a topic that's way too broad for a single SO question.
#Nullable, #Nonnull are locating in package: javax.annotation
Checkout guava, its got some nice things are type safety:
http://code.google.com/p/guava-libraries/wiki/GuavaExplained

Categories