Spring-WS endpoints document literal wrapping/unwrapping

1.3k views Asked by At

I am integrating with a system that expects us to consume WS-I 1.1 document/literal wrapped messages. We have a working solution but it appears like there could be a simpler way to deal with payload wrapping/unwrapping.

I have an endpoint that as follows:

@Endpoint
public class FooEndpoint
{

  @Autowired
  private FooService FooService;

  @PayloadRoot(localPart = "Foo", namespace = "http://foo/service")
  @ResponsePayload
  public JAXBElement<FooAcknowledgementType> Foo(
        @RequestPayload JAXBElement<FooRequestType> requestElement)
  {
    FooRequestType request = requestElement.getValue();
    FooAcknowledgementType response = FooService.Foo(request);

    // TODO: Find a better solution with the wrapped response
    return new JAXBElement<FooAcknowledgementType>(new QName(
          "http://foo/service", "FooAcknowledgement"),
          FooAcknowledgementType.class, null, response);
  }
}

and a WSDL which defines the contract is like:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:tns="http://foo/service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://www.w3.org/2000/09/xmldsig#" xmlns:ns1="http://foo/schema"
  name="Foo" targetNamespace="http://foo/service">
  <wsdl:types>
    <xsd:schema xmlns:s="http://foo/schema" targetNamespace="http://foo/service">
      <xsd:import namespace="http://foo/schema" schemaLocation="foo_types.xsd" />
      <xsd:element name="Foo" type="s:FooRequestType" />
      <xsd:element name="FooAcknowledgement" type="s:FooAcknowledgementType" />
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="FooRequest">
    <wsdl:part name="parameter" element="tns:Foo" />
  </wsdl:message>
  <wsdl:message name="FooAcknowledgement">
    <wsdl:part name="parameter" element="tns:FooAcknowledgement" />
  </wsdl:message>
  <wsdl:portType name="FooPortType">
    <wsdl:operation name="Foo">
      <wsdl:input message="tns:FooRequest" />
      <wsdl:output message="tns:FooAcknowledgement" />
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="FooBinding" type="tns:FooPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="Foo">
      <soap:operation soapAction="http://foo/serviceFoo" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="Foo">
    <wsdl:documentation>Foo web service</wsdl:documentation>
    <wsdl:port name="FooService" binding="tns:FooBinding">
      <soap:address location="http://localhost:8080/foo/services/Foo" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

I've generated jaxb objects from the foo_types.xsd schema as referenced in the endpoint class above.

The issue is that when we receive soap messages in document/literal wrapped style the soap body payload would look like

<x:Foo>
  <!-- elements from s:FooRequestType -->
</x:Foo>

and we are expected to respond with a soap body payload like

<x:FooAcknowledgement>
  <!-- elements from s:FooAcknowledgementType -->
</x:FooAcknowledgement>

Is there anyway that the Spring-WS can handle this out of the box? We can consume and produce compliant messages with the code as it is but it seems like this might not be the right way to go about it as this style is not referenced in the spring docs at http://docs.spring.io/spring-ws/site/reference/html/tutorial.html#tutorial.xsd

1

There are 1 answers

0
anger On BEST ANSWER

The solution for us was to add the namespace and element name to the @XmlRootElement annotation via our jaxb bindings.xml, E.g.

<jaxb:bindings node="xs:complexType[@name='fooType']">
  <annox:annotate target="class">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="FooAcknowledgement" namespace="http://foo/service"/>
  </annox:annotate>
</jaxb:bindings>