Also see this blog entry for information on CXF interceptors and alternative simpler methods of modifying SOAP requests and responses.
This tutorial shows various usages of JAX-WS handlers and how they can be attached to CXF-based SOAP web services and clients. We'll be attaching the handlers to the DoubleIt web service and client. The finished tutorial source code can be cloned or downloaded from GitHub.
The design and behavior of JAX-WS handlers are primarily defined in Chapter 9 of the JAX-WS Specification, with additional relevant material in Sections 4.2.1, 5.3, and 10. Some main features of handlers:
The Metro-based JAX-WS handler samples (in its WSDL-first and Java-first versions) provide a good example of using Handlers to log incoming and outgoing SOAP messages, from both the client and web service provider. This code can be used as-is with CXF. We'll expand on these examples by modifying the SOAP message, processing the SOAP request without the web service being activated, and using the MessageContext to pass property values between (client or service) endpoint and handlers. The following list of handler capabilities shows some of the functionality covered:
JAX-WS 2.1 Spec Reference | Functionality | How Demonstrated Below |
---|---|---|
9.1.1 | Logical Handlers may manipulate the message payload (SOAP body in the case of SOAP binding.) |
The client logical handler will change the value of the SOAP request to a MAX_VALUE MessageContext property set by the SOAP client, if its value exceeds that property. |
9.1.1 | Protocol Handlers may access and change protocol specific aspects (e.g., the SOAP header) of a message. |
The client SOAPHandler will add two elements to the SOAP header. |
9.3.2.1 | For the request-response MEP [Message Exchange Pattern], returning false from a Handler's |
Not implemented here; code demonstrating this already available in this CXF sample. |
9.3.2.1 | For the request-response MEP, throwing a SOAPFaultException from a Handler's |
The client- and service-side logical handlers will return a SOAPFault error back to the client if there is an attempt to double the number 20 or 30, respectively. In both cases, the Service Endpoint Interface (SEI) implementation will not be activated. |
9.4.1 | MessageContext properties are scoped either |
During service-side inbound processing, the service SOAPHandler will read the two elements added by the client SOAPHandler and add those values to the MessageContext, one with HANDLER and the other with APPLICATION scope. The SEI implementation will be able to read only the latter. |
9.4.1.1 | Tables 9.2 - 9.4 of the JAX-WS Specification lists several standard message context properties. Some are applicable only if HTTP is being used and/or the web service is being deployed in a servlet container. These properties appear to all have |
HandlerUtils.java has methods that will output MessageContext property values. It can be called from within the endpoints and handlers as desired. |
Steps:
Download and deploy the DoubleIt web service on Tomcat. This is just a check to make sure the DoubleIt web service and client is working properly on your machine before adding the handlers. Best not to proceed unless the SOAP calls from that tutorial can be made successfully.
Create the HandlerUtils.java class to output the MessageContext properties. Although this class would ideally be kept in just one place, to avoid architectural complexity for this tutorial we can add this class to both the client
and service
packages. Note this class is not exhaustive in the MessageContext properties it reports on--it does not output the HTTP header values and Servlet properties, for example.
Create the client-side handlers. For tutorial convenience, I'm nesting both handlers within a single class. Place the following ClientHandlers.java class in the Client submodule's client
package:
Update the SOAP client to use the handlers. Replace the WSClient.java file from Step #9 of the DoubleIt tutorial with the below class.
Create the service-side handlers. I could not nest the service-side handlers into a single class as I could above for the client handlers, CXF, when reading the service-side handler chain configuration file, complains about not being able to instantiate the handlers unless they are declared standalone. At any rate, add the following classes to the service
package:
Update the web service provider to use the handlers. Replace the DoubleItPortTypeImpl.java file from Step #6 of the DoubleIt tutorial with the below class. The handler configuration file (handlers.xml) is declared and the WebServiceContext is injected so the web service can read any APPLICATION-scoped properities created by the web service's handlers.
Attach the JAX-WS handlers to the web service provider. We'll now need to create the handlers.xml file declared in the previous step. This configuration file's XSD is defined in the JSR 181 Specification (Version 2.0, Appendix B).
For the required location of the handler chain configuration file, CXF follows the JSR 181 standard (see Sect. 4.6.1) in that relative paths are evaluated from the location of the compiled class, and absolute paths (e.g., "/handlers.xml") with respect to the base of the classpath. In the sample I used an absolute path for @HandlerChain and placed the config file in a new service/src/main/
directory. Per Maven's Standard Directory Layout rules, files in the resources
directory are automatically placed by Maven in the classpath root (i.e., WEB-INF/classes
) when it creates the web service WAR file.
Redeploy the web service and test that the client and service provider handlers are working. After redeploying the service, run the SOAP client again to follow the output of the four SOAP calls made. The client side handler output you should see on the console window as before. As for the web service provider, if you're using Linux, the handler output should be viewable from $CATALINA_HOME/logs/catalina.{date}.out
; if Windows, the console window that is hosting Tomcat. You may wish to comment out some of the printMessageContext calls made above to reduce the output. Also note because of the MAX_VALUE limitation of 200 enforced by the client-side logical handler, the web service query doubling 300 will top out at 400.
Notes:
You may find design and/or performance benefits using CXF-specific interceptors instead of JAX-WS defined handlers. For example, within CXF, SOAP handlers can carry a performance penalty, as SAAJ loads the entire message as a DOM object into memory, as CXF's Dan Kulp noted.
See the Additional Resources section of my CXF interceptor article for simpler CXF-specific ways of modifying SOAP requests and responses.
Posted by Glen Mazza in Web Services at 07:00AM Feb 25, 2018 | Comments[0]