Java SOAP Header

SOAP (Simple Object Access Protocol) is a messaging protocol used for exchanging structured information in web services. SOAP headers are a way to include additional information in a SOAP message beyond the body content. In this article, we will explore how to work with SOAP headers in Java.

SOAP Header Overview

A SOAP header is an optional part of a SOAP message and typically contains information such as security credentials, routing information, or other metadata. The header is sent before the actual SOAP body and is used to provide additional context for the message.

SOAP headers can be defined in a WSDL (Web Services Description Language) file, which describes the structure and functionality of the web service. The WSDL file specifies the message format, including the SOAP header elements.

Working with SOAP Headers in Java

To work with SOAP headers in Java, we can use various libraries and frameworks such as JAX-WS, Apache CXF, or Spring Web Services. In this article, we will focus on using JAX-WS, which is a standard Java API for creating web services.

Step 1: Create a SOAP Web Service

First, let's create a simple SOAP web service using JAX-WS. We will create a service that calculates the sum of two numbers.

// SumWebService.java
import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public class SumWebService {

    @WebMethod
    public int sum(int a, int b) {
        return a + b;
    }
}

Step 2: Generate WSDL File

Next, we need to generate a WSDL file for our web service. We can use the wsgen tool provided by JAX-WS to generate the WSDL.

$ wsgen -cp . com.example.SumWebService

This command generates the WSDL file (e.g., SumWebService.wsdl) in the current directory.

Step 3: Define SOAP Header in WSDL

Now, let's modify the WSDL file to define a SOAP header. We will add a <soap:header> element inside the <wsdl:message> element.

<!-- SumWebService.wsdl -->
<definitions ...>
    ...
    <message name="SumRequest">
        <part name="header" element="tns:HeaderElement"/>
        <part name="body" element="tns:SumRequestBody"/>
    </message>
    
    <message name="SumResponse">
        <part name="body" element="tns:SumResponseBody"/>
    </message>
    
    <portType name="SumWebServicePortType">
        <operation name="sum">
            <input message="tns:SumRequest"/>
            <output message="tns:SumResponse"/>
        </operation>
    </portType>
    
    <binding name="SumWebServiceBinding" type="tns:SumWebServicePortType">
        <soap:binding style="document" transport="
        <operation name="sum">
            <soap:operation soapAction=""/>
            <input>
                <soap:header message="tns:SumRequest" part="header" use="literal"/>
                <soap:body parts="body" use="literal"/>
            </input>
            <output>
                <soap:body parts="body" use="literal"/>
            </output>
        </operation>
    </binding>
    
    ...
</definitions>

In this example, we have defined a custom SOAP header element called HeaderElement and included it in the SumRequest message using the <soap:header> element.

Step 4: Implement SOAP Handler

To process the SOAP header, we need to create a SOAP handler. A SOAP handler intercepts incoming and outgoing SOAP messages and allows us to manipulate the headers and body.

// CustomSOAPHandler.java
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;

public class CustomSOAPHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public Set<QName> getHeaders() {
        return null; // We don't define any headers explicitly
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean isOutbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        
        if (!isOutbound) {
            try {
                SOAPMessage soapMessage = context.getMessage();
                SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
                SOAPHeader soapHeader = soapEnvelope.getHeader();
                
                if (soapHeader != null) {
                    // Process SOAP header
                    // ...
                }
            } catch (SOAPException e) {
                e.printStackTrace();
            }
        }
        
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    @Override
    public void close(MessageContext context) {
        // Clean up resources
    }
}

In this example, we implement the SOAPHandler interface and override its methods. In the handleMessage method, we check if the SOAP message is inbound or outbound. If it is