i have 2 custom annotations, but one should always executed before the other. How do i ensure this? Is there some kind of ordering or do it with additional method definitions?
You can ensure the order of your custom annotations with #Order annotation.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/Order.html
Example:
First annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface CustomAnnotation {
}
#Aspect
#Component
#Order(value = 1)
public class CustomAnnotationInterceptor {
#Before("#annotation(customAnnotation )")
public void intercept(JoinPoint method, CustomAnnotation customAnnotation ) {
//Code here
}
}
Second annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface CustomAnnotationTwo {
}
#Aspect
#Component
#Order(value = 2)
public class CustomAnnotationInterceptorTwo {
#Before("#annotation(customAnnotationTwo )")
public void intercept(JoinPoint method, CustomAnnotationTwo customAnnotationTwo ) {
//Code here
}
Using them:
#CustomAnnotationTwo
#CustomAnnotation
public void someMethod(){
}
In this example, CustomAnnotationInterceptor will execute first.
From http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering
Spring AOP follows the same precedence rules as AspectJ to determine the order of advice execution. The highest precedence advice runs first "on the way in" (so given two pieces of before advice, the one with highest precedence runs first). "On the way out" from a join point, the highest precedence advice runs last (so given two pieces of after advice, the one with the highest precedence will run second).
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the declaration order via reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each aspect class, or refactor the pieces of advice into separate aspect classes - which can be ordered at the aspect level.
I know this is very old question, but I just wanted to document my findings. Can anyone please confirm if these are correct?
It is already mentioned in this page that Spring documentation says that execution of annotations is undefined unless #Order annotation is used.
I tried to rename the Aspect classes, and tested many times, and found that Aspect classes are executed in alphabetical order of their names and found that the result is consistent.
Below is my sample code:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface A {}
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface B {}
#Aspect
public class A_Aspect {
#Around("#annotation(mypackage.A)")
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("A_Aspect");
joinPoint.proceed();
}
}
#Aspect
public class B_Aspect {
#Around("#annotation(mypackage.B)")
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("B_Aspect");
joinPoint.proceed();
}
}
class AdvisedClass{
#B
#A
public void advisedMethod(){}
}
When I tried to execute advisedMethod(), following are the logs I received:
A_Aspect
B_Aspect
I changed annotation declaration sequence:
#A
#B
public void advisedMethod(){}
Following are the logs:
A_Aspect
B_Aspect
I renamed Annotation #A to #C, Following are the logs:
A_Aspect
B_Aspect
But, when I tried to rename Aspect class A_Aspect to C_Aspect, Following are the logs:
B_Aspect
C_Aspect
As I said, I want someone to confirm this as I could not find any documentation for this
Checkout https://stackoverflow.com/a/30222541/810109: At least in Java 8 you can retrieve annotations in a guaranteed order, so you just have to declare them in the right order.
First annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface FirstAnnotation {
String value() default "";
}
Second annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface SecondAnnotation {
String value() default "";
}
Usage example:
public class Test {
#SecondAnnotation("second annotation")
#FirstAnnotation("first annotation")
private String annotatedField1 = "value of field 1";
#SecondAnnotation("second annotation")
#FirstAnnotation("first annotation")
private String annotatedField2 = "value of field 2";
#SecondAnnotation("second annotation")
private String annotatedField3 = "value of field 3";
#FirstAnnotation("first annotation")
private String annotatedField4 = "value of field 4";
// Sample
public static void processAnnotatedFields( final Object obj ) throws IllegalArgumentException, IllegalAccessException {
for ( final Field field : getFieldsFornAnotation( obj, FirstAnnotation.class ) ) {
// Do something with fields that are annotated with #FirstAnnotation
final FirstAnnotation an = field.getAnnotation( FirstAnnotation.class );
System.out.print( "#" +an.annotationType().getSimpleName()+ "(" +an.value()+ "): " );
System.out.println( field.getName()+ " = '" +field.get(obj)+ "'" );
}
System.out.println();
for ( final Field field : getFieldsFornAnotation( obj, SecondAnnotation.class ) ) {
// Do something with fields that are annotated with #SecondAnnotation
final SecondAnnotation an = field.getAnnotation( SecondAnnotation.class );
System.out.print( "#" +an.annotationType().getSimpleName()+ "(" +an.value()+ "): " );
System.out.println( field.getName()+ " = '" +field.get(obj)+ "'" );
}
}
/**
* Collect object fields annotated with "annotationClass"
* This can be saved in static map to increase performance.
*/
private static final Set<Field> getFieldsFornAnotation( final Object o, final Class<? extends Annotation> annotationClass ) {
final Set<Field> fields = new LinkedHashSet<Field>();
if ( o == null || annotationClass == null )
return fields;
for (final Field field : o.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(annotationClass)) {
field.setAccessible( true );
fields.add( field );
}
}
return fields;
}
public static void main(final String[] args) throws IllegalArgumentException, IllegalAccessException {
processAnnotatedFields( new Test() );
}
}
Result/output:
#FirstAnnotation(first annotation): annotatedField1 = 'value of field 1'
#FirstAnnotation(first annotation): annotatedField2 = 'value of field 2'
#FirstAnnotation(first annotation): annotatedField4 = 'value of field 4'
#SecondAnnotation(second annotation): annotatedField1 = 'value of field 1'
#SecondAnnotation(second annotation): annotatedField2 = 'value of field 2'
#SecondAnnotation(second annotation): annotatedField3 = 'value of field 3'
You can do it by using EJB interceptors.
you can simply add interceptors via #Interceptors( { MyInterceptor.class } ) and then add for second one #MyInterceptorConfiguration(value=something).
As bkail says in their answer here:
This is only possible with CDI stereotype
annotations (see the interceptor
bindings page for examples) in EE 6 (EJB 3.1).
Yes I think Annotation itself provide annotation for that like #First, and #Second etc. so you can try that
Related
I want to have annotation on class level that will execute advice on every method in annotated class.
Is that even possible.
Example: I would like to annotate OmniDemoService with #DoSomethingForMe and I want both method1 and method2 to log "look at me" before execution
This example is not working and I don't know why. When I transform Pointcut to Around and just use it with annotation (also change annotation ElementType to method) everything is working on method level.
So I think it is wrong defined Pointcut.
Annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface DoSomethingForMe {
}
Advice:
#Aspect
#Component
public class DoSomethingForMeAdvice {
private static final Logger logger = LoggerFactory.getLogger(DoSomethingForMeAdvice.class);
#Pointcut("execution(public * *(..)) && #annotation(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
#Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
}
Usage:
#Service
#DoSomethingForMe
public class OmniDemoService {
private static final Logger logger = LoggerFactory.getLogger(OmniDemoService.class);
public void method1() {
logger.info("---1---");
}
public void method2() {
logger.info("---2---");
}
}
Your issue is that you are confusing pointcut definition with advices.
Pointcut is aiming, advice performs the actual WhateverYouWantToBeExecuted. Like for example
#Pointcut("#annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
#Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
String methodName = jp.getSignature().toShortString();
logger.info("Executing: " + methodName);
}
Solution for the problem is to use within for pointcut
#Pointcut("#within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
#Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
Solution provided by #J Asgarov in the comments
Check out what the AspectJ quick reference says about #annotation():
any join point where the subject has an annotation of type
SomeAnnotation
You used #annotation(DoSomethingForMe) but the "subject" of a method execution is a method. So that would mean any method annotated #DoSomethingForMe.
Use #this(DoSomethingForMe) or #target(DoSomethingForMe).
Thanks to kriegaex for pointing out that #this and #target must be evaluated at runtime, which would pollute the codebase a lot (i.e. check in every method). So the next approach is better:
If you check the AspectJ manual section about type patterns you will see that you can annotate the type directly. Please also remember to use use fully qualified class names. So that would be:
execution(public * (#com.path.DoSomethingForMe *).*(..))
Also, if you have such a simple pointcut and you don't need to reuse it, I think you can drop the additional method and just use it in the advice directly:
#Before("execution(public * (#com.path.DoSomethingForMe *).*(..))")
which says: "before the execution of any public method of a type annotated with #com.path.DoSomethingForMe", where "before the execution of a method" means "inside the method, at the beginning".
Alternatively, if this pointcut looks a bit too complicated for you, you can separate annotation matching and method matching like this, as suggested by J Asgarov in his comment:
#Before("execution(public * *(..)) && #within(com.path.DoSomethingForMe)")
I am trying to come up with a custom annotation, wanted to see if my use-case fit a allowed way of using custom annotation.
I want to replicate what Spring #Value does, but instead of reading a property off of a property, i want to my custom thing.
#Documented
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
#SupportedSourceVersion(SourceVersion.RELEASE_8)
public #interface EncryptedValue {
String value();
}
public Class TestEncrypted {
#EncryptedValue("dGVzdCBzdHJpbmc=");
public String someEncryptedValue;
}
I am hoping in annotation processor, i decrypt value and set to the field someEncryptedValue.
/**
*
*/
#SupportedAnnotationTypes("annotation.EncryptedValue")
#SupportedSourceVersion(SourceVersion.RELEASE_8)
public class CustomProcessor extends AbstractProcessor{
private Types typeUtils;
private Elements elementUtils;
private Filer filer;
private Messager messager;
#Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
typeUtils = processingEnv.getTypeUtils();
elementUtils = processingEnv.getElementUtils();
filer = processingEnv.getFiler();
messager = processingEnv.getMessager();
}
#Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
for(Element ele : annotatedElements) {
EncryptedValue encryptedValue = ele.getAnnotation(EncryptedValue.class);
if(!ele.getKind().isField()){
messager.printMessage(Diagnostic.Kind.ERROR,"EncryptedValue is supported for field");
return false;
}
String annotationValue = encryptedValue.value();
// now get the enclosing type
Set<Modifier> modifiers = ele.getModifiers();
String nameOfVariable = ele.getSimpleName().toString();
// check to see what fields we can modify (i think we can't modify static).
messager.printMessage(Diagnostic.Kind.NOTE,"ClassType: "+ele.getSimpleName().toString()+", nameOf="+annotationValue);
String simpleName = ele.getEnclosingElement().getSimpleName().toString();
for (Element elem : roundEnv.getRootElements()) {
messager.printMessage(Diagnostic.Kind.NOTE, "Enclosing ClassName: "+elem.getSimpleName().toString());
if (elem.getSimpleName().toString().equals(simpleName)) {
for (Element variableDeclaration : elem.getEnclosedElements()) {
if (variableDeclaration instanceof VariableElement) {
messager.printMessage(Diagnostic.Kind.NOTE, "variable: "+((VariableElement) variableDeclaration).getSimpleName().toString());
}
}
}
}
}
}
return true;
}
}
I get the variable, its return types and everything, but not sure how to set value of the variable from this annotation, even if i figure it out, is it good way of using custom annotations.
*Note: This might be sample, what I am planning to do is much more complicated than above sample.
There's no way to modify existing source files via the current publicly-available API. Tools like Lombok which do this are using undocumented internal Javac features to edit the abstract syntax tree. For example, you could use the Sun compiler tree API to obtain a VariableTree, cast it to a JCVariableDecl, then modify it and hope there are no unforeseen consequences. There's no guarantee that tools like Lombok will actually work, and they could break tomorrow with no warning.
What you could do instead is have the annotated classes reference a class which your annotation processor generates, as in the following example:
public class TestEncrypted {
#EncryptedValue("dGVzdCBzdHJpbmc=");
public String someEncryptedValue =
TestEncryptedDecryptedValues.someEncryptedValue;
}
// then generate this class with the annotation processor
final class TestEncryptedDecryptedValues {
static final String someEncryptedValue = "test string";
}
Another way to do something like this would be to use the annotation processor to generate a factory object or method which creates instances of e.g. TestEncrypted with the field assigned to the decrypted value.
A good tutorial for code generation with annotation processors is here: https://deors.wordpress.com/2011/10/08/annotation-processors/
Also, as a side note in case you don't know this, String literals and names appear in the compiled class file, so none of these examples which decrypt the data at compile-time provide any security.
I've got a simple aspect that supposed to set the value of class fied, that has annotation #GuiceInject.
Originally I have this
#GuiceInject(module=RepositoryModule.class)
private IRacesRepository repository;
And I expect to get similar to this
private IRacesRepository repository = GuiceInject.getInstance(IRacesRepository.class);
And here is my aspect
public aspect InjectionAspect {
Object around(): get(#GuiceInject * *) {
System.out.println(thisJoinPointStaticPart);
// instantiate object as it supposed to be null originally
return GuiceInjector.getInstance(thisJoinPoint.getTarget().getClass());
}
}
As far as I understand - I am new to AOP - it supposed to replace get invokations of the field with the code in aspect.
It compiles fine, but when I run the application - nothing happens. I get NullPointerException for readRaces method as it stays null so aspect did not work.
My main class looks like this
public class Example {
#GuiceInject(module=RepositoryModule.class)
private IRacesRepository racesRepository;
private void execute() {
System.out.println("List of races: " + racesRepository.readRaces());
}
public static void main(String[] args) {
new Example().execute();
}
}
What is the problem? Annotation has this definition
#Target(ElementType.FIELD)
// make annotation visible in runtime for AspectJ
#Retention(RetentionPolicy.RUNTIME)
public #interface GuiceInject {
Class<? extends AbstractModule> module();
}
Please try to redefine pointcut syntax as
Object around(): get(#package.subpackage.GuiceInject * *.*)
Correct field signature must specify the type of the field, the declaring type, and name. If your annotation is in different package, it should be fully qualified.
I found several related (not duplicate) question to this, but they didn't satisfy me.
I am unable to understand where and why to use custom annotations?
I read an example of custom annotation in a book, but it was not explained thoroughly.
#interface MyAnno
{
String str();
int val();
}
class MyClass
{
#MyAnno(str = "Annotation example", val = 100)
public static void myMeth()
{
System.out.println("Inside myMeth()");
}
}
class CustomAnno
{
public static void main(String args[])
{
MyClass.myMeth();
}
}
The output is as expected Inside myMeth().
I am having few questions regarding this example.
1- How can I use String str() and int val() in this program? OR
What is the use of any abstract method of an custom annotation?
2- Why custom annotations. I mean that what effect they are having on any code.
3- How can I create an annotation which is having effects like #override is having?(I mean any kind of effect which can be noticed)
If this example is useless for you, then please give me a suitable small example in which a custom annotation is used.
Three main reasons to use custom annotations are:
To reduce the effort of writing code (a compile-time annotation processor generates code for you). Here is a tutorial: part 1, part 2.
To provide additional correctness guarantees (a compile-time annotation processor warns you about errors). One nice tool for this is the Checker Framework, which prevents null pointer dereferences, concurrency errors, and more.
To customize behavior (at run time, your code checks for the annotation using reflection and behaves differently depending on whether the annotation is present). Frameworks such as Hibernate use annotations this way; also see an Oracle article.
In each case, use of annotations reduces the likelihood of errors in your code, compared to other non-annotation approaches.
Here is a minimal example. The following code demonstrates use of custom annotation.
It is about Employees and Benefits. If we have a requirement such that BasicBenefits has to be applied to all types of employess then we can come up with custom annotation such as BasicBenefits, and annotate all types of Employee implementations (e.g. CorporateEmployee, ContractEmployee, ManagerEmployee etc. etc.) with the BasicBenefits.
Custom Annotation Class(interface)
import java.lang.annotation.*;
#Inherited
#Documented
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#interface BasicBenefits {
String bId() default "B-101";
String bName() default "General Class A Employee";
}
Class using the custom annotation(no need of any imports):
#BasicBenefits(bId="B-400", bName="General Plus Class A Employee")
public class Employee {
String eId;
String eName;
public Employee(String eId, String eName){
this.eId = eId;
this.eName = eName;
}
public void getEmployeeDetails(){
System.out.println("Employee ID: "+eId);
System.out.println("Employee Name: "+eName);
}
}
Driver class to test out the above.
import java.lang.annotation.Annotation;
public class TestCustomAnnotationBasicBenefits {
public static void main(String[] args) throws Exception{
Employee emp = new Employee("E-100", "user3320018");
emp.getEmployeeDetails();
Class reflectedClass = emp.getClass();
Annotation hopeBenefitAnn = reflectedClass.getAnnotation(BasicBenefits.class);
BasicBenefits bBenefits = (BasicBenefits)hopeBenefitAnn;
System.out.println("Benefit ID: "+bBenefits.bId());
System.out.println("Benefit Name: "+bBenefits.bName());
}
}
Your code look almost there, just two things need to be included in the main method.
1.) Need reference to MyClass
2.) Need to get the annotation using reflection from MyClass.
Here is a bit modified code from what you have:
#Inherited
#Documented
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnno
{
String str();
int val();
}
//using above custom annotation on class level
//can also use method level
//just need to change t #Target(ElementType.METHOD)
#MyAnno(str = "Annotation example", val = 100)
class MyClass
{
public static void myMeth()
{
System.out.println("Inside myMeth()");
}
}
import java.lang.annotation.Annotation;
class CustomAnno
{
public static void main(String args[])
{
//1. getting reference to the class where the custom annotation is applied.
//2. then getting the annotation to get the values
MyClass myClass = new MyClass();
Class cls = myClass.getClass();
Annotation getMyAnno = cls.getAnnotation(MyAnno.class);
MyAnno myAnno = (MyAnno)getMyAnno;
MyClass.myMeth(); //left this as is.
System.out.println("myAnno.str(): "+ myAnno.str());
System.out.println("myAnno.str(): "+ myAnno.val());
}
}
The abstract methods of the annotation define the values you can pass to it (in your case str = "Annotation example", val = 100). You can access them using reflection (Method.<T>getAnnotation(Class<T>)). Custom annotations don’t have direct impact. They are only useful if you evaluate them.
Note that you have to annotate your custom annotation with #Retention(value=RUNTIME) to be able to read it via reflection.
To be of any use, annotations must be parsed first. The built-in annotations (such as #Override or #FunctionalInterface, to name the most obvious ones) are parsed by the compiler itself. As for custom annotations, these guys are commonly parsed by third-party frameworks, although we can also use the reflection mechanism to demonstrate this technique in standalone code.
By way of an example, the code below changes its behaviour at run time depending on the value of the field declared in the custom annotation named #SwitchingAnnotation:
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#interface SwitchingAnnotation{
boolean flag();
}
public class Worker{
void doThis(){ System.out.println("Doing this"); }
void doThat(){ System.out.println("Doing that"); }
#SwitchingAnnotation(
flag = false
)
public void work(boolean flag) {
if (flag) doThis();
else doThat();
}
}
class Test{
public static void main(String[] args) {
try{
SwitchingAnnotation sw = Worker.class.getMethod("work", boolean.class)
.getAnnotation(SwitchingAnnotation.class);
new Worker().work(sw.flag()); // prints Doing that
}
catch(NoSuchMethodException nsme){
System.out.println(nsme);
}
}
}
I'm trying to use Java annotations, but can't seem to get my code to recognize that one exists.
What am I doing wrong?
import java.lang.reflect.*;
import java.lang.annotation.*;
#interface MyAnnotation{}
public class FooTest
{
#MyAnnotation
public void doFoo()
{
}
public static void main(String[] args) throws Exception
{
Method method = FooTest.class.getMethod( "doFoo" );
Annotation[] annotations = method.getAnnotations();
for( Annotation annotation : method.getAnnotations() )
System.out.println( "Annotation: " + annotation );
}
}
You need to specify the annotation as being a Runtime annotation using the #Retention annotation on the annotation interface.
i.e.
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnnotation{}
Short answer: you need to add #Retention(RetentionPolicy.RUNTIME) to your annotation definition.
Explanation:
Annotations are by default not kept by the compiler. They simply don't exist at runtime. This may sound silly at first, but there are lots of annotations that are only used by the compiler (#Override) or various source code analyzers (#Documentation, etc).
If you want to actually USE the annotation via reflection like in your example, you'll need to let Java know that you want it to make a note of that annotation in the class file itself. That note looks like this:
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation{}
For more information, check out the official docs1 and especially note the bit about RetentionPolicy.
Use #Retention(RetentionPolicy.RUNTIME)
Check the below code. It is working for me:
import java.lang.reflect.*;
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnnotation1{}
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnnotation2{}
public class FooTest {
#MyAnnotation1
public void doFoo() {
}
#MyAnnotation2
public void doFooo() {
}
public static void main(String[] args) throws Exception {
Method method = FooTest.class.getMethod( "doFoo" );
for( Annotation annotation : method.getAnnotations() )
System.out.println( "Annotation: " + annotation );
method = FooTest.class.getMethod( "doFooo" );
for( Annotation annotation : method.getAnnotations() )
System.out.println( "Annotation: " + annotation );
}
}