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.
Related
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.
I am using Spring and Java 8. I would like to create an aspect or something like that that would set value of my field during object construction, the constructor itsleft validates if the field is not null so the value has to be set accordingly, is it possible with aspects ?
protected MyObject(TimeProvider timeProvider) {
this.timeProvider = requireNonNull(timeProvider, " cannot be null");
requireNonNull(someField, "someFieldcannot be null");
Here u can see that someField is required during creation and not specified in list of fields in the constructor. Thats my specific case.
There is something in the question that doesn't sound right, I'll explain...
Spring AOP indeed allows to create aspects that will wrap Spring beans. They're completely irrelevant for non-spring managed objects.
Now if you're talking about Spring Bean: MyObject then spring will create the instance of this object and inject the TimeProvider - an another bean. If this TimeProvider doesn't exist, spring context will fail to start, thats exactly what you're trying to achieve. You're already using constructor injection so this should work as long as MyObject is a spring bean. Obviously in this case you don't need any aspects, spring will do all the job for you.
Alternatively if MyObject is not a spring bean then spring-aop is completely irrelevant as I've explained.
Its possible to go deeper and analyze how Spring AOP really works and you'll realize that they don't do exactly validations like this, but again, this is rather more advaned discussion than required in order to answer this question
You can use BeanFactory to either
Create new (non singleton) instance of of given class - injection will be done for your
Perform injections on already existing object.
In both cases #Autowire + #NotNull on setter/field should do the trick.
Check https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/AutowireCapableBeanFactory.html#autowireBean-java.lang.Object- for example or any other variants.
I am playing around with Java (javax) annotation processing.
Suppose I have an annotation for methods:
#Target(ElementType.METHOD)
public #interface MethodAnnotation { }
Now I want to process all the methods which are overridden from a type with the annotated method:
interface MyInterface() {
#MethodAnnotation
void f()
}
class MyClass implements MyInterface {
override void f() { } // <- I want to process this method
}
#Inherited meta-annotation seems not to be suitable here:
Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class.
Also, is it possible to process an inherited class method which is not overridden in a subclass? Like this:
class MyClass {
#MethodAnnotation
void f() { }
}
class MySubClass extends MyClass { } // <- I want to process its f()
// or at least to find out that it doesn't
// override the method
How can I access the overriden methods of a certain method within AbstractProcessor?
I guess, to achieve this I need to find subclasses of the eclosing class, but I haven't found a way to do this either.
UPD: I suppose it's possible using RoundEnvironment.getRootElements() but still found no proper way of doing this.
The short answer is that out-of-the-box annotation processing isn't going to make this easy for you, but it can be done.
Rather than using the normal dispatch mechanism for processing, you're actually going to have to process every method and do the filtering yourself.
Step 1:
Define your processor so that it supports all annotations by using "*" as its supported annotation type. This will mean that your processor will get invoked every round.
Step 2:
Use getRootElements to get the entire set of elements every round.
Step 3:
Create an ElementScanner8 to traverse any element that you find to look for ExecutableElements. If you're willing to trust that overridden methods are annotated with #Override, you can do a quick filter on those. Otherwise, just look at all of them.
Step 4:
Now you need to see if the method overrides a method with the annotation you're looking for. There's no easy way to get methods that a given method has overridden, so you need to get the enclosing element of the method, look at its superclass and implemented interfaces (recursively), get their enclosed elements, filter out the methods, and test to see if it has been overridden by the method in question. If it has, you can check the annotations to see if it has one you care about.
Step 5:
At this point, you should have the overriding method, the overridden method and the annotation mirror that you were looking for, so you should be able to implement whatever logic you wanted.
according to the javadoc of javax.annotation.processing.Processor in Jsr269-1.8
An annotation is present if it meets the definition of being present
given in AnnotatedConstruct. In brief, an annotation is considered
present for the purposes of discovery if it is directly present or
present via inheritance. An annotation is not considered present by
virtue of being wrapped by a container annotation...
The JavaDoc of AnnotatedConstruct#getAnnotationsByType says that it returns indirectly present annotations, so I think you should scan for methods and check if they indirectly have the annotation using this call. Something in the spirit of this.
Disclaimer... haven't tried it ;)
Method annotations are not inherited. Type annotations can be inherited through the use of "#Inherited" annotation.
What you could do is define a functional interface with an inherited type annotation, however I don't know if this is elegant enough for you.
If those annotations are available at runtime, and you want to reach them at runtime, you can use the Reflections library.
For example:
Collection<URL> urls = ClasspathHelper.forPackage("nl.shopname.location.domain");
Reflections reflections = new Reflections(
new ConfigurationBuilder().setUrls(urls).setScanners(new FieldAnnotationsScanner()));
Set<Field> fieldsWithAnnotation = reflections.getFieldsAnnotatedWith(MyAnnotation.class);
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.
Is it possible to make the BeanFactoryPostProcessor detects if beans classes have methods annotated with a custom annotation (#inject for instance) and proceed to make a certain treatment if it's the case ?
If this is not possible, can you explain how i get access to the beans metadata and exploit it in the BeanFactoryPostProcessor ?
Thanks in advance.
Edit: I came across this link, not sure if it's the right solution though, since i heard that using reflections considerably deteriorates the overall application performance.
The ConfigurableListableBeanFactory passed into the postProcessBeanFactory() method call, has a method getBeanDefinition(String), from which you can get the class name of that bean. From here you can do a Class.forName(String), and get the class, and then you can inspect its members for your annotation. Of course this suggestion uses Java Reflection also.
You could also try to annotate each class that you want to inspect with its own custom annotation. From the ConfigurableListableBeanFactory you can then call getBeansWithAnnotation(Class). This returns a map from beanName to the corresponding instance.
Or you can take a look at the JavaDoc yourself:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.html