Thanks Alexander for the response. 

Yes an allArgs designator would be nice to have which would simplify the 
things. My workaround using the ThreadLocal is enough for now as it would 
unblock the use case but it was also nice to know the workaround only using 
AspectJ even though my code is in an application using Spring framework and 
unfortunately Spring doesn’t support percflow instantiation model  
<https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-instantiation-models>.

Regarding the designator I haven’t created any issue on Bugzilla and let the 
decision to be made by Andy Clement about the issue and its priority :) 

Kind Regards
Sina 

> On Sep 8, 2019, at 4:56 AM, Alexander Kriegisch <alexan...@kriegisch.name> 
> wrote:
> 
> What you are implementing is called a wormhole pattern, only in your case you 
> want to generalise it with respect to the caller arguments. For that you 
> would need a hypothetical pointcut designator allArgs(myParameter) which does 
> not exist and which would bind the whole Object[] as produced by 
> Pointcut.getArgs() to a pointcut or advice parameter with a corresponding 
> type. I admit it would be nice to have. If you believe you need it and cannot 
> live with a workaround, feel free to create a Bugzilla ticket for it for 
> future consideration. I cannot speak for Andy Clement, so I have no idea if 
> he would consider implementing it or if he even has free cycles to do so.
> 
> As you said, you could use a singleton aspect with ThreadLocal variable in 
> order to achieve what you want. As an alternative, I want to show you how you 
> can do it with percflow instantiation. Which alternative you choose will 
> depend on how many aspect instances would have to be created in your case and 
> if that would become a problem or not. I recommend to just give it a try:
> 
>  
> package de.scrum_master.aspect;
> 
> import org.aspectj.lang.JoinPoint;
> import org.aspectj.lang.ProceedingJoinPoint;
> import org.aspectj.lang.annotation.Around;
> import org.aspectj.lang.annotation.Aspect;
> import org.aspectj.lang.annotation.Before;
> 
> import de.scrum_master.app.CallerAnnotation;
> 
> @Aspect("percflow(execution(* *(..)) && 
> @annotation(de.scrum_master.app.CallerAnnotation))")
> public class AnotherAspect {
>   private CallerAnnotation callerAnnotation;
>   private Object[] callerArgs;
> 
>   @Before("execution(* *(..)) && @annotation(callerAnnotation)")
>   public void executeCaller(JoinPoint joinPoint, CallerAnnotation 
> callerAnnotation) {
>     this.callerAnnotation = callerAnnotation;
>     callerArgs = joinPoint.getArgs();
>   }
> 
>   @Around("execution(public void callee(String, Integer))")
>   public Object executeCallee(ProceedingJoinPoint joinPoint) throws Throwable 
> {
>     System.out.println(joinPoint);
>     System.out.println("  Caller annotation: " + callerAnnotation);
>     System.out.println("  Caller arguments:");
>     for (Object arg : callerArgs)
>       System.out.println("    " + arg);
>     System.out.println("  Callee arguments:");
>     for (Object arg : joinPoint.getArgs())
>       System.out.println("    " + arg);
>     return joinPoint.proceed();
>   }
> }
> 
> The console log for my previously posted sample code if you only replace the 
> aspect:
> 
> execution(void de.scrum_master.app.SampleClazz.callee(String, Integer))
>   Caller annotation: @de.scrum_master.app.CallerAnnotation(value="xyz")
>   Caller arguments:
>     de.scrum_master.app.Foo@527740a2
>     de.scrum_master.app.Bar@13a5fe33
>   Callee arguments:
>     x
>     11
> execution(void de.scrum_master.app.SampleClazz.callee(String, Integer))
>   Caller annotation: @de.scrum_master.app.CallerAnnotation(value="abc")
>   Caller arguments:
>     22
>   Callee arguments:
>     y
>     22
>  
> Kind regards
> -- 
> Alexander Kriegisch
> https://scrum-master.de <https://scrum-master.de/>
>  
> Sina Golesorkhi schrieb am 07.09.2019 19:31:
> 
> Hi Alexander, 
>  
> Thanks for response. Please find my comments below.
> 
> On Sep 5, 2019, at 5:30 AM, Alexander Kriegisch <alexan...@kriegisch.name 
> <mailto:alexan...@kriegisch.name>> wrote:
> Hi Sina.
> 
> Your request sounds a bit like ordering Mousse au Chocolat without chocolate 
> in a restaurant.
> 
> Interesting metaphor but I don’t see it being the case here :) 
> Your advice has two very specific Foo and Bar parameters, but the 
> corresponding pointcut should not bind them to method parameters. Where else 
> would they come from then? What is the problem anyway? Please give me a 
> reason for wishing to avoid making the pointcut specific to the method 
> signature, then maybe I can help you find a solution for your problem.
> 
>  
>  
> The idea is to be able to annotate a method to tag it so that you can define 
> an Aspect in which you extract some information from the annotation and the 
> annotated method, hence @CallerAnnotation * *(..)).  The reason that I’m 
> using * * (..) is because the I don’t want the Aspect to become aware of 
> signature of the annotated method as this won’t scale if I’m going to use the 
> annotation on top of different methods with different signatures. 
>  
> If I have to bind the the Pointcut definition to a specific method signature 
> then I’m losing the generalization that I get through the annotation. If I 
> only had one PointCut and my final JoinPoint was the annotated method then I 
> could have easily used the thisJoinPoint.getArgs() in order to get the method 
> arguments but since I’m using cflowbelow and combining that Pointcut with 
> another Pointcut to catch the JoinPoint of the callee() method I can only 
> access the args()  of the callee method but not the annotated method. 
>  
> I’m afraid that this is not possible only using AspectJ. My expectation was 
> to be able to get an Object[] which contains the arguments of the annotated 
> method without the need to specify its signature. 
> One way that I can think of would be to have two different advices one for 
> the annotated method and another one for the callee method and use 
> ThreadLocal to pass on the information (arguments of annotated method) and 
> examine and read those args in the second advice from ThreadLocal.
>  
> Thanks.  
> Just guessing you want to re-use the method execution pointcut for another 
> advice, but this time more generically without specific parameters, you can 
> just do it like this (full MCVE <https://stackoverflow.com/help/mcve> 
> follows):
> 
>  
> 
> package de.scrum_master.app;
> 
> public class Foo {}
> 
> 
> 
> package de.scrum_master.app;
> 
> public class Bar {}
> 
> 
> 
> package de.scrum_master.app;
> 
> import static java.lang.annotation.ElementType.METHOD;
> import static java.lang.annotation.RetentionPolicy.RUNTIME;
> 
> import java.lang.annotation.Retention;
> import java.lang.annotation.Target;
> 
> @Retention(RUNTIME)
> @Target(METHOD)
> public @interface CallerAnnotation {
>   String value();
> }
> 
> 
> 
> package de.scrum_master.app;
> 
> public class SampleClazz {
>   @CallerAnnotation("xyz")
>   public void caller(Foo foo, Bar bar) {
>     callee("x", 11);
>   }
> 
>   @CallerAnnotation("abc")
>   public void anotherCaller(int number) {
>     callee("y", number);
>   }
> 
>   public void callee(String s, Integer i) {}
> 
>   public static void main(String[] args) {
>     SampleClazz sampleClazz = new SampleClazz();
>     sampleClazz.caller(new Foo(), new Bar());
>     sampleClazz.anotherCaller(22);
>   }
> }
> 
> 
> 
> package de.scrum_master.aspect;
> 
> import org.aspectj.lang.JoinPoint;
> import org.aspectj.lang.ProceedingJoinPoint;
> import org.aspectj.lang.annotation.Around;
> import org.aspectj.lang.annotation.Aspect;
> import org.aspectj.lang.annotation.Before;
> import org.aspectj.lang.annotation.Pointcut;
> 
> import de.scrum_master.app.Bar;
> import de.scrum_master.app.CallerAnnotation;
> import de.scrum_master.app.Foo;
> 
> @Aspect
> public class MyAspect {
>   @Pointcut("execution(* *(..)) && @annotation(callerAnnotation)")
>   protected void executeAnnotation(CallerAnnotation callerAnnotation) {}
> 
>   @Pointcut("executeAnnotation(callerAnnotation) && args(foo, bar)")
>   protected void executeAnnotationWithArgs(CallerAnnotation callerAnnotation, 
> Foo foo, Bar bar) {}
> 
>   @Pointcut("cflowbelow(executeAnnotation(callerAnnotation))")
>   protected void executeBelowAnnotation(CallerAnnotation callerAnnotation) {}
> 
>   @Pointcut("cflowbelow(executeAnnotationWithArgs(callerAnnotation, foo, 
> bar))")
>   protected void executeBelowAnnotationWithArgs(CallerAnnotation 
> callerAnnotation, Foo foo, Bar bar) {}
> 
>   @Pointcut(value = "execution(public void callee(String, Integer))")
>   protected void executeCallee() {}
> 
>   @Around("executeCallee() && 
> executeBelowAnnotationWithArgs(callerAnnotation, foo, bar)")
>   public Object finalAdvice(ProceedingJoinPoint joinPoint, CallerAnnotation 
> callerAnnotation, Foo foo, Bar bar) throws Throwable {
>     System.out.println("[finalAdvice] " + joinPoint);
>     System.out.println(" " + callerAnnotation);
>     System.out.println(" " + foo);
>     System.out.println(" " + bar);
>     return joinPoint.proceed();
>   }
> 
>   @Before("executeCallee() && executeBelowAnnotation(callerAnnotation)")
>   public void anotherAdvice(JoinPoint joinPoint, CallerAnnotation 
> callerAnnotation) throws Throwable {
>     System.out.println("[anotherAdvice] " + joinPoint);
>     System.out.println(" " + callerAnnotation);
>   }
> }
>  
> See how executeAnnotation(callerAnnotation) is re-used? Maybe this is what 
> you want, maybe not, I have no idea.
>  
> BTW, the console log looks like this:
>  
> [finalAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, 
> Integer))
>   @de.scrum_master.app.CallerAnnotation(value="xyz")
>   de.scrum_master.app.Foo@370736d9
>   de.scrum_master.app.Bar@5f9d02cb
> [anotherAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, 
> Integer))
>   @de.scrum_master.app.CallerAnnotation(value="xyz")
> [anotherAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, 
> Integer))
>   @de.scrum_master.app.CallerAnnotation(value="abc")
>  
> Regards
> -- 
> Alexander Kriegisch
> https://scrum-master.de <https://scrum-master.de/>
>  
> Sina Golesorkhi schrieb am 05.09.2019 01:45:
> 
> Hi there I have the following code sample 
>  
> @Aspect
> public class MyAspect {
>  
>     @Pointcut("cflowbelow(execution(@CallerAnnotation * *(..)) && 
> @annotation(callerAnnotation))")
>     protected void executeBelowAnnotation(final CallerAnnotation 
> callerAnnotation) {
>     }
>  
>     @Pointcut(value = "execution(public void callee(String, Integer))")
>     protected void executeCallee() {
>     }
>  
>     @Around("executeCallee() && executeBelowAnnotation(callerAnnotation)")
>     public Object finalAdvice(final ProceedingJoinPoint joinPoint, final 
> CallerAnnotation callerAnnotation)
>             throws Throwable {
>         return joinPoint.proceed();
>     }
> }
>  
>  
> public class SampleClazz() {
>  
>     @CallerAnnotation("xyz")
>     public void caller(Foo foo, Bar bar){
>         this.callee();
>     }
>  
>     private void callee(String s, Integer i){
>       // Do Something
>     }
> }
>  
> and I would like to know is there any possibility to use the args such as 
> args(..) in order to get the method arguments of the caller method in the 
> following example?
>  
> I know that I can in my first pointcut define 
>  
> @Pointcut("cflowbelow(call(@CallerAnnotation * *(..)) && 
> @annotation(callerAnnotation) && args(foo, bar))")
>     protected void executeBelowAnnotation(final CallerAnnotation 
> callerAnnotation, Foo foo, Bar bar) {
>     }
>  
> So that I also pass on those method params to the finalAdvice method, however 
> I would like to do this without explicitly defining the arguments in my 
> pointcut so that it doesn’t depend on the signature of the annotated method. 
>  
> One way that I have done before has been using another annotation to annotate 
> the params and then having @annotation in my pointcut but I would like to see 
> whether I can skip having yet another annotation for this. 
>  
> Also another way might be the use of executionAdvice and then defining two 
> advices and combining them together for the two pointcuts. That way I guess I 
> can use the getMethodArgs() from ProceedingJoinPoint.
>  
> So is there any way to use the args() to achieve this? 
>  
> Regards
> Sina
>  
>  
>  
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@eclipse.org <mailto:aspectj-users@eclipse.org>
> To change your delivery options, retrieve your password, or unsubscribe from 
> this list, visit
> https://www.eclipse.org/mailman/listinfo/aspectj-users 
> <https://www.eclipse.org/mailman/listinfo/aspectj-users>_______________________________________________
> aspectj-users mailing list
> aspectj-users@eclipse.org
> To change your delivery options, retrieve your password, or unsubscribe from 
> this list, visit
> https://www.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@eclipse.org
To change your delivery options, retrieve your password, or unsubscribe from 
this list, visit
https://www.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to