Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

developerWorks Community:

  • Close [x]

Web services programming tips and tricks: Using SOAP headers with JAX-RPC

Create and process information transferred in the header portion of a SOAP message

Andre Tost (atost@us.ibm.com), Senior Certified IT Specialist, IBM Software Group
Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible. You can contact Andre at atost at us.ibm.com.

Summary:  In this article, Andre Tost examines ways to create and process information that is transferred in the header portion of a SOAP message. Specifically, he looks at how this can be done in applications that are built using the JAX-RPC standard, which is how most, if not all, Java applications will provide and consume Web services.

Date:  07 Oct 2003
Level:  Intermediate

Activity:  58723 views
Comments:  

The SOAP header

Like any good messaging protocol, SOAP defines the concept of a message header. It is an optional part of any SOAP message. If it exists, the header contains information about the message, or about the context in which the message is sent, or basically whatever the creator of the message thought was a good idea to put there instead of the actual body of the message. Obviously, both the sender and the receiver of the message need to agree on its format.

I could spend this entire article on the discussion about what kind of data is appropriate to be put into the header instead of the body. The most commonly used example is security information and, in fact, there is a specification (WS-Security) describing how to store userid and password information or other authentication credentials in the SOAP header.

However, in this article, I will focus on the programming side of things and show you how to deal with SOAP header fields, both from a client and server side perspective. To keep the example as simple as possible, I will use the good old "Stockquote" example, that is, a Web service returning a stock quote.


SOAP headers and WSDL

As mentioned above, if two applications exchange SOAP messages with headers, they have to agree on the data format of these headers. Naturally, the description of this format goes into the WSDL definition for the Web service. One decision you have to make is whether the data that is stored in the SOAP header is part of your functional, or business interface. In other words, is the header information part of your port type (that is, included in the input or output message of an operation), or is it not? We will assume here for now that it is. This means that it is not only defined in the SOAP binding, but also part of the port type, namely in the <getLastSellPriceRequest> message.

WSDL allows you to define SOAP header fields for input and/or output messages separately. For this example, we will assume that you want to pass along a timestamp field with the request message, to allow measuring response times of the service, for example. Again, the focus here is not on what you send in the header and why, but how it is done.

Listing 1 shows an extract of the WSDL definition file (you can find a download link for the complete example in the Resources section).


Listing 1. Example WSDL definition with SOAP header field

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://soapheader.ibm.com" ...>
  <wsdl:types>
    <schema ...>
      <element name="getLastSellPrice"> 
         <complexType> 
           <sequence>
            <element name="ticker" nillable="true" type="xsd:string" />
           </sequence>
         </complexType>
      </element>
      <element name="getLastSellPriceResponse">
         <complexType>
           <sequence>
             <element name="getLastSellPriceReturn" type="xsd:float" />
           </sequence>
         </complexType>
      </element>
      <element name="quote_timestamp" type="xsd:dateTime" />
  </schema>
  </wsdl:types>
  <wsdl:message name="getLastSellPriceRequest">
    <wsdl:part name="parameters" 
               element="intf:getLastSellPrice"/>
    <wsdl:part name="request_header" 
               element="intf:quote_timestamp"/>
  </wsdl:message>
  <wsdl:message name="getLastSellPriceResponse">
    <wsdl:part name="parameters"  
               element="intf:getLastSellPriceResponse"/>
  </wsdl:message>
  <wsdl:portType name="StockService">
    <wsdl:operation name="getLastSellPrice">
      <wsdl:input name="getLastSellPriceRequest" 
                  message="intf:getLastSellPriceRequest"/>
      <wsdl:output name="getLastSellPriceResponse" 
                   message="intf:getLastSellPriceResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="StockServiceSoapBinding" 
                type="intf:StockService">
    <wsdlsoap:binding style="document"
                    transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getLastSellPrice">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="getLastSellPriceRequest">
        <wsdlsoap:header message="intf:getLastSellPriceRequest"
                         part="request_header" use="literal"/>
        <wsdlsoap:body use="literal" parts="parameters"/>
      </wsdl:input>
      <wsdl:output name="getLastSellPriceResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="StockServiceService">
    ...
  </wsdl:service>
</wsdl:definitions>

The most interesting part of this WSDL definition is highlighted in bold. The SOAP bindings, in the <input> element, contain both a <header> and a <body> element, defining which message parts are transferred in the header and which in the body. In this case, the timestamp goes into the header.


The service implementation

Now you want to provide an implementation of the service described above. I choose JAX-RPC as the server side model, so that you have a standardized Java application hosting the service. There are several options in mapping the header information, so let's look at each of them in a bit more detail.

JAX-RPC message handlers

The JAX-RPC specification describes the concept of message handlers. A server side message handler can intercept a request message before it reaches the Web service, or it can intercept a response message before it is sent back to the requestor. More than one message handler can be invoked for a service, leading to a so called "handler chain". Which handlers are invoked for a service is configurable, but can also be set programmatically. I will cover a much more detailed explanation and examples for JAX-RPC handlers in a separate article in the future.

