Hi, I had this annotation which worked with AspectJ, however stopped working after I migrated to spring-aspects
+ spring-aop
version 6.2.4:
@AfterReturning(pointcut = "this(processor) && @annotation(x.y.z.ProcessorListenerHook)", returning = "returnValue")
public void executeListenersAfter(JoinPoint joinPoint, Processor processor, Object returnValue) {
Exception is:
AmbiguousBindingException Binding of returning parameter is ambiguous: there are 2 candidates.
The problem is in AspectJAdviceParameterNameDiscoverer.getParameterNames
- in processing parameters according to this order
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
private static final String THIS_JOIN_POINT = "thisJoinPoint";
private static final String THIS_JOIN_POINT_STATIC_PART = "thisJoinPointStaticPart";
// Steps in the binding algorithm...
private static final int STEP_JOIN_POINT_BINDING = 1;
private static final int STEP_THROWING_BINDING = 2;
private static final int STEP_ANNOTATION_BINDING = 3;
private static final int STEP_RETURNING_BINDING = 4;
private static final int STEP_PRIMITIVE_ARGS_BINDING = 5;
private static final int STEP_THIS_TARGET_ARGS_BINDING = 6;
private static final int STEP_REFERENCE_PCUT_BINDING = 7;
private static final int STEP_FINISHED = 8;
"Returning binding" is processed BEFORE "this target binding" so during calling maybeBindReturningVariable()
there are two unbound arguments left, so this method throws an exception.
/**
* If a returning variable was specified and there is only one choice remaining, bind it.
*/
private void maybeBindReturningVariable() {
if (this.numberOfRemainingUnboundArguments == 0) {
throw new IllegalStateException(
"Algorithm assumes that there must be at least one unbound parameter on entry to this method");
}
if (this.returningName != null) {
if (this.numberOfRemainingUnboundArguments > 1) {
throw new AmbiguousBindingException("Binding of returning parameter '" + this.returningName +
"' is ambiguous: there are " + this.numberOfRemainingUnboundArguments + " candidates.");
}
Is this the intended behavior?
How should I use both this
and returning
in one @AfterReturning
annotation?
Thanks.
Comment From: sbrannen
Hi @xardael,
Congratulations on opening your first issue for the Spring Framework! 👍
Hi, I had this annotation which worked with AspectJ, however stopped working after I migrated to
spring-aspects
+spring-aop
version 6.2.4:
Just to clarify...
Are you saying that your use of @AfterReturning
works when compiling an aspect using the AspectJ compiler (ajc
)?
Or are you saying that your use of @AfterReturning
worked with a previous version of the Spring Framework and stopped working with Spring Framework 6.2.4?
Comment From: xardael
Hi,
Are you saying that your use of @AfterReturning works when compiling an aspect using the AspectJ compiler (ajc)
I used aspectjrt v. 1.9.22.1.
Edit: I just want to clarify that the exception
AmbiguousBindingException Binding of returning parameter is ambiguous: there are 2 candidates.
is thrown during runtime.
Comment From: jhoeller
I'm afraid this is a limitation of AspectJAdviceParameterNameDiscoverer
indeed: It can only handle signatures that are unambiguous without taking the actual parameter names into account. In your scenario, the processor
and returnValue
arguments are ambiguous if the declared parameter names are not available since both of them could be a target or a return value in terms of type.
The recommended solution is to compile your code with -parameters
so that our StandardReflectionParameterNameDiscoverer
strategy applies in preference to AspectJAdviceParameterNameDiscoverer
which is really a limited fallback (and quite old as well). I'll turn this into a corresponding enhancement request for improving the exception message along those lines.
Comment From: xardael
Thank you @jhoeller, compiled with "-parameters" solved the issue.
One more questien, could it be somehow specified using
argNames="processor,returnValue"
or this is not related?
Thanks.
Comment From: jhoeller
This should work as well. I recommend compiling with -parameters
though.