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.defaultendpo...@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]

_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to