Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Examining a destructive read in an aspect

Glad you got something working.  I just want to make sure we're on the
same page using within():

pointcut hasIncoming() : call(boolean
XQServiceContext.hasNextIncoming()) && !within(com.sonicsw..*);
This means I want to match calls to XQServiceContext.hasNextIncoming
that are not made from types in the com.sonicsw package or
subpackages. (i.e. I assume you want to match those made from the
aspect, in com.ncr..*, this pointcut ought to match those)

pointcut getIncoming(XQServiceContext ctx) : call(XQEnvelope
XQServiceContext.getNextIncoming()) && target(ctx) &&
(within(XQService) || within(XQServiceEx));
This means I want to match calls to getNextIncoming where the target
is an instance of XQServiceContext and the call is being made from
XQService or XQServiceEx.  Remember, within is about lexical matching,
unlike target which is an instanceof test.  So if the calls are made
from a subtype of XQService or XQServiceEx they will not match this
pointcut.

I'm almost tempted to say to create some basic before():call(...)
advice and in the advice body print the
thisEnclosingJoinPointStaticPart - that will give us precisely where
it thinks the calls are coming from and within's can then be coded for
those.

cheers
Andy

On 3 February 2011 13:09, Grey, Lee <Lee.Grey@xxxxxxx> wrote:
> These seem to be getting the job done:
>
>    pointcut hasIncoming() :
>        call(boolean *.hasNextIncoming()) &&
>        withincode(void *.service(XQServiceContext));
>
> And
>
>    pointcut getIncoming() :
>        call(XQEnvelope *.getNextIncoming()) &&
>        withincode(void *.service(XQServiceContext));
>
> Any feedback on these?  Also, can you provide an example of how to use within() properly?  I've had no success with specifying a wildcarded package expression that will work for me.
>
> Thanks,
> Lee
>
> -----Original Message-----
> From: aspectj-users-bounces@xxxxxxxxxxx [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Grey, Lee
> Sent: Thursday, February 03, 2011 2:00 PM
> To: aspectj-users@xxxxxxxxxxx
> Subject: Re: [aspectj-users] Examining a destructive read in an aspect
>
> My if() strategy is not working on more complex processes, because there seem to be nested calls to hasNextIncoming() and getNextIncoming() which make it impossible for me to know when to clear my cached XQEnvelope.  I was ending up with either a null or an infinite loop, so I'm going to have to try to make the pointcut work.
>
> Here are my logs from a run where two calls to getNextIncoming() came back-to-back, causing the first one to succeed and the second one to retrieve null (because I clear the ThreadLocal after returning it):
>
>
> [XQServiceAspect] In the around() advice before call to void com.sonicsw.xq.XQService.service(XQServiceContext)
> In beforeCallToService: calling hasNextIncoming:  <-- call to the real Sonic method In beforeCallToService: hasNextIncoming returned true In beforeCallToService: getNextIncoming returned com.sonicsw.xqimpl.envelope.Envelope@14cbd50  <-- call to the real Sonic method In beforeCallToService: stored in tlEnv: com.sonicsw.xqimpl.envelope.Envelope@14cbd50
> [XQServiceAspect] beforeCallToService returned true env=com.sonicsw.xqimpl.envelope.Envelope@14cbd50
> msg=com.sonicsw.xq.connector.jms.XQJMSMessage@120f4c8
> cmd=null
> [XQServiceAspect] analyzeMessage returned true, calling service() [XQServiceAspect] In the around() advice before call to boolean com.sonicsw.xqimpl.service.XQServiceChain.XQServiceContextWrapper.hasNextIncoming()
> [XQServiceAspect] In the around() advice after call to boolean com.sonicsw.xqimpl.service.XQServiceChain.XQServiceContextWrapper.hasNextIncoming()
> result=true
>
> [XQServiceAspect] In the around() advice before call to XQEnvelope com.sonicsw.xqimpl.service.XQServiceChain.XQServiceContextWrapper.getNextIncoming()
> [XQServiceAspect] In the around() advice after call to XQEnvelope com.sonicsw.xqimpl.service.XQServiceChain.XQServiceContextWrapper.getNextIncoming()
> result=com.sonicsw.xqimpl.envelope.Envelope@14cbd50  <-- returned the XQEnvelope as expected
>
> [XQServiceAspect] In the around() advice before call to XQEnvelope com.sonicsw.xq.service.xcbr.context.impl.InvocationContextImpl.getNextIncoming()
> [XQServiceAspect] In the around() advice after call to XQEnvelope com.sonicsw.xq.service.xcbr.context.impl.InvocationContextImpl.getNextIncoming()
> result=null  <-- because of a second call to getNextIncoming(), the ThreadLocal is now empty
>
> [11/02/03 13:15:24] ID=dev_ESBCore (severe) [Dispatch] Exception calling service dev.CBR: message rejected
> [11/02/03 13:15:24] ID=dev_ESBCore (severe) Trace follows...
> java.lang.NullPointerException
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.debug.DebugServiceInterceptor.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$AjcClosure1.run(<Unknown>:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081proceed(XQServiceAspect.java:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081(XQServiceAspect.java:72)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.callService(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.doHandleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQDispatcher.onMessage(Unknown Source)
>        at com.sonicsw.xqimpl.endpoint.container.EndpointContextContainer.onMessage(Unknown Source)
>        at com.sonicsw.xq.connector.jms.JMSEndpoint$JMSEndpointListener.onMessage(Unknown Source)
>        at progress.message.jimpl.Session.deliver(Session.java:2952)
>        at progress.message.jimpl.Session.run(Session.java:2358)
>        at progress.message.jimpl.Session$SessionThread.run(Session.java:2743)
> com.sonicsw.xq.XQServiceException:
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.debug.DebugServiceInterceptor.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$AjcClosure1.run(<Unknown>:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081proceed(XQServiceAspect.java:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081(XQServiceAspect.java:72)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.callService(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.doHandleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQDispatcher.onMessage(Unknown Source)
>        at com.sonicsw.xqimpl.endpoint.container.EndpointContextContainer.onMessage(Unknown Source)
>        at com.sonicsw.xq.connector.jms.JMSEndpoint$JMSEndpointListener.onMessage(Unknown Source)
>        at progress.message.jimpl.Session.deliver(Session.java:2952)
>        at progress.message.jimpl.Session.run(Session.java:2358)
>        at progress.message.jimpl.Session$SessionThread.run(Session.java:2743)
> Caused by...
> java.lang.NullPointerException
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.xcbr.XCBRService.service(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xq.service.cbr.CBRService.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.debug.DebugServiceInterceptor.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.intercept(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service_aroundBody0(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQServiceChain$AjcClosure1.run(<Unknown>:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081proceed(XQServiceAspect.java:1)
>        at com.ncr.eai.esb.aop.XQServiceAspect.ajc$around$com_ncr_eai_esb_aop_XQServiceAspect$1$f783e081(XQServiceAspect.java:72)
>        at com.sonicsw.xqimpl.service.XQServiceChain.service(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.callService(Unknown Source)
>        at com.sonicsw.xqimpl.service.ServiceMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.doHandleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.ProcessMessageHandler.handleMessage(Unknown Source)
>        at com.sonicsw.xqimpl.service.XQDispatcher.onMessage(Unknown Source)
>        at com.sonicsw.xqimpl.endpoint.container.EndpointContextContainer.onMessage(Unknown Source)
>        at com.sonicsw.xq.connector.jms.JMSEndpoint$JMSEndpointListener.onMessage(Unknown Source)
>        at progress.message.jimpl.Session.deliver(Session.java:2952)
>        at progress.message.jimpl.Session.run(Session.java:2358)
>        at progress.message.jimpl.Session$SessionThread.run(Session.java:2743)
>
>
> My new strategy is to continue to return the same message from getNextIncoming() and only clear it if hasNextIncoming() returns nothing.  I'm concerned that may result in an infinite loop, but perhaps if I can get the pointcut to distinguish between calls within my advice and calls from Sonic classes, maybe I can make it works.
>
> I tried adviceexecution(), but that didn't seem to work as expected.
>
> Why won't a simple expression like !within(com.sonicsw..*) work?  Is my syntax wrong?  Shouldn't I be able to distinguish between their calls from the container and my own from within my aspect using something that simple?
>
> Thanks,
> Lee
>
> -----Original Message-----
> From: aspectj-users-bounces@xxxxxxxxxxx [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Andy Clement
> Sent: Thursday, February 03, 2011 1:28 PM
> To: aspectj-users@xxxxxxxxxxx
> Subject: Re: [aspectj-users] Examining a destructive read in an aspect
>
> I think you really should be able to single out the ones you are interested in at compile time.  I probably would have used
> withincode() to scope exactly the one I'm interested in:
>
> // Select the call to getNextIncoming() made within the method
> XQServiceEx.service()
> pointcut getIncoming(XQServiceContext ctx) : call(XQEnvelope
> XQServiceContext.getNextIncoming()) && target(ctx) && withincode(* XQServiceEx.service());
>
> But I can't immediately see why your within() (which is just a broader form of withincode really) isn't working for you.
>
> Andy
>
> On 3 February 2011 10:07, Grey, Lee <Lee.Grey@xxxxxxx> wrote:
>> I think I have a solution, but I'm not sure whether it violates a best
>> practice (or is just beneath a good aspect developer):
>>
>> I created a ThreadLocal<Boolean> to determine which invocations should
>> be advised and which should not:
>>
>>  private static final ThreadLocal<Boolean> tlAdvise = new
>> ThreadLocal<Boolean>() {
>>   @Override protected Boolean initialValue() { return true; }  }; Then
>> I set the ThreadLocal to false when I want to run the real methods and
>> to true when I want them to be short-circuited with my own advise:
>>
>>     ...
>>   tlAdvise.set(false);
>>   if( ctx.hasNextIncoming() ) {    // call the real Sonic code
>>    System.out.println("In beforeCallToService: hasNextIncoming
>> returned true");
>>    XQEnvelope env = ctx.getNextIncoming();    // call the real Sonic
>> code
>>    tlAdvise.set(true);
>>     ...
>> My pointcuts use if:
>>
>>     pointcut hasIncoming() :
>>      execution(boolean XQServiceContext.hasNextIncoming()) &&
>>      if(tlAdvise.get());
>> and
>>
>>     pointcut getIncoming() :
>>      execution(XQEnvelope XQServiceContext.getNextIncoming()) &&
>>      if(tlAdvise.get());
>> Is this a brute-force solution to something that could be done far
>> more elegantly and efficiently with just a little more pointcut
>> knowledge?  Is there anything that makes this a bad idea?
>>
>> Thanks for your insights,
>> Lee
>> ________________________________
>> From: aspectj-users-bounces@xxxxxxxxxxx
>> [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Grey, Lee
>> Sent: Wednesday, February 02, 2011 11:45 PM
>> To: aspectj-users@xxxxxxxxxxx
>> Subject: Re: [aspectj-users] Examining a destructive read in an aspect
>>
>> I've done what you suggested, and I think it would work fine, except
>> that I can't get the pointcut right for the two calls I need to
>> intercept.  I seem to be getting all or nothing.
>>
>> What pointcut would intercept the calls to ctx.hasNextIncoming() and
>> ctx.getNextIncoming() when they come from the actual
>> XQServiceEx.service() method but would still make the real,
>> unadulterated calls when made from inside my aspect?
>>
>> My failed attempts include
>>
>> pointcut hasIncoming() : call(boolean
>> XQServiceContext.hasNextIncoming()) && !within(com.sonicsw..*);
>>
>> pointcut getIncoming(XQServiceContext ctx) : call(XQEnvelope
>> XQServiceContext.getNextIncoming()) && target(ctx) &&
>> (within(XQService) || within(XQServiceEx));
>>
>> and other unsuccessful flailing.  I find creating successful pointcuts
>> to be black magic.
>>
>> Thanks,
>> Lee
>> ________________________________
>> From: aspectj-users-bounces@xxxxxxxxxxx
>> [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Ramnivas
>> Laddad
>> Sent: Monday, January 31, 2011 8:50 PM
>> To: aspectj-users@xxxxxxxxxxx
>> Subject: Re: [aspectj-users] Examining a destructive read in an aspect
>>
>> You could do something along the following lines:
>> 1. In your before advice read destructively as needed and store away
>> the result 'env' in a ThreadLocal.
>> 2. Advise ctx.getNextIncoming() with an around advice to return the
>> stored result (and don't call proceed() in it).
>> -Ramnivas
>>
>> On Mon, Jan 31, 2011 at 2:59 PM, Grey, Lee <Lee.Grey@xxxxxxx> wrote:
>>>
>>> I've been working on intercepting the service() method invocation in
>>> a Sonic ESB container.  I had just started to write my before()
>>> advice when the bad news dawned on me.  Just about every ESB
>>> service() method starts with the following...
>>>
>>>    public void service(XQServiceContext ctx) throws
>>> XQServiceException {
>>>         XQEnvelope env = null;
>>>         while (ctx.hasNextIncoming()) {
>>>             env = ctx.getNextIncoming();
>>>             if (env != null) {
>>>                 XQMessage msg = env.getMessage(); That call to
>>> ctx.getNextIncoming() is a destructive read that returns a different
>>> XQEnvelope every time it's called.  The problem is that I need to
>>> evaluate the contents of the message that comes from
>>> ctx.getNextIncoming() in my before() advice.  What that means is that
>>> the call to
>>> ctx.getNextIncoming() in the service() method is not going to get the
>>> message, because the before() advice already got it.
>>>
>>> Now I'm wondering if there's a way to put an aspect around
>>> ctx.getNextIncoming() to make it deliver the message again.  Or if I
>>> can somehow clone ctx so that I can read the cloned message in
>>> before() and then read it from the real XQServiceContext object in service().
>>> XQServiceContext doesn't offer any way to peek or browse, and it
>>> doesn't have a method to put a message, either.
>>>
>>> I would imagine I'm not the first person to run into this kind of
>>> issue with AOP before.  I'm hoping that there's a pattern to address it.
>>>
>>> Thanks,
>>> Lee Grey
>>> _______________________________________________
>>> aspectj-users mailing list
>>> aspectj-users@xxxxxxxxxxx
>>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>>>
>>
>>
>> _______________________________________________
>> aspectj-users mailing list
>> aspectj-users@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>>
>>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>


Back to the top