[jboss-user] [JBoss Web Services CXF] - XTS tests broken in AS trunk after switch to CXF stack in 3.3.0

Andrew Dinn do-not-reply at jboss.com
Wed Jun 9 12:18:37 EDT 2010


Andrew Dinn [http://community.jboss.org/people/adinn] replied to the discussion

"XTS tests broken in AS trunk after switch to CXF stack in 3.3.0"

To view the discussion, visit: http://community.jboss.org/message/547157#547157

--------------------------------------------------------------
> Andrew Dinn wrote:
> 
> . . .
> Now this is rather weird because the message with action  http://fabrikam123.com/InitiatorPortType/Response http://fabrikam123.com/InitiatorPortType/Response is never sent to the Participant service implemented by class ParticipantPortTypeImpl. Not surprisingly given the action definition it is sent to service Initiator implemented by class InitiatorPortTypeImpl. So, mmy code is sending messages to one service and they are being delivered to another service. Of course when running on trunk with native a few weeks back this worked fine. Also when I last tested it on a CXF build some months back it worked fine.
> I will try to debug the code path through to AbstractInvocationHandler.getImplMethod() in order to see why it is looking at the wrong class and get back with any info I can find.

I debugged a case where the message has been misdirected and it appears that the delivery process goes awry in class org.jboss.wsf.stack.cxf.AbstractInvoker inside method _invokeInternal(Exchange exchange, Object o, WrappedMessageContext ctx). The problem appears to relate to the use of an InheritableThreadLocal. Here is the code:

> private Object _invokeInternal(Exchange exchange, Object o, WrappedMessageContext ctx)
>    {
>       BindingOperationInfo bop = exchange.get(BindingOperationInfo.class);
>       MethodDispatcher md = (MethodDispatcher)exchange.get(Service.class).get(MethodDispatcher.class.getName());
>       Method m = md.getMethod(bop);
>  
> 
>       Object[] params = NO_ARGS;
>       List<Object> paramList = null;
>       if (m.getParameterTypes().length != 0)
>       {
>          if (o instanceof List<?>)
>          {
>             paramList = CastUtils.cast((List<?>)o);
>             params = paramList.toArray();
>          }
>          else
>          {
>             params = new Object[]{o};
>          }
>       }
>  
> 
>       Endpoint ep = EndpointAssociation.getEndpoint();
>       InvocationHandler invHandler = ep.getInvocationHandler();
>  
> 
>       Invocation inv = invHandler.createInvocation();
>       InvocationContext invContext = inv.getInvocationContext();
>       inv.getInvocationContext().addAttachment(WebServiceContext.class, getWebServiceContext(ctx));
>       invContext.addAttachment(MessageContext.class, ctx);
>       inv.setJavaMethod(m);
>       inv.setArgs(params);
>  
> 
>       Object retObj = null;
>       try
>       {
>          invHandler.invoke(ep, inv);
>          . . .
> 
The debugger shows the following:
> ctx { javax.xml.ws.wsdl.service --> {http://fabrikam123.com}InitiatorService,
>       javax.xml.ws.wsdl.port --> {http://fabrikam123.com}InitiatorPortType,
>       org.apache.cxf.request.uri --> /interop11/ATInitiatorService
>       . . . }
> 
> m = "public void com.jboss.transaction.txinterop.webservices.atinterop.sei.InitiatorPortTypeImpl.response()"
> 
> ep = org.jboss.wsf.framework.deployment.DefaultEndpoint at 18138d9 {
> 
>   name = jboss.ws:context=interop11,endpoint=Interop11ATParticipantService
>   shortName = Interop11ATParticipantService
>   urlPattern = /ATParticipantService
>   targetBean = com.jboss.transaction.txinterop.webservices.atinterop.sei.ParticipantPortTypeImpl
>    . . . }
So, the problem appears to be that the call to EndpointAssociation.getEndpoint() is returning the wrong endpoint. Now this is strange because it is a very simple function:

>   private static final ThreadLocal<Endpoint> endpoint = new InheritableThreadLocal<Endpoint>();
> 
>    public static Endpoint getEndpoint()
>    {
>       return endpoint.get();
>    }
> 
Now this is a one way message which, as can be seen in the exception trace, is being dispatched by a worker pool thread. The handoff to this thread happens in the interceptor chain when one of the interceptors determines that this is a one way message. The interceptor queues the partially sent message and returns early so as not to block the JaxWS client. This can be seen in ContextUtils$1.run in the stack trace which is defined inside method ContextUtils.rebaseResponse.

>                     if (retrieveAsyncPostResponseDispatch(inMessage)) {
>                         //need to suck in all the data from the input stream as
>                         //the transport might discard any data on the stream when this 
>                         //thread unwinds or when the empty response is sent back
>                         DelegatingInputStream in = inMessage.get(DelegatingInputStream.class);
>                         if (in != null) {
>                             in.cacheInput();
>                         }
>                         
>                         // async service invocation required *after* a response
>                         // has been sent (i.e. to a oneway, or a partial response
>                         // to a decoupled twoway)
>                         
>                         // pause dispatch on current thread ...
>                         inMessage.getInterceptorChain().pause();
> 
>                         // ... and resume on executor thread
>                         getExecutor(inMessage).execute(new Runnable() {
>                             public void run() {
>                                 inMessage.getInterceptorChain().resume();
>                             }
>                         });


As you can see the message is queued to an executor obtained from the message. When I execute getExecutor(inMessage) in the debugger it does indeed return an executor. What is more when I execute the code in getExecutor it does indeed appear to be obtained from the Initiator service not the Participant service. However, when I looked at the threads in the Executor thread pool something is very wrong. The inheritedThreadLocalMap field in some of the threads has the Initiator port as the endpoint while in other threads it has the Participant port as the endpoint. So, something is resetting the thread local endpoint of Initiator service executor  threads.

I don't know exactly why or where this is happening but I will try tracing calls to getEndpoint and setEndpoint in order to see if I can idenitfy what is doing the reset.

--------------------------------------------------------------

Reply to this message by going to Community
[http://community.jboss.org/message/547157#547157]

Start a new discussion in JBoss Web Services CXF at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2046]

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jboss-user/attachments/20100609/6d1e8d25/attachment-0001.html 


More information about the jboss-user mailing list