I have 2 custom annotations:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface FlowPoint {
public enum PointInFlow {
START, END
}
PointInFlow pointInFlow();
}
and:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ScopeAnnotation {
public enum Category {
BUSINESS, DETECTION, INTERNAL_FUNC, THRESHOLD
}
Category category() default Category.DETECTION;
}
At my code I annotated a method with PointInFlow.START
and some others with Category.DETECTION
and Category.BUSINESS
my pointCuts are:
@Pointcut("execution(* *(..)) && @annotation(flowPoint) && if()")
public static boolean executeStartMethod(<annotationPackage>.FlowPoint flowPoint) {
return flowPoint.pointInFlow() == FlowPoint.PointInFlow.START;}
@Before("executeStartMethod(flowPoint)")
public void beforeStartMethod(<annotationPackage>.FlowPoint flowPoint, JoinPoint jp) {
logger.infoBefore(jp, flowPoint.pointInFlow());}
@After("executeStartMethod(flowPoint)")
public void afterStartMethod(<annotationPackage>.annotation.FlowPoint flowPoint, JoinPoint jp) {
logger.infoAfter(jp);}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION;}
@Before("executeDetectionMethod(scopeAnnotation)")
public void beforeDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoBefore(jp, scopeAnnotation.category());}
@After("executeDetectionMethod(scopeAnnotation)")
public void afterDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoAfter(jp);}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeBusinessMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;}
@Before("executeBusinessMethod(scopeAnnotation)")
public void beforeBusinessMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoBefore(jp, scopeAnnotation.category());}
@After("executeBusinessMethod(scopeAnnotation)")
public void afterBusinessMethod(<annotationPackage>.annotation.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoAfter(jp);}
The issue is DETECTION and BUSINESS separately are working, (when I comment out one of the detection or business pointcut definition.) but not as above together.
thanks in advance for any help
You should see the following AspectJ compile error:
circular advice precedence:
can't determine precedence between two or more pieces of advice that apply to the same join point:
method-execution(void de.scrum_master.app.Application.doEight())
As a work-around you can do this:
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation) {
return
scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION ||
scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;
}
@Before("executeDetectionOrBusinessMethod(scopeAnnotation)")
public void beforeDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation, JoinPoint jp) {
infoBefore(jp, scopeAnnotation.category());
}
@After("executeDetectionOrBusinessMethod(scopeAnnotation)")
public void afterDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation, JoinPoint jp) {
infoAfter(jp);
}
Or if you insist in separating the pointcuts and advices for both annotation values, just use around advices instead of before/after:
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionMethod(ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION;
}
@Around("executeDetectionMethod(scopeAnnotation)")
public Object aroundDetectionMethod(ScopeAnnotation scopeAnnotation, ProceedingJoinPoint jp) throws Throwable {
infoBefore(jp, scopeAnnotation.category());
try {
return jp.proceed();
} finally {
infoAfter(jp);
}
}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeBusinessMethod(ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;
}
@Around("executeBusinessMethod(scopeAnnotation)")
public Object aroundBusinessMethod(ScopeAnnotation scopeAnnotation, ProceedingJoinPoint jp) throws Throwable {
infoBefore(jp, scopeAnnotation.category());
try {
return jp.proceed();
} finally {
infoAfter(jp);
}
}