Apache CXF client namespace is in element instead of envelope

2.8k views Asked by At

The problem I'm having is with Apache CXF putting the namespace inside the element instead of soap envelope.

I used codegen maven plugin to generate the client code from WSDL.

Here are the namespaces in the WSDL:

              xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
              xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
              xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

When I fire a SOAP request I can see in logs that the following message has been sent:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
    <ns1:userRegistrationRequest xmlns:ns1="http://some.com/namespace1">
        <InputParameter xmlns:ns2="http://some.com/namespace1">
            <ns2:Message>
                <ns2:Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
                <ns2:HashTable>
                    <ns2:Item key="action">
                        <ns2:Value>some_action</ns2:Value>
                    </ns2:Item>
                </ns2:HashTable>
            </ns2:Message>
        </InputParameter>
    </ns1:userRegistrationRequest>
</soap:Body>

The problem is that the Value element was null in my code when I constructed the message, but here it appears with XSI namespace.

What I was expecting to get is something like this (Value element should not be present and XSI should be in the envelope element):

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
    <ns1:userRegistrationRequest xmlns:ns1="http://some.com/namespace1">
        <InputParameter xmlns:ns2="http://some.com/namespace1">
            <ns2:Message>
                <ns2:HashTable>
                    <ns2:Item key="action">
                        <ns2:Value>some_action</ns2:Value>
                    </ns2:Item>
                </ns2:HashTable>
            </ns2:Message>
        </InputParameter>
    </ns1:userRegistrationRequest>
</soap:Body>

Does anyone have an idea how to prevent the CXF from generating that empty Value element and put the namespace inside the soap envelope element?

1

There are 1 answers

1
Milan On

Ok, so to answer my question. There are two aspects of this problem.

First, adding namespaces to the envelope element. It can be done by writting a custom interceptor and registering it in some early phase. Something like this:

import java.util.Map;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;

public class MyInterceptor extends AbstractSoapInterceptor {

    private Map<String, String> nsMap;

    public MyInterceptor(Map<String, String> nsMap) {
        super(Phase.USER_LOGICAL);
        this.nsMap = nsMap;
      }

    public void handleMessage(SoapMessage message) throws Fault {
        message.put("soap.env.ns.map", nsMap); 
        message.put("disable.outputstream.optimization", Boolean.TRUE); 
    }

}

I found the above solution here

Secondly, to remove empty value element an xsd should be changed to that the element has minOccurs="0" and nillable = "false".