Search code examples
springaopspring-aoppointcutpointcuts

spring AoP, pointcut expression for overloaded methods with same parameter types


I've defined a class for CRUD operations on comments. The read method is overloaded.

class Comment{
    // method 1: returns all the comments by a user
    findAll(long userId, long subjectId, String param);

    // method 2: returns all the comments of all the users
    findAll(long subjectId, String param)
}

The point cut expression I've tried is

@Around("execution(* com.package..*Controller.findAll(..)) && args(userId,subjectId,..)")
public Object validateFindAll(final ProceedingJoinPoint proceedingJoinPoint, final long userId, final long subjectId) {
    // validate userId, if available
    // validate subjectId
}

Problem: As the data types for userId and subjectId are same, the point expression when applied to method 2 shifts the param values by 1 place. This means, the expression does not understand that the first parameter userId isn't passed. Instead, userId gets 'subjectId' as value and the subjectId gets the adjacent parameter 'param' as its value.

Note

  1. I am trying to avoid writing another method like findUserComments().

  2. I want to maintain consistency across the application. There are other classes with similar patterns of CRUD operations.

Question: Is it possible to define an expression applicable to both the methods with the first parameter userId being optional ?

EDIT - Solution While I was playing around with different approaches as suggested in the solutions below, I've finally removed method 2. I handle that case in method 1.


Solution

  • Problem is related to method averloading actually. Since, you are passing long userId and long subjectId AOP will always try to match those arguments. Solutions could be

    1) Create another pointcut for other argument i.e. 1 for long,long and other for long, String

    2) Use variable argument signature in the begining such as

     @Around("execution(* com.org..findAll(..)) && args(..,subjectId,param)")
    public Object validateFindAll(final ProceedingJoinPoint joinPoint, final long userId, final long subjectId) {
    
     }
    

    instead of using variable argument in the begining. Then you can use getArgs() method to figure out arguments. This is simple solution but may slowdown your processing.

    3) Though as a design issue, I would suggest to encapsulate all your parameters in one single object and pass it. Instead of passing multiple parameters. It will help you in future as well.