开发者

Sonic ESB class hierarchy causing unwanted multiple invocations of aspect

开发者 https://www.devze.com 2023-02-06 17:37 出处:网络
Howdy.I\'m trying to use AspectJ with Sonic ESB to intercept calls to the service() method of any custom ESB service.That means I don\'t know the type of the service class in advance; I only know that

Howdy. I'm trying to use AspectJ with Sonic ESB to intercept calls to the service() method of any custom ESB service. That means I don't know the type of the service class in advance; I only know that it implements interface XQServiceEx. The implemented service() method is invoked by the Sonic container every time a JMS message arrives at the service endpoint. However, the container has a somewhat complex internal structure, and I'm getting three invocations of my advice for each inbound message. (I hope my terminology isn't too far off.)

My aspect looks like this:

package com.ncr.eai.esb.aop;

import com.sonicsw.xq.XQService;
import com.sonicsw.xq.XQServiceEx;
import com.sonicsw.xq.XQServiceContext;
import com.sonicsw.xq.XQServiceException;
import com.ncr.eai.esb.*;

aspect XQServiceAspect {
 final String id = "O : ";

 pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) :
     call(void XQService.service(XQServiceContext)) &&
     target(svc) &&
     target(com.sonicsw.xq.XQService) &&
//     within(com.ncr..*) &&
     args(ctx);

    before(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) {
     System.out.println(id + "Entering XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
    }

    void around(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) {
     System.out.println(id + "In the around() advice before call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
     proceed(svc, ctx);
     System.out.println(id + "In the around() advice after call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
     }


    after(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx) returning: serviceCall(svc, ctx) {
     System.out.println(id + "Returned from XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
    }
}

The output looks like this:

O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain@c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl@97e765 com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain@c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl@97e765 com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper@195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper@195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect@1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect@1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
  >>>> Inside of the actual service() method!
  >>>> About to exit the actual service() method!
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect@1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect@1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper@195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper@195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper@19c705e com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain@c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl@97e765 com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain@c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl@97e765 com.ncr.eai.esb.aop.XQServiceAspect@d8ce8f

I know the results of my experimentation are kind of hard to read here, but each call to service() results in a sequence of three calls from com.sonicsw.xqimpl.service.XQServiceChain, com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServ开发者_开发技巧iceWrapper, and com.ncr.eai.esb.ServiceFromAspect. I only want to see one call per message, meaning one call to service(). And I don't know in advance what the name of the third class will be. This test is being run with a custom service named com.ncr.eai.esb.ServiceFromAspect, but there may be dozens of other services that implement XQServiceEx, and I don't want to have to hard-code them; they need to be discovered at run-time. I tried to add the commented out within(com.ncr..*) phrase, but using that prevented the pointcut from working at all. I also tried to exclude com.sonicsw packages with things like !within(com.sonicsw..*), but that also stopped all pointcuts from working.

As far as deployment goes, I've got this aspect jarred up, and I'm doing load-time weaving by adding javaagent to the container command-line. The overall strategy is working, but I have spent longer than I want to admit trying to construct a pointcut that works as desired.

How do I get only one call per message?

Any "advice" appreciated!

Thanks, Lee Grey, SOA Architect NCR


It looks like a decorator pattern going on in there. All you probably need is to use cflowbelow() to avoid advising decorated calls.

 pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) :
     call(void XQService.service(XQServiceContext)) &&
     target(svc) &&
     target(com.sonicsw.xq.XQService) &&
     args(ctx) &&
     !cflowbelow(call(void XQService.service(XQServiceContext)));
0

精彩评论

暂无评论...
验证码 换一张
取 消