ShowTable of Contents
The Web Experience Factory (WEF) 8.0 release contains an enhancement to the web service call builders that gives you an option to define a global JAX-WS handler class. This handler makes it possible for models to intercept and process the inbound and outbound SOAP envelopes associated with each web service call initiated from the models. Most customers will never need to use this feature. However, there are scenarios where it can be very useful:
- The logging functionality of the web service call builders does not meet your needs. The global JAX-WS handler can be used to implement a custom logging solution.
- You need advanced security handling than is not implemented by the web service call builders. The JAX-WS handler can be used to modify the outbound and inbound SOAP envelopes (or the JAX-WS engine's behavior) to implement the required security strategy.
- The message exchange with the web service end-point involves SOAP attachments. The web service call builders do not provide any support for handling attachments therefore you would use a JAX-WS handler to process any outbound or inbound attachments.
This sample demonstrates how to implement a JAX-WS handler and integrate it with models that make web service calls. The sample includes a web service consumer model and a JAXWS handler. The sample also includes and a simple web service built using standard Java EE 5 / JAX-WS 2.0 techniques; this service is called by the consumer model.
this sample is not intended to provide guidance on how to implement specific JAX-WS handler features nor how to implement web service end-points using Java EE. The code in this sample is only intended to illustrate how a JAX-WS handler can be used with the web service call builders.
Installation and Configuration Instructions
The sample consists of two files: a WEF archive and a deployable WAR file. The archive contains the web service consumer model and JAX-WS handler. The WAR file contains the web service end-point called by the consumer. Each file must be installed before the sample can be run.
Prerequisites: Software Versions
1. The archive must be imported into a WEF 8 or later project. Releases earlier than version 8 do not contain the required JAX-WS handler support.
2. The WAR file must be deployed on an application server that supports Java EE 5 or later.
Step 1: Deploy the Web Service WAR
The WAR contains a simple implementation of a calculator service. The service was implemented using standard Java EE and JAX-WS techniques. The WAR can be deployed as-is using the administration tool for your application server. It is beyond the scope of this document to provide detailed instructions on how to deploy the WAR file. However, you must ensure that the web service contained in the WAR is registered with the server and that the WAR is started before advancing to the next step.
Step 2: Retrieve the WSDL and Schema
The deployed WAR does not contain a WSDL file or schemas for the calculator service; these files are generated on-demand by the server's JAX-WS infrastructure. The steps to retrieve the WSDL vary depending upon the application server and how the WAR was deployed, but in general, you use the application server's administration tool to retrieve the WSDL and schemas. For example, the following administration page from WebSphere 7.0 allows you to download a ZIP file containing the generated WSDL and schemas. This command group is available on the page you see after clicking on the deployed WAR in the Enterprise Applications view.
Clicking on Publish WSDL files displays the following page.
Clicking on the link will download the ZIP.
Save the files to a well know place on the file-system since they will be needed in a subsequent step.
Step 3: Import the WEF Archive
Select a WEF 8 project into which the sample archive files will be imported. Right-click on the project name and select “Import”, then proceed through the steps to import the archive files.
Do not deploy the project if asked to do so by Designer.
Step 4: Set the Java Build Path
The handler contains references to JAX-WS 2.0 classes and WebSphere web service security utilities. Designer must be configured with a 1.6 JRE to resolve the JAX-WS classes. To resolve the WebSphere classes you'll need to modify Designer's Java build path. In the WebSphere 7.0 test environment used to develop this sample the required JAR is located at
The sample can be run without the WebSphere classes; simply comment out or remove the WebSphere class references in the handler implementation and rebuild the project.
Step 5: Configure override.properties
Open WEB-INF/config/override.properties in the selected project and add the following line.
This property defines the JAX-WS handler to be used for all web service calls in the project.
The class was imported into the project during step 3.
Step 6: Update the WSDL and Schema File(s)
This step is not strictly required; the imported archive contains a copy of the WSDL and schema generated by the test server used to validate the sample. However, since the application server in your environment may generate a different WSDL or schema file(s) it makes sense to use the files downloaded in step 2. Copy the WSDL and schema file(s) into the WEB-INF/wsdl/samples
directory in the selected WEF 8 project. If you don't see these files in Designer after the copy, then refresh the project.
Step 7: Update the Consumer Model
Open /models/samples/JaxWsHandlerSample.model then open the Web Service Multiple Operation builder for editing. Update the WSDL URL input to point at the WSDL file you copied into the project. Press Fetch WSDL, then Enable All Operations. The Operations input should now contain “add”, “divide”, “multiple”, and “subtract”. If you don't see these operations or you encounter an error while fetching the WSDL, then there is a good chance there is something wrong with the WSDL or schema file(s) copied into the project. Finally, press Apply. The builder is configured to call the calculator web service deployed in step 1.
Step 8: Deploy the WEF 8 Project
Deploy the WEF 8 project so that the new override.properties configuration is put into service.
After the project is deployed you are ready to run the sample.
Running the Sample
Run JaxWsHandlerSample.model from Designer and you should see the following page. This page is generated by the Web Service Multiple Operation builder which has been
configured to create a test page for the web service end-point.
Click on the “add” link to display the input page (shown below on the left) for the service operation. Enter appropriate integer values and press “Submit” to invoke the service. The result page will be displayed as shown below on the right. This confirms that the web service and consumer model are working as designed.
The handler configured in step 5 is invoked when the SOAP request and response messages are processed by the JAX-WS engine. In the application server's System.out log you will see text similar to the following. The first 4 lines are from CalculatorRequestHandler while the next 4 lines are from a second JAX-WS handler configured for the service end-point implementation (this second handler is contained in the WAR deployed in step 1).
[4/19/12 17:35:36:609 EDT] 0000004e SystemOut O -----
[4/19/12 17:35:36:609 EDT] 0000004e SystemOut O sampleContent
[4/19/12 17:35:36:609 EDT] 0000004e SystemOut O text/plain
[4/19/12 17:35:36:610 EDT] 0000004e SystemOut O Client says hello!
[4/19/12 17:35:38:365 EDT] 0000004c SystemOut O -----
[4/19/12 17:35:38:365 EDT] 0000004c SystemOut O 133251465469.1334871338336.IBM.WEBSERVICES@localhost
[4/19/12 17:35:38:365 EDT] 0000004c SystemOut O text/plain
[4/19/12 17:35:38:365 EDT] 0000004c SystemOut O Server says hello!
In the test environment used to develop this sample the WEF 8 project and the WAR file containing the web service were both deployed to the same application server therefore the output from the 2 handlers are grouped together.
Sample Design Highlights
Now that you have successfully run the sample we can briefly explore its key design points.
One Handler Per Project
Only one JAX-WS handler can be configured for a project and this single handler will be called for all web service requests initiated by the project's models. This makes it trivial to intercept all web service requests without having to modify individual web service call builders in existing models. For new models this may appear to be a limitation, but there are simple techniques that can be used to achieve per-model application of the handler. One such technique in used in this sample and will be covered in more detail below.
Open BaseJaxWsHandler.java and you will see that it implements a public WEF interface named WebAppAccessConsumer. This interface marks the handler as requiring the WebAppAccess instance of the model calling the web service. At run-time the model instance is automatically injected into the handler so that it can fetch variables or invoke model actions required to process the SOAP envelopes. The injection occurs each time a web service call is made and is performed before the JAX-WS engine calls any of the handler methods. This behavior is key to the per-model technique mentioned earlier.
If you use this feature in a handler you must not use the injected WebAppAccess after the request has completed. WebAppAccess instances are invalidated after a request and attempting to use one to access model artifacts will result in an exception.
JaxWsHandlerSample.model contains a set of methods—their name begins with SOAP—that are used to implement some of the handler's functionality. When the handler is called by the JAX-WS engine to process an envelope the handler uses the injected WebAppAccess instance to inspect the model for the presence of the methods. If a method is found in the model, then it is called as part of the envelope's processing. Thus a model is able to control which handler functions are applied to the web service calls it initiates; this is how the permodel technique mentioned earlier is implemented.
The following sequence of high-level steps is performed as part of a web service call initiated by a model.
- A model action is executed as part of a request and this action eventually calls a data service implemented by a web service call builder.
- A new instance of the handler is created and the web service builder code injects the model's WebAppAccess instance into the handler, passes the service input XML to the JAX-WS engine, then calls the JAX-WS engine to perform the actual web service request.
- The JAX-WS engine transforms the service input XML into a SOAP envelope and calls the handler to process the outbound envelope.
- The handler uses the injected WebAppAccess instance to inspect the model and determine if it contains one or more of the marker methods. If so, then those methods are called as part of the outbound envelope's processing.
- The handler returns and the JAX-WS engine makes the HTTP request to the web service.
- The web service responds with a SOAP envelope.
- The JAX-WS engine calls the handler again, but this time passing in the response envelope it received from the web service.
- The handler again uses the injected WebAppAccess instance to inspect the model and call any marker methods as part of the response envelope's processing.
- The handler returns control to the JAX-WS engine which processes the envelope.
- The JAX-WS engine returns the SOAP envelope to the web service builder code which then extracts the result XML and returns control to the model.
- The model continues to process the request, typically displaying the result XML.
- The request completes and the WebAppAccess instance injected into handler is invalidated.
The sample handler is split into a base class and a derived class that contains knowledge of the marker methods used in the sample model. The base class contains a method (not called in the sample as configured) that illustrates how WebSphere's security classes can be used to implement a custom security strategy.
If you have a web service that understands USERNAMETOKEN security, then you can modify the sample to enable USERNAMETOKEN generation and call this web service. The required steps are:
- Enable the SOAP_getUserName and SOAP_getPassword methods in the sample model.
- Modify these methods to return an appropriate user name and password for the web service being called.
- Disable the other marker methods; it's unlikely the web service is configured to receive and return SOAP attachments.
- Point the Web Service Multiple Operations builder as the WSDL for web service.
The model can now be run. If you encounter errors because of the USERNAMETOKEN, then check the implementation of the addUsernameToken method in the handler's base class.
The code may need to be modified to generate the USERNAMETOKEN using different parameters (such as including a nonce or a timestamp).