A SOAP header often contains "out-of-band" information. This is information that is not directly part of the business functionality of a service, and thus should not be passed into the service implementation. A JAX-RPC message handler can extract SOAP header fields from an incoming message, or add new headers to an outgoing message, without the actual service implementation even knowing about it.

Listing 2 shows an example message handler retrieving and removing SOAP header fields from an incoming message (again, you can find a link to the complete source in the Resources section).


Listing 2. JAX-RPC message handler example
public class SOAPHeaderHandler extends javax.xml.rpc.handler.GenericHandler {
   ...
   public boolean handleRequest(MessageContext arg) {
	if (arg instanceof SOAPMessageContext) {
		SOAPMessageContext context = (SOAPMessageContext)arg;
		try {
			SOAPHeader header = 
           context.getMessage().getSOAPPart().getEnvelope().getHeader();
			Iterator headers = 
                        header.extractHeaderElements
                        ("http://schemas.xmlsoap.org/soap/actor/next");
			while (headers.hasNext()) {
				SOAPHeaderElement he = 
                                 (SOAPHeaderElement)headers.next();
				// process the retrieved header element here
			}	
		} catch (SOAPException x) {
			// insert error handling here
		}
	}
	return true;
   }
}

Parameter on the Service Endpoint Interface (SEI)

Another option for dealing with a SOAP header field is to simply add it to the Service Endpoint Interface (SEI) of the Web service. This allows you to process the SOAP header directly in the service implementation.

Exactly how the header information in the WSDL definition is mapped into a parameter on the SEI depends on your JAX-RPC implementation, because the specification does not define how this is done. For example, your SEI for the WSDL example above may look like Listing 3 (generated by WebSphere Studio Application Developer 5.1).


Listing 3. Service Endpoint Interface example

public interface StockService_SEI extends java.rmi.Remote {

  public float getLastSellPrice(
                 String ticker, 
                 java.util.Calendar request_Header) 
       throws java.rmi.RemoteException;
}

Most likely, your JAX-RPC implementation will generate header information as part of the SEI if the header is defined as a message part in the port type. In the example shown in Listing 1 above, the "request_header" part is included in the <getLastSellPriceRequest> message and hence is mapped to a parameter on the SEI.

The ServiceLifecycle interface

This option also provides header information to the service implementation class. However, it does not show up on the endpoint interface, but must be explicitly retrieved from the message. You can view this as a mix of the two earlier methods: the content of the SOAP header is retrieved from the passed MessageContext not in a message handler, but in the service implementation class.

To get access to the SOAP message, your service implementation class must implement the javax.xml.rpc.server.ServiceLifecycle interface. It contains a method called init(), which is used by the JAX-RPC engine to pass a context object into the service implementation instance. In the actual service method, you can use code that is similar to that described earlier for the message handler to retrieve the content of the header. Listing 4 shows what that looks like for our example.


Listing 4. The ServiceLifecycle interface
public class StockService implements 
                      StockService_SEI, javax.xml.rpc.server.ServiceLifecycle
{
   ServletEndpointContext ctx;

   public float getLastSellPrice(String ticker, java.util.Calendar request_Header) {
	float f = 0.0f;
	if (ctx != null) {
		ServletContext servletContext = ctx.getServletContext();

            SOAPMessageContext mc = 
                   (SOAPMessageContext)ctx.getMessageContext();
		// process SOAP header as shown in the message handler
	}
	// further processing...
	return f;
   }
	
   public void init(Object arg0) throws ServiceException {
	if (javax.xml.rpc.server.ServletEndpointContext.class.isInstance(arg0))
		ctx = (ServletEndpointContext) arg0;
   }



Client side processing

Processing of SOAP handlers on the client side is not much different from what I have discussed above for the server side. You can directly use the first two options.
JAX-RPC defines the concept of message handlers for clients just like for servers, and they are normally defined in the client Web service deployment descriptor.
The other option is to add the SOAP header fields as parameters on the client side stub, so that they can directly be passed as part of the invocation. Respectively, they can also be returned as a result of the invocation, if the header fields are defined for the output message.


Summary

SOAP header fields can be created and processed by JAX-RPC applications in a variety of ways. They can be part of the business interface of a service, or be "hidden" and processed by message handlers. In either case, the service contract, that is, the WSDL definition, must define any SOAP header fields that are used. Specific JAX-RPC engines will support all or a subset of the options described above.



Download

NameSizeDownload method
ws-tipjaxcode.zip HTTP

Information about download methods


Resources

About the author

Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible. You can contact Andre at atost at us.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=87013
ArticleTitle=Web services programming tips and tricks: Using SOAP headers with JAX-RPC
publish-date=10072003
author1-email=atost@us.ibm.com
author1-email-cc=