Move namespace declaration from payload to envelop

2020-07-17 05:04发布

问题:

I just created a web service client using axis and eclipse that does not work with my web service provider. The message created by the web service client looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <enviarMensajeRequest 
       xmlns="http://www.springframework.org/spring-ws/Imk-Zenkiu-Services">
      <usuario>someuser</usuario>
      <clave>somepassword</clave>
      <mensaje>somemessage</mensaje>
      <contacto>
        <buzonSMS>somenumber</buzonSMS>
        <primerNombre>somefirstname</primerNombre>
        <primerApellido>somelastname</primerApellido>
      </contacto>
    </enviarMensajeRequest>
  </soapenv:Body>
</soapenv:Envelope>

I see nothing wrong with the message but my provider insists the message should be:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:imk="http://www.springframework.org/spring-ws/Imk-Zenkiu-Services">
  <soapenv:Body>
     <imk:enviarMensajeRequest>
        <imk:usuario>someuser</imk:usuario>
        <imk:clave>somepassword</imk:clave>
        <imk:mensaje>somemessage</imk:mensaje>
        <imk:contacto>
           <imk:buzonSMS>somenumber</imk:buzonSMS>
           <imk:primerNombre>somefirstname</imk:primerNombre>
           <imk:primerApellido>somelastname</imk:primerApellido>
        </imk:contacto>
     </imk:enviarMensajeRequest>
  </soapenv:Body>
</soapenv:Envelope>

Notice the namespace declaration moving from the enviarMensajeRequest to the soapenv:Envelope and the qualification with imk: on the parameters. I've tried many combinations on the process but my web service, wsdl and xml knowledge is very limited. The provider says that they can't help beyond telling me this. Any ideas? Perhaps a different framework that I can use to create the correct client.

回答1:

Your provider is wrong, the messages are semantically equivalent; yours is unqualified, theirs is qualified. Are you using Axis or Axis2? If you're using Axis, I suggest you switch to Axis2 for a more robust, standards-compliant SOAP stack (both products are bad, but Axis2 is less-bad).

I assume you are creating your client with wsdl2java? If you can't get this tool to generate the message the way you like, then your best bet is to generate the message programmatically. With Axis2, you can do this with the AXIOM API. See this link for some example API usage. Note that with most of the methods, e.g. createOMElement, you optionally pass the namespace prefix. So, if your provider requires it, then you could pass a String containing "imk" as the namespacePrefix parameter.


If you end up doing this programmatically and you are only going to be writing a simple client, then I STRONGLY suggest you abandon the Axis/Axis2 approach and use the JAX-WS stack instead, as it is part of Java since 1.6. The API is cleaner and the documentation is better. For example, following is a very simple client I wrote to send a SOAP request to our JIRA server. The sample code creates both qualified and unqualified elements.

QName port = new QName(endpoint, "subversionsoapservice-v2");
QName serviceName = new QName(endpoint, "ISubversionSoapServiceService");

Service service = Service.create(serviceName);
service.addPort(port, SOAPBinding.SOAP11HTTP_BINDING, endpoint);

Dispatch<SOAPMessage> dispatch = service.createDispatch(port, SOAPMessage.class, Service.Mode.MESSAGE);
MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage request = factory.createMessage();
SOAPBody body = request.getSOAPBody();

SOAPElement reindexRepository = body.addChildElement("reindexRepository", "jira", "http://soap.ext.plugin.jira.atlassian.com");
SOAPElement in0 = reindexRepository.addChildElement("in0");
in0.addTextNode("test");

request.saveChanges();
dispatch.invoke(request);

The XML sent by the client looks like this:

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <jira:reindexRepository xmlns:jira="http://soap.ext.plugin.jira.atlassian.com">
            <in0>test</in0>
        </jira:reindexRepository>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>