I also don't know how you can bind the complete set of arguments for
any/all method signatures.  It might be a decent enhancement-request -
others on the list may know whether access this has been previously
proposed.

For completeness, I believe that the fix for
https://bugs.eclipse.org/bugs/show_bug.cgi?id=67592 resulted in the
array-copy for args, ensuring all advice sees the same args at the
join-point (provided of course that a state-changing method is not
called on one of the array members).

Brett

On 15 April 2013 12:42, Jay Roberts <puda...@gmail.com> wrote:
> Hi Brett,
>
> Thanks for the links and the response.  I had come across that discussion, 
> but it still didn't meet my needs.
>
> I understand the logic of getArgs returning the original passed args, those 
> semantics makes sense.
>
> But what I can't do is have something like  args(..) in the pointcut and bind 
> to the entire set of arguments.  We don't need just one or two of them, we 
> need all of them brought into scope and bound then so that downstream aspects 
> may act upon what changes we may make.
>
> The usage of our aspects are across a wide array of method signatures and we 
> want to examine all of them via reflection, etc, making decisions about what 
> to do for each based upon a number of factors.  We don't know which of the 
> params will need modification, replacement in advance, so we would have to 
> write a whole bunch of point cuts to try to cover this.
>
> Something that would let us bind to all the arguments as, say, an object array
>
> @Around("execution( @anno * *(..) && args(..)")
> public Object myAdvice(ProceedingJoinPoint jp, Object[] args){
>      …….
> }
>
> Or, and it would be useful, the ability for an aspect to access, at least in 
> a read only way, the current state of the closure - if it needs to be 
> modified, jp.proceed(Object[]) already takes care of that.  That would 
> actually allow trailing aspects to understand not just what arguments were 
> originally passed to the method, but what ones the closure is going to 
> actually execute on and do this comprehensively for all arguments.  It seems 
> like that is very relevant information for certain aspects, at least in my 
> limited experience.
>
> So I appreciate sending on those links, but they really don't help with this 
> situation.
>
> I did come up w/a very clunky workaround for our stuff, but I'm thinking that 
> maybe I'll go back and write an aspect on JoinPointImpl that exposes the 
> information that we need in our downstream aspects and allows us to have 
> concise code for upstream aspect.
>
> Again, thanks for the response, I think AspectJ is terrifically cool, I've 
> used it on and off over the years, great stuff.
>
> Best,
>
> Jay Roberts
>
> Seems like a natural extension of
> On Apr 14, 2013, at 10:00 PM, Brett Randall <javabr...@gmail.com> wrote:
>
>> Jay,
>>
>> This was asked not so long ago on the list - it should be added to a
>> FAQ if it is not already there, and perhaps justifies a JavaDoc
>> clarficiation.
>>
>> See also:
>>
>> http://aspectj.2085585.n4.nabble.com/Modifying-parameters-in-more-than-one-aspect-providing-around-advice-td4650584.html
>> http://stackoverflow.com/questions/12843998/modifying-parameters-in-more-than-one-aspect-providing-around-advice
>>
>> The behaviour you are seeing is expected, but perhaps not obvious.
>> They key is that JoinPoint.getArgs() only returns a _copy_ of the
>> _original_ method arguments at the join-point.  So modifying them in a
>> prior aspect and/or reading them in a subsequent aspect will not do
>> what you want.
>>
>> As mentioned by Alexander on the other thread and per his
>> code-example, you cannot use getArgs() to do what you want - you need
>> to instead bind arguments using args() in your pointcut, and then
>> access the arguments via the formal parameter instead of getArgs(),
>> e.g. in your FirstAspect:
>>
>> @Pointcut("execution(@SomeAnnotation * *.foo(..)) && args(myArg)")
>> public void anyFoo(Object myArg) {}
>>
>> @Around("anyFoo(myArg)")
>> public Object doAdvice(ProceedingJoinPoint jp, Object myArg) throws 
>> Throwable{
>>  // ...
>>  if (myArgs instanceof BadArg) {
>>    System.out.println("replaced BadArg");
>>    myArg = new GoodArg();
>>  }
>>  return jp.proceed(new Object[] {myArg});
>> }
>>
>> .. then in your SecondAspect, bind myArg in the same fashion to read
>> the replaced argument.  This should make the code work in the way you
>> expect.
>>
>> Brett
>>
>>
>> On 14 April 2013 16:35, Jay Roberts <puda...@gmail.com> wrote:
>>> Hi,
>>>
>>> I have a situation where I have several possibly cascading Around advices 
>>> as simplified below.
>>>
>>> @Aspect
>>> @Precedence(FirstAspect, *)
>>> class FirstAspect{
>>>        @Around("execution(@SomeAnnotation * *.foo(..))")
>>>        public Object doAdvice(ProceedingJoinpoint jp) throws Throwable{
>>>                Object [] args = jp.getArgs();
>>>                for(int i=0;i<args.length : i++){
>>>                        if(args[i] instanceof BadArg){
>>>                                args[i] = new GoodArg();
>>>                        }
>>>                }
>>>                jp.proceed(args);
>>>        }
>>> }
>>>
>>> @Aspect
>>> class SecondAspect{
>>>        @Around("execution(@SomeAnnotation * *(..))")
>>>        public Object doAdvice(ProceedingJoinpoint jp) throws Throwable{
>>>                Object [] args = jp.getArgs();
>>>                // Gets the same args as returned from jp.getArgs() in 
>>> FirstAspect,
>>>                // not the modified ones.
>>>
>>>                …. do something but have BadArg instead of GoodArg…..
>>>
>>>                jp.proceed();
>>>        }
>>> }
>>>
>>> FirstAspect may or may not appear before SecondAspect, SecondAspect is 
>>> narrower.  I traced through the aspectj source and debugger, and I saw that 
>>> both FirstAspect and SecondAspect have the same join point, whose args 
>>> remain the original args passed in the target method call.  The args passed 
>>> in to proceed I see go into state for the AroundClosures and the ones 
>>> modified in FirstAspect do make it to the target method foo.  FirstAspect 
>>> is correctly executing before SecondAspect.
>>>
>>> I also see that JoinPoint.getArgs returns a copy of args rather than a 
>>> reference.  And I've read a whole bunch on the web about binding args 
>>> inside the join point using args.  However, this binding requires some 
>>> name/pattern, and both FirstAspect, SecondAspect match to any method params 
>>> (..).
>>>
>>> So how can I modify things such that downstream aspects of FirstAspect will 
>>> get the modified args passed by FirstAspect to JoinPoint.proceed?  Is there 
>>> a way in the advice matching to bind to args(..) so I can get it as a 
>>> reference in FirstAspect?  Or, can SecondAspect somehow get the 
>>> AroundClosure state so it can look at those rather than JoinPoint.getArgs()?
>>>
>>> In the meantime, I've just setup a globally accessible 
>>> ThreadLocal<Map<JoinPoint, Object[]> variable that aspects (possibly) 
>>> downstream of FirstAspect can lookup modified args and use those if they 
>>> exist rather than the JoinPoint.getArgs().  This is pretty clunky 
>>> workaround for the moment, I feel I am really missing something here.
>>>
>>> Any help would be appreciated.
>>>
>>> Thanks1
>>>
>>> Jay Roberts
>>> _______________________________________________
>>> aspectj-users mailing list
>>> aspectj-users@eclipse.org
>>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>> _______________________________________________
>> aspectj-users mailing list
>> aspectj-users@eclipse.org
>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@eclipse.org
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
aspectj-users@eclipse.org
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to