Spring AOP pointcut that matches annotation on interface

Posted by seanizer on Stack Overflow See other posts from Stack Overflow or by seanizer
Published on 2010-05-17T08:40:39Z Indexed on 2010/05/17 9:00 UTC
Read the original article Hit count: 389

Filed under:
|
|
|
|

Hello,

this is my first post here, so I apologize in advance for any stupidity on my side.

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.

Thanks in advance, Sean

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>

© Stack Overflow or respective owner

Related posts about java

Related posts about aop