Reputation: 9178
I have defined by advise to be executed for the two methods :
SampleBusinessLogicImpl.updateSample(Sample sample) and SampleBusinessLogicImpl.createSample(Sample sample)
But my advise get executed for the first update() method only. What am I doing wrong here ?
@Aspect
public class SampleDynamicValidationAspect {
private static final Logger logger = LoggerFactory.getLogger(SampleDynamicValidationAspect.class);
/**
private SampleTblDAO dao; //DAOs can be used inside dynamic validations
**/
@Before("execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.updateSample(com.rakuten.gep.sample.entity.common.Sample,..)) && args(sample,..) throws *Exception"
+"|| execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.createSample(com.rakuten.gep.sample.entity.common.Sample,..)) && args(sample,..) throws *Exception")
public void validate(Sample sample) throws SampleException {
//Dynamic validation here.
//If some validation is failed, wrapped the appropiate exception in SampleException
System.out.println("Involking Dynamic Validator");
}
}
My SampleBusinessLogicImpl class is as follows :
@Service
public class SampleBusinessLogicImpl implements SampleBusinessLogic {
@Autowired
@Qualifier(value="proxySampleTblDao")
private SampleTblDao sampleTblDao;
@Override
@Transactional(rollbackFor=Exception.class)
public Sample createSample(Sample sample) throws SampleException {
//..
}
@Override
@Transactional(rollbackFor=Exception.class)
public Sample updateSample(Sample sample) throws SampleException {
//..
}
}
Upvotes: 1
Views: 12011
Reputation: 2053
When you define the matching method expression in the Pointcut
, it should match the actual method on which you would want to advice
This is what your pointcut expression should be
@Before("execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.updateSample(com.rakuten.gep.sample.entity.common.Sample,..) throws *Exception) && args(sample,..)"
+"|| execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.createSample(com.rakuten.gep.sample.entity.common.Sample,..) throws *Exception) && args(sample,..)")
Reason:
In your case, the method signature is
public Sample createSample(Sample sample) throws SampleException {
public Sample updateSample(Sample sample) throws SampleException {
But, your pointcut is
@Before("execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.updateSample(com.rakuten.gep.sample.entity.common.Sample,..)) && args(sample,..) throws *Exception"
+"|| execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.createSample(com.rakuten.gep.sample.entity.common.Sample,..)) && args(sample,..) throws *Exception")
Notice that the throws *Exception
is outside the method declaration in the pointcut
expression. And that is why the pointcut expression doesnt match your method declaration.
Move the throws *Exception
within execution(
and it will work. I just tried it.
Clarifying the invocation of only one method.
Yes, actually.. You do not need to specify the throws *Exception
. It would suffice with just the method So, if you remove it completely, it would work perfectly fine, with both the method executions. Now, why update works is because, it is declared first in the Pointcut
expression. So, the Pointcut matches the method declaration for updateSample()
then it encounters the out of place *Exception
and the || is applied to *Exception
which actually is nothing.
Now, if you just flip the pointcut expression the way it is declared, the erroronous one that is. Only createSample
would work because that is what the only one matched in the pointcut expression.
Remember, the )
is closed in the execution expression
too.
@Before("execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.createSample(com.rakuten.gep.sample.entity.common.Sample,..) throws *Exception) && args(sample,..)"
+"|| execution(public * com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.updateSample(com.rakuten.gep.sample.entity.common.Sample,..) throws *Exception) && args(sample,..)")
Also, from the Spring AOP documentation
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
All parts except the returning type pattern (ret-type-pattern in the snippet above), name pattern, and parameters pattern are optional.
Hope, i was able to help with the doubt.
Upvotes: 4
Reputation: 81
You can define like this
@Before(value="( execution(* com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.updateSample(..))"
+ "|| execution(* com.rakuten.gep.sample.businesslogic.impl.SampleBusinessLogicImpl.createSample(..)))"
+ " && args(sample)")
Upvotes: 2