flyx
flyx

Reputation: 39638

JAX-WS: How to add additional XML namespaces to a SOAP response

I have a webservice autogenerated with JAXWS. This webservice is a simulator for the actual implementation and is used for testing. A response from the actual implementation looks like this:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:nsc:RFIDCommandEnum="http://tempuri.org/nsc:RFIDCommandEnum.xsd"
        xmlns:nsc="http://xxx.com/schema/yyy/ltu-tcs"
        xmlns:nse:DeviceStateEnum="http://tempuri.org/nse:DeviceStateEnum.xsd"
        xmlns:nse="http://xxx.com/schema/yyy"
        xmlns:nsl="http://xxx.com/wsdl/yyy/ltu/tcs"
        xmlns:nst="http://xxx.com/wsdl/yyy/tcs/ltu">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <nsl:setDataResponse>
            <result>...</result>
        </nsl:setDataResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The same response by the simulator looks like this:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getDataResponse xmlns:ns2="http://xxx.com/wsdl/yyy/ltu/tcs">
            <result>...</result>
       </ns2:getDataResponse>
    </S:Body>
</S:Envelope>

Now I already know that nested namespaces like xmlns:nsc:RFIDCommandEnum will cause problems, so I need to get the simulator deliver these namespaces like the actual implementation does. After some googling, I figured out I should do something like this:

@javax.xml.bind.annotation.XmlSchema(
    namespace = "http://xxx.com/schema/yyy/ltu-tcs",
    xmlns = {
        @javax.xml.bind.annotation.XmlNs(prefix = "nsc:RFIDCommandEnum", namespaceURI = "http://tempuri.org/nsc:RFIDCommandEnum.xsd"),
        @javax.xml.bind.annotation.XmlNs(prefix = "nsc", namespaceURI =  "http://xxx.com/schema/epm/ltu-tcs"),
        @javax.xml.bind.annotation.XmlNs(prefix = "nse:DeviceStateEnum", namespaceURI = "http://tempuri.org/nse:DeviceStateEnum.xsd"),
        @javax.xml.bind.annotation.XmlNs(prefix = "nse", namespaceURI = "http://xxx.com/schema/yyy"),
        @javax.xml.bind.annotation.XmlNs(prefix = "nsl", namespaceURI = "http://xxx.com/wsdl/yyy/ltu/tcs"),
        @javax.xml.bind.annotation.XmlNs(prefix = "nst", namespaceURI = "http://xxx.com/wsdl/yyy/tcs/ltu")
    },
    elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.xxx.yyy.tcs.simulator;

But it doesn't work. The package com.xxx.yyy.tcs.simulator is where the simulating implementation class of the webservice is located. I figured I probably need to apply these annotations to the autogenerated classes that represent the XML content, but cannot change these, because they are also used in production code and I don't want to pollute that with my namespaces.

So I tried to derive from my StandardResponse class which represents the <result> element:

package com.xxx.yyy.tcs.simulator;

// ...

@WebService(name = "LTU_for_TCS", targetNamespace = "http://xxx.com/wsdl/yyy/ltu/tcs")
public class LTU_for_TCS_Impl implements LTUForTCS {
    // ...

    public static final class NamespacePollutedStandardResponse extends StandardResponse {
        private NamespacePollutedStandardResponse(final Application application,
                                                  final ResultCodeEnum code,
                                                  final String message) {
            super(application, code, message);
        }
    }

    @WebMethod
    @WebResult(name = "result", partName = "result")
    @Override
    public GetLTUDataResponse getData(
            @WebParam(name = "application", partName = "application")
            Application application) {
        logger.info("getData");
        return new NamespacePollutedStandardResponse(getApplicationHeader(),
            ResultCodeEnum.SUCCESS,
            "This is the LTU simulator!");
    }
}

However, this still doesn't change the response I get from the simulator. Now I'm wondering: Can I change the namespace list of StandardResponse at all? Why doesn't it work like this - NamespacePollutedStandardResponse is part of the simulator package, so it should get the namespaces defined in the XmlSchema attribute, shouldn't it? And is there a way to add the namespaces to the root element instead (I only found information how to add it to one of the payload elements)?

Upvotes: 2

Views: 5756

Answers (2)

vsingh
vsingh

Reputation: 6749

You can add namespace to the root element

@XmlRootElement(namespace ="http://mynamespace.com")

Upvotes: 1

flyx
flyx

Reputation: 39638

I solved the problem by writing a javax.servlet.Filter that adds the additional namespaces to the response. This is not very pretty, but it's a lot easier to create an answer as close as possible to the original this way.

Upvotes: 2

Related Questions