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
We need to bring this handler into play. That means configuring CXF to use this handler.
If we now start our server:
Now If I were to test the code:
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 runtimeI decided to add one such Handler to the wsdl first example:
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.
publicclass CrazyHandler implements LogicalHandler<LogicalMessageContext> {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."
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");
}
}
We need to bring this handler into play. That means configuring CXF to use this handler.
<jaxws:endpoint id="randomWs"As seen here we have associated a handler with our endpoint.
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>
If we now start our server:
1431 [localhost-startStop-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory -Thus for our endpoint an inner bean instance was created of type CrazyHandler and associated with it.
Creating instance of bean 'com.ws.service.samplews_ns.handler.CrazyHandler#17e7f88'
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);For this request, I decided to watch the behavior from the logs. Here are some observations:
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());
- 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] - 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 - 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 - 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] - 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
Thus the call lands up in our handler's handleMessage for a second time.
- 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 - 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]
- 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.