Spring adding two elements to the SOAP header

2019-05-26 11:36发布

问题:

My question basically is the same as this question.
I don't have enough reputation to add a comment to the OP's question. Please help

The problem I'm having is:
The SOAP web service I'm trying to call requires the header to have two elements, one containing basic header data and another with synchronisation specific data, the header that's required looks like this :

<header>
  <initHeader>
    <requestID></requestId>
    <...some more elements>
  </initHeader>
 <syncHeader>
    <appId></appId>
    <dateTime></dateTime>
    <event></event>
 </syncHeader>
</header>

When generating the header using WebServiceMessageCallback (specifically during the transformation shown below), I get this:

"ERROR: 'The markup in the document following the root element must be well-formed.'"

    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.transform(new StringSource(soapHeaderStr), ((SoapMessage) message).getSoapHeader().getResult());

The issue here is that the transformer expects all the elements in the header to be under one root element. But here, the header has two.

I changed the header data like this(below) and the transformer does not complain.

    <header>
      <myRootelement>
      <initHeader>
        <requestID></requestId>
        <...some more elements>
      </initHeader>
     <syncHeader>
        <appId></appId>
        <dateTime></dateTime>
        <event></event>
     </syncHeader>
     </myRootelement>
    </header>

According to the above mentioned question, the OP had solved this problem by addigng a dummy root element as above and then removing it just before transforming it into the header.

I want to know how this removal of the dummy root elements is possible ? Something like this may be ? http://technology.amis.nl/2011/05/16/how-to-remove-unwanted-soap-header-elements-in-jax-ws/
I'm not quite sure how to remove a root element while keeping its children intact.

回答1:

Managed to solve the problem, Here's how :

Instead of marshalling the two elements into StringResult objects and then trying to add them to the header using a the Transformer like this :

StringResult stringResult = new StringResult();
webServiceTemplate.getMarshaller().marshal(element, stringResult);
StringSource headerSource = new StringSource(stringResult.toString());
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(headerSource, soapHeader.getResult());

You can marshal the two elements directly into the soap header like this :

webServiceTemplate.getMarshaller().marshal(element1,soapHeader.getResult());
webServiceTemplate.getMarshaller().marshal(element2,soapHeader.getResult());

The marshaller mentioned here is a "org.springframework.oxm.jaxb.Jaxb2Marshaller" The element 1 and 2 above are the JAXB elements created using the generated Object factory class.

With this approach, there is no need to add dummy root elements.

Hope this helps someone out there, and thanks to Grigori.G for pointing me in the right direction !