What you want cannot be done this way because, as the error message says, the annotation binding is inconsistent: You cannot bind all three annotations at the same time because they are in (possibly mutually exclusive) OR parts of the pointcut, i.e. usually only of of them can be bound (unless you assign multiple annotations to the same method). Your expectation might be that AspectJ can deal with this inconsistency by just assigning null
to the other two if one is bound, but this is not how the compiler works right now.
I can offer a workaround which involves reflection instead of using the @annotation()
binding.
Driver application:
package de.scrum_master.app;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
public class Application {
public static void main(String[] args) {
doGiven("foo");
doSomething("bar");
doWhen(11);
doSomethingElse(22);
doThen();
}
@Given("an input value") public static void doGiven(String string) {}
@When("I do something") public static void doWhen(int i) {}
@Then("I should obtain a result") public static boolean doThen() { return true; }
public static void doSomething(String string) {}
public static void doSomethingElse(int i) {}
}
Aspect:
package de.scrum_master.aspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
@Aspect
public class JBehaveInterceptor {
@Pointcut("execution(@org.jbehave.core.annotations.* * *(..))")
public void jBehavePointcut() {}
@Before("jBehavePointcut()")
public void jBehaveAdvice(JoinPoint.StaticPart thisJoinPointStaticPart) {
Method method = ((MethodSignature) thisJoinPointStaticPart.getSignature()).getMethod();
for (Annotation jBehaveAnnotation : method.getAnnotations()) {
if (jBehaveAnnotation.annotationType().getPackage().getName().equals("org.jbehave.core.annotations"))
System.out.println(thisJoinPointStaticPart + " -> " + jBehaveAnnotation);
}
}
}
As you can see, the pointcut only intercepts methods annotated by org.jbehave.core.annotations.*
which narrows down pointcut matching considerably - to more than just @Given
, @When
, @Then
, but maybe that is even what you want because JBehave offers more annotations than just those.
In the advice we loop over all method annotations because there might be more than just the JBehave ones. If any annotation package name matches the corresponding JBehave package, we do something (in this case print the annotation to standard output).
I hope this solves your problem. I cannot extend the AspectJ language for you, this is the best I can think of. Anyway, this yields the following output:
execution(void de.scrum_master.app.Application.doGiven(String)) -> @org.jbehave.core.annotations.Given(priority=0, value=an input value)
execution(void de.scrum_master.app.Application.doWhen(int)) -> @org.jbehave.core.annotations.When(priority=0, value=I do something)
execution(boolean de.scrum_master.app.Application.doThen()) -> @org.jbehave.core.annotations.Then(priority=0, value=I should obtain a result)