Search code examples
javaspringspring-annotations

Custom Annotation with dynamic argument


Here is my problem :

I have an annotation :

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DummyAnnotation {
String dummyParam1();
String dummyParam2();
}

My service is :

@Component
public class DummyService {

@DummyAnnotation(dummyParam1="#otp",dummyParam2="#transactionId")
public void dummy(String otp, String transactionId){

}
}

My aspect is trying to validate the two arguments and throw exception if the validation don't successed :

 @Around(value = "@annotation(annotation)")
public Object verifyOtp(final ProceedingJoinPoint jointPoint, final DummyAnnotation  annotation) throws Throwable {
            String transactionId = annotation.dummyParam1();
            String otp = annotation.dummyParam2();
            Boolean otpValid = otpService.verify(transactionId, otp);
            if (otpValid) {
                return jointPoint.proceed();
            }
            else {
                throw new AuthentificationForteException();
            }

}

How can i get this working because Spring EL is not working and in my Aspect i have dummyAnnotation.dummyParam1() Equal to "#otp" and not to the value of my argument String otp .

Thanks in advance .


Solution

  • Finnaly i find a solution :

    The solution is to implement a specific Spring Expression Parser.
    I added these declaration to my aspect :

    private ExpressionParser expressionParser = new SpelExpressionParser();
    private ParserContext parserContext = new TemplateParserContext();
    

    and I changed how I retrieved my dummyValue :

    @Around(value = "@annotation(annotation)")
    public Object verifyOtp(final ProceedingJoinPoint jointPoint, final DummyAnnotation  annotation) throws Throwable {
    
    String transactionId = getDummyValue(annotation.dummyParam1(),jointPoint.getArgs());
    String otp = getDummyValue(annotation.dummyParam2(),jointPoint.getArgs());
    
            Boolean otpValid = otpService.verify(transactionId, otp);
            if (otpValid) {
                return jointPoint.proceed();
            }
            else {
                throw new AuthentificationForteException();
            }
    

    }

    getDummyValue is a method that parse the expression :

    private String getDummyValue(String authExpression,  Object[] args){
        Expression expression = expressionParser.parseExpression(authExpression, parserContext);
        String value = expression.getValue(new RootObject(args),String.class);
        return value;
    }
    
    
    private static class TemplateparserContext implements ParserContext{
    
        @Override
        public boolean isTemplate() {
            return true;
        }
    
        @Override
        public String getExpressionPrefix() {
            return "#{";
        }
    
        @Override
        public String getExpressionSuffix() {
            return "}";
        }
    
    }
    
     protected static class RootObject {
    
            private final Object[] args;
    
            private RootObject(Object[] args) {
                super();
                this.args = args;
            }
    
            public Object[] getArgs() {
                return args;
            }
        }
    

    and finally I changde my service and the use of the DummyAnnotation to :

     @Component
     public class DummyService {
    
     @DummyAnnotation(dummyParam1="#{args[0]}",dummyParam2="#{args[1]}")
     public void dummy(String otp, String transactionId){
    
     }
     }