Search code examples
javaxmlsoapjax-wsxml-namespaces

move xml namespace declarations to root element with jax-ws annotations


I'm trying to generate an xml payload with jax-ws and it's not working out. The server expects all namespaces to be in the envelope tag. For example:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://somewhere.namespace1.com" xmlns:ns2="http://somewhere.namespace2.com">

is what I need, while

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">

is what I have.

jax-ws generates a payload like

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns1:Element1 xmlns:ns1="http://somewhere.namespace1.com" xmlns:ns1="http://somewhere.namespace2.com">
            <ns2:Element2>value</ns2:Element2>
        </ns1:Element1>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

but I need

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://somewhere.namespace1.com" xmlns:ns2="http://somewhere.namespace2.com">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns1:Element1>
            <ns2:Element2>value</ns2:Element2>
        </ns1:Element1>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I have tried putting package-info.java files with the @javax.xml.bind.annotation.XmlSchema and I'm able to change the prefix but not move the actual namespace declaration from a child node to the root node. For example, I can (apparently?) define all the namespaces I need in the envelope with

@javax.xml.bind.annotation.XmlSchema(
    elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
    xmlns = {
            @XmlNs(
                prefix = "ns1",
                namespaceURI="http://somewhere.namespace1.com"),
            @XmlNs(
                prefix = "ns2",
                namespaceURI="http://somewhere.namespace2.com"),
    }
)

But then in the package-info.java where Element1.java and Element2.java are, I don't want the namespaces defined there. I've tried

@javax.xml.bind.annotation.XmlSchema(
    namespace="http://schemas.xmlsoap.org/soap/envelope/",
    location = ""
)

but it doesn't work.

Has anyone else had a similar problem? I'm sure it's just a question of annotations but I haven't been able to figure it out.


Solution

  • I solved this problem by making the call with Spring's WebServiceTemplate#sendAndReceive(String, WebServiceMessageCallback, WebServiceMessageExtractor<T>) where in the second parameter (the callback) I manually added the namespaces that I needed to be in the header. For example something like

    wsResponse = this.webServiceTemplate.sendAndReceive(uri,
            (webServiceMessage) -> {
                ...
                SoapMessage soapMessage = (SoapMessage) webServiceMessage;
                ...
                final SoapEnvelope envelope = soapMessage.getEnvelope();
                headerNamespaces.forEach(envelope::addNamespaceDeclaration);
                ...
            }, this.responseExtractor);