Pregunta

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 .

¿Fue útil?

Solución

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){

 }
 }

Otros consejos

Wouldn't writing an aspect that works against this be simpler?

@DummyAnnotation
public void dummy(@Otp String otp, @TransactionId String transactionId){
  ...
}

It would also not be Spring-specific, making it easier to test.

(If you intend to traverse into the arguments to extract the OTP or TX ID, e.g. #foo.txId, then this won't work of course, but I think it's simpler otherwise.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top