Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP pointcut that matches annotation on interface

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> 
like image 938
Sean Patrick Floyd Avatar asked May 17 '10 08:05

Sean Patrick Floyd


People also ask

Which of the following option will match the given pointcut?

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.

What methods does this pointcut expression reference?

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,..))")

Can logical operators be used in the pointcut expression?

4. How to combine pointcut expressions. In AspectJ, pointcut expressions can be combined with the operators && (and) , || (or) , and ! (not) .

What is pointcut annotation?

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.


1 Answers

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!

like image 163
Espen Avatar answered Sep 20 '22 06:09

Espen