I have a controller:
@Authorised(id = "{personId}")
@RequestMapping(value = {"{personId}"}, method = GET)
public void test(@PathVariable PersonId personId) {
System.out.println(personId); //gets personId
}
Annotation:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authorised {
String id() default "";
}
Pointcut:
@Pointcut("@annotation(Authorised)")
private void AuthorisedMethod() {}
And the method that has to get {personId} value not string "{personId}":
@Before("AuthorisedMethod()")
public void checkIfIsCurrentlyAuthenticated(JoinPoint joinPoint) throws NoSuchMethodException {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
Parameter[] parameters = signature.getMethod().getParameters();
Authorised annotations = joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes).getAnnotation(Authorised.class);
String id = annotations.id();
System.out.println(id); // prints: "{personId}"
// do the chekcing
throw new UnauthenticatedUserException();
}
Can it be achieved and how?
UPDATE: But what if method argument parameter number don't match with the pointcut args()? I mean that what if specific method has parameter @PathVariable PersonId personId and few more, but poincut needs to know only PersonId personId?
Like @statut said you have to write args() like that: args(personId,..)
You can modify @Before()
annotation to have PersonId
value and pass this value to aspect, for example
@Before("AuthorisedMethod() && args(personId)")
public void checkIfIsCurrentlyAuthenticated(JoinPoint joinPoint, PersonId personId) throws NoSuchMethodException {}
To test it I had the following Aspect:
@Aspect
@Component
public class SomeAspect {
@Pointcut("@annotation(Authorised)")
private void AuthorisedMethod() {
}
@Before("AuthorisedMethod() && args(personId)")
public void checkIfIsCurrentlyAuthenticated(JoinPoint joinPoint, PersonId personId) throws NoSuchMethodException {
System.out.println("aspect " + personId.getId());
}
}
Configuration class:
@Configuration
@ComponentScan(basePackages = {"test"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {
}
Test component:
@Component
public class Test {
@Authorised(id = "{personId}")
public void test(PersonId personId) {
System.out.println("component " + personId.getId()); //gets personId
}
}
And testNG's runner:
@ContextConfiguration(classes = Config.class)
public class TestRunner extends AbstractTestNGSpringContextTests {
@Autowired
test.Test test;
@Test
public void testName() {
test.test(new PersonId("id"));
}
}
When I run it, I get printed "aspect id"
from aspect and "component id"
from invoked method.