Glen Mazza's Weblog

« New OSHA regulation... | Main

https://web-gmazza.rhcloud.com/blog/date/20170611 Sunday June 11, 2017

Switching from SOAP 1.1 to SOAP 1.2 messages

This blog entry shows the steps needed to switch from SOAP 1.1 to SOAP 1.2 formatted messages in your SOAP requests and responses. I'll be showing the modifications necessary for the basic web service tutorial.

The SOAP 1.2 specification is the default SOAP binding for WSDL 2.0, but for the majority of us remaining with WSDL 1.1 the W3C created a reference document to show how SOAP 1.2 messages can defined within WSDL 1.1-based WSDLs. Perhaps the biggest reason to switch to SOAP 1.2 is to take advantage of its enhanced fault code handling. Thankfully, as long as you're using the standard document/literal binding type there are not many WSDL changes needed in upgrading to SOAP 1.2.

Using Wireshark, let's first see what SOAP 1.1 and SOAP 1.2 messages look like over the wire. For CXF, the web service tutorial generates these SOAP 1.1 requests and responses:

POST /doubleit/services/doubleit HTTP/1.1
Content-Type: text/xml;
charset=UTF-8
Accept: */*
SOAPAction: ""
User-Agent: Apache CXF 2.5.1
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection:
keep-alive
Content-Length: 224

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:DoubleIt xmlns:ns2="http://www.example.org/schema/DoubleIt">
            <numberToDouble>10</numberToDouble>
        </ns2:DoubleIt>
    </soap:Body>
</soap:Envelope>

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type:
text/xml;charset=UTF-8
Content-Length: 238
Date: Fri, 20 Jan 20xx 10:33:25
GMT

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:DoubleItResponse xmlns:ns2="http://www.example.org/schema/DoubleIt">
            <doubledNumber>20</doubledNumber>
        </ns2:DoubleItResponse>
    </soap:Body>
</soap:Envelope>

For SOAP 1.2 with CXF:

POST /doubleit/services/doubleit HTTP/1.1
Content-Type:
application/soap+xml; charset=UTF-8
Accept: */*
User-Agent:
Apache CXF
2.5.1
Cache-Control: no-cache
Pragma: no-cache
Host:
localhost:8080
Connection: keep-alive
Content-Length: 222

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Body>
        <ns2:DoubleIt xmlns:ns2="http://www.example.org/schema/DoubleIt">
            <numberToDouble>10</numberToDouble>
        </ns2:DoubleIt>
    </soap:Body>
</soap:Envelope>

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type:
application/soap+xml;charset=UTF-8
Content-Length: 236
Date: Fri, 20 Jan 20XX 14:14:09 GMT

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Body>
        <ns2:DoubleItResponse xmlns:ns2="http://www.example.org/schema/DoubleIt">
            <doubledNumber>20</doubledNumber>
        </ns2:DoubleItResponse>
    </soap:Body>
</soap:Envelope>

For this simple web service call, the main changes of note between SOAP 1.1 and SOAP 1.2 are a different namespace for the SOAP body elements, different Accept headers in the SOAP request and usage of an action parameter in the Content-Type header in SOAP 1.2 instead of a separate SOAPAction HTTP header.

Converting a WSDL-first web service from SOAP 1.1 to SOAP 1.2. Using the WSDL defined for my DoubleIt tutorial, here are the steps I followed:

  1. Add a soap12 namespace declaration to the top-level wsdl:definitions element. (Also good to remove the older SOAP 1.1 namespace declaration, so errors will be returned in case you overlooked converting some elements to the new namespace.)
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    
  2. In the wsdl:binding section, change the namespace prefix of the soap:binding to soap12:binding. The rest of the declaration can remain as-is.
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    

    For each wsdl:binding/wsdl:operation element similarly change the namespace prefix of its soap:operation and soap:body elements:

    <soap12:operation soapAction=""/>
    <soap12:body use="literal"/>
    

    The attributes available for the soap:operation element are explained here for SOAP 1.1 and here for SOAP 1.2. The latter offers a new soapActionRequired attribute to require the action parameter be sent. For my web service, I'm requiring only an empty string to be sent (meaning the web service provider should rely on the SOAP body contents to determine the operation to call), but you may wish to provide URI values in your own WSDLs. One URI naming convention is to concatenate the namespace of the WSDL with the name of the operation (example), so for my DoubleIt operation it would be "http://www.example.org/contract/DoubleIt/DoubleIt".

    Finally, in the wsdl:service/wsdl:port section, update the namespace prefix of the soap:address element:

    <soap12:address location="http://localhost:8080..."/>
    
  3. No change to the build process is necessary as the CXF WSDL2Java Maven plugin will detect the new SOAP bindings in the WSDL and generate a SOAP 1.2-compliant web service provider and client accordingly.

Converting a Java-first web service from SOAP 1.1 to SOAP 1.2.

  1. Add the SOAP12HTTP_BINDING annotation to your web service implementation class:

    import javax.xml.ws.BindingType;
    
    @WebService(targetNamespace = "http://www.example.org/contract/DoubleIt",
                ...)
    @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
    public class MyJavaFirstPortTypeImpl implements MyJavaFirstPortType {
    ...
    
  2. That's it. You can build/deploy the web service and client as usual. Note that CXF's Maven Java2WS plugin has a <soap12/> setting but using it appears to have no practical effect--while it will generate a SOAP 1.2 WSDL locally, unless the @BindingType annotation above is set it will still deploy as a SOAP 1.1 web service. Further, the annotation above alone is sufficient for CXF to deploy a SOAP 1.2-based web service.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.