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)));
精彩评论