I have a service class implemented in Java 6 / Spring 3 that needs an annotation to restrict access by role.
I have defined an annotation called RequiredPermission that has as its value attribute one or more values from an enum called OperationType:
public @interface RequiredPermission { /** * One or more {@link OperationType}s that map to the permissions required * to execute this method. * * @return */ OperationType[] value();} public enum OperationType { TYPE1, TYPE2; } package com.mycompany.myservice; public interface MyService{ @RequiredPermission(OperationType.TYPE1) void myMethod( MyParameterObject obj ); } package com.mycompany.myserviceimpl; public class MyServiceImpl implements MyService{ public myMethod( MyParameterObject obj ){ // do stuff here } }
I also have the following aspect definition:
/** * Security advice around methods that are annotated with * {@link RequiredPermission}. * * @param pjp * @param param * @param requiredPermission * @return * @throws Throwable */ @Around(value = "execution(public *" + " com.mycompany.myserviceimpl.*(..))" + " && args(param)" + // parameter object " && @annotation( requiredPermission )" // permission annotation , argNames = "param,requiredPermission") public Object processRequest(final ProceedingJoinPoint pjp, final MyParameterObject param, final RequiredPermission requiredPermission) throws Throwable { if(userService.userHasRoles(param.getUsername(),requiredPermission.values()){ return pjp.proceed(); }else{ throw new SorryButYouAreNotAllowedToDoThatException( param.getUsername(),requiredPermission.value()); } }
The parameter object contains a user name and I want to look up the required role for the user before allowing access to the method.
When I put the annotation on the method in MyServiceImpl, everything works just fine, the pointcut is matched and the aspect kicks in. However, I believe the annotation is part of the service contract and should be published with the interface in a separate API package. And obviously, I would not like to put the annotation on both service definition and implementation (DRY).
I know there are cases in Spring AOP where aspects are triggered by annotations one interface methods (e.g. Transactional). Is there a special syntax here or is it just plain impossible out of the box.
PS: I have not posted my spring config, as it seems to be working just fine. And no, those are neither my original class nor method names.
PPS: Actually, here is the relevant part of my spring config:
<aop:aspectj-autoproxy proxy-target-class="false" /> <bean class="com.mycompany.aspect.MyAspect"> <property name="userService" ref="userService" /> </bean>
Explanation: Union means the methods that either pointcut matches. Intersection means the methods that both pointcuts match. Union is usually more useful. Explanation: Using the static methods in the org.
This pointcut matches any method that starts with find and has only one parameter of type Long. If we want to match a method with any number of parameters, but still having the fist parameter of type Long, we can use the following expression: @Pointcut("execution(* *.. find*(Long,..))")
4. How to combine pointcut expressions. In AspectJ, pointcut expressions can be combined with the operators && (and) , || (or) , and ! (not) .
Pointcut is a set of one or more JoinPoint where an advice should be executed. You can specify Pointcuts using expressions or patterns as we will see in our AOP examples. In Spring, Pointcut helps to use specific JoinPoints to apply the advice.
If I understand you correct, you want a pointcut that finds all methods in classes that extends MyService and is annotated and with the preferred arguments.
I propose that you replace:
execution(public * com.mycompany.myserviceimpl.*(..))
with:
execution(public * com.mycompany.myservice.MyService+.*(..))
The plus sign is used if you want a joinpoint to match the MyService class or a class that extends it.
I hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With