Quantcast
Channel: Learning the code way
Viewing all articles
Browse latest Browse all 231

Handlers and Interceptors in CXF - Are they related ?

$
0
0
I have been trying out some things in CXF (and also feeling pretty good about it :P ) The other day I needed to modify the message of more than one web service in a common manner. I achieved the same using a CXF interceptor. However another team member did the same task using Handlers. Interestingly Handler is more a part of the JAX-WS vocabulary than Interceptor. So I decided to look at this option too.
What exactly is a handler? 
From jax-ws.java.net site
Handlers are message interceptors that can be easily plugged in  to the JAX-WS runtime 
to do additional processing of the inbound and outbound messages. Handlers are invoked
with a message context that provides methods to access and modify inbound and
outbound messages and to manage a set of properties.
I decided to add one such Handler to the wsdl first example:
publicclass CrazyHandler implements LogicalHandler<LogicalMessageContext> {

privatestaticfinal Logger LOG = Logger.getLogger(CrazyHandler.class.getName());

@Override
publicbooleanhandleMessage(final LogicalMessageContext context) {
LOG.info("call came handleMessage");
returntrue;
}

@Override
publicbooleanhandleFault(final LogicalMessageContext context) {
LOG.info("call came handleFault");
returnfalse;
}

@Override
publicvoidclose(final MessageContext context) {
LOG.info("call came close");
}

}
The class implements a Logical Handler. The javax.xml.ws.handler.LogicalHandler instances "are protocol-agnostic and cannot change any protocol-specific parts (like headers) of a message. Logical handlers act only on the payload of the message."
We need to bring this handler into play. That means configuring CXF to use this handler.
<jaxws:endpoint id="randomWs"
implementor="com.ws.service.samplews_ns.SampleServiceOperationsPortTypeImpl"
wsdlLocation="random.wsdl" address="randomService">
<jaxws:handlers>
<bean class="com.ws.service.samplews_ns.handler.CrazyHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
As seen here we have associated a handler with our endpoint.
If we now start our server:
1431 [localhost-startStop-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory  -
Creating instance of bean 'com.ws.service.samplews_ns.handler.CrazyHandler#17e7f88'
Thus for our endpoint an inner bean instance was created of type CrazyHandler and associated with it.
Now If I were to test the code:
finalString endpointAddress = "http://localhost:8080/Handler/services/randomService";
final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(SampleServiceOperationsPortType.class);
//the SEI
factory.setAddress(endpointAddress);
final SampleServiceOperationsPortType client = (SampleServiceOperationsPortType) factory.create();

final GetRandomRequest randomRequest = new GetRandomRequest();
randomRequest.setName("coolio");
final GetRandomResponse reply = client.random(randomRequest);
System.out.println("Server said: " + reply.getValue());
For this request, I decided to watch the behavior from the logs. Here are some observations:
  1.  When CXF received the request, it created an interceptor chain to handle this request:
    224440 [http-bio-8080-exec-3] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  
    - Chain org.apache.cxf.phase.PhaseInterceptorChain@cce15ab was modified. Current flow:
    receive [PolicyInInterceptor, AttachmentInInterceptor]
    pre-stream [CertConstraintsInterceptor]
    post-stream [StaxInInterceptor]
    read [WSDLGetInterceptor, ReadHeadersInterceptor, SoapActionInInterceptor, StartBodyInterceptor]
    pre-protocol [MEXInInterceptor, MustUnderstandInterceptor]
    pre-protocol-frontend [SOAPHandlerInterceptor, LogicalHandlerInInterceptor]
    post-protocol [CheckFaultInterceptor, JAXBAttachmentSchemaValidationHack]
    unmarshal [DocLiteralInInterceptor, SoapHeaderInterceptor]
    pre-logical [OneWayProcessorInterceptor]
    post-logical [WrapperClassInInterceptor]
    pre-invoke [SwAInInterceptor, HolderInInterceptor]
    invoke [ServiceInvokerInterceptor]
    post-invoke [OutgoingChainInterceptor, StaxInEndingInterceptor]

  2. As seen above, CXF actually used an interceptor to execute the handler. If we look closely, we can see that the PhaseInterceptorChain passes control to the LogicalHandlerInInterceptor in the pre-protocol-frontend phase. This interceptor than invokes all handlers for the inbound flow i.e. incoming request. accordingly our CrazyHandler is invoked and the message is logged.
    ...
    224460 [http-bio-8080-exec-3] DEBUG org.apache.cxf.phase.PhaseInterceptorChain
    - Invoking handleMessage on interceptor org.apache.cxf.jaxws.handler.logical.LogicalHandlerInInterceptor@43e73c9a
    224464 [http-bio-8080-exec-3] DEBUG org.apache.cxf.jaxws.handler.HandlerChainInvoker
    - invoking handlers, direction: inbound
    224470 [http-bio-8080-exec-3] DEBUG org.apache.cxf.jaxws.handler.HandlerChainInvoker
    - invoking handler of type com.ws.service.samplews_ns.handler.CrazyHandler
    224470 [http-bio-8080-exec-3] INFO com.ws.service.samplews_ns.handler.CrazyHandler
    - call came handleMessage

  3. In the invoke phase the ServiceInvokerInterceptor begins the call that eventually lands up at our endpoint:
    224496 [http-bio-8080-exec-3] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  
    - Invoking handleMessage on interceptor org.apache.cxf.interceptor.ServiceInvokerInterceptor@3d38d0ab
    Nov 27, 2013 11:16:35 AM com.ws.service.samplews_ns.SampleServiceOperationsPortTypeImpl random
    INFO: Executing operation random
    com.ws.service.xsd.random_schema.GetRandomRequest@bcf1913
  4. After all the phases associated with the inbound request are processed, CXF creates a separate chain for the response processing:
    224540 [http-bio-8080-exec-3] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  
    - Chain org.apache.cxf.phase.PhaseInterceptorChain@586cc05e was modified. Current flow:
    setup [PolicyOutInterceptor]
    pre-logical [HolderOutInterceptor, SwAOutInterceptor, WrapperClassOutInterceptor, SoapHeaderOutFilterInterceptor]
    post-logical [SoapPreProtocolOutInterceptor]
    prepare-send [MessageSenderInterceptor]
    pre-stream [AttachmentOutInterceptor, StaxOutInterceptor]
    pre-protocol-frontend [SOAPHandlerInterceptor]
    write [SoapOutInterceptor]
    pre-marshal [LogicalHandlerOutInterceptor]
    marshal [BareOutInterceptor]
    post-marshal [LogicalHandlerOutEndingInterceptor]
    write-ending [SoapOutEndingInterceptor]
    pre-stream-ending [StaxOutEndingInterceptor]
    prepare-send-ending [MessageSenderEndingInterceptor]
  5. Here to if we observe there is the pre-marshal phase which includes a LogicalHandlerOutInterceptor. The class is responsible for invoking our handlers for the outbound flow or the response.
    224549 [http-bio-8080-exec-3] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  
    - Invoking handleMessage on interceptor org.apache.cxf.jaxws.handler.logical
    .LogicalHandlerOutInterceptor$LogicalHandlerOutEndingInterceptor@572b0d74
    224554 [http-bio-8080-exec-3] DEBUG org.apache.cxf.jaxws.handler.HandlerChainInvoker
    - invoking handlers, direction: outbound
    224555 [http-bio-8080-exec-3] DEBUG org.apache.cxf.jaxws.handler.HandlerChainInvoker
    - invoking handler of type com.ws.service.samplews_ns.handler.CrazyHandler
    224555 [http-bio-8080-exec-3] INFO com.ws.service.samplews_ns.handler.CrazyHandler
    - call came handleMessage
    Thus the call lands up in our handler's handleMessage for a second time.
  6. Once the chain completes processing the servlet method also ends.
    224560 [http-bio-8080-exec-3] DEBUG org.apache.cxf.transport.servlet.ServletController  
    - Finished servicing http request on thread: Thread[http-bio-8080-exec-3,5,main]
From what we have seen yet we can conclude that
  • Handlers is more generic term defined as a part of the JAX-WS specification. It concerns with filter like behavior for web services.
  • CXF has implemented the above concept of filter like processing with interceptors. It also supports the more generic mechanism of handlers.
  • The implementation of JAX-WS handlers in CXF is achieved using interceptors.
  • This is also clear from the packages. The Handlers and related classes fall within the javax package. The interceptors and related classes land up in the cxf packages and jars.
There is a lot more in this topic. I found this excellent link that further list some more subtle differences between the two methods of processing available with CXF.

Viewing all articles
Browse latest Browse all 231

Trending Articles