My jax-ws webservice client returns only empty objects

I have a third-party web service for which I create a client using wsimport. Each web service call succeeds, but the response object that I return has all its fields equal to zero. Watching the network, I see that on the wire all the XML elements in the response message have values ​​in them, so the object must contain non-zero data. In addition, the client for the same service generated by the old axis1 and called with the same data returns a non-empty response. Any idea what is going on? (If that matters, I use the MOXy implementation of JAXB).

Update . I was able to narrow it down. Wsdl defines an object in its own namespace, for example http://www.acme.com/ws . The answer I get from the service is

 <?xml version="1.0" encoding="UTF-8"?> ... SOAP envelope ... <ns1:opINFOWLResponse xmlns:ns1="http://www.acme.com/ws" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns1:responseINFOWL xsi:type="ns1:responseINFOWL"> <result>6003</result> <ndserr/> <transid>61437594</transid> <descriptionerr>BLAH.</descriptionerr> </ns1:responseINFOWL> </ns1:opINFOWLResponse> ... SOAP closing tags ... 

and not tied to non-empty OpINFOWLResponse , which wraps a non null responseINFOWL object with all fields set to null. Just for fun, I tried to write a couple of lines to unleash the above fragment (after removing SOAP overhead)

 JAXBContext ctx = JAXBContext.newInstance(OpINFOWLResponse.class); Unmarshaller u = ctx.createUnmarshaller(); OpINFOWLResponse o = (OpINFOWLResponse) u.unmarshal(new StringReader(theSnippetAbove)); ResponseINFOWL w = o.getResponseINFOWL(); 

and I get the same result. If I changed the XML above to

 <?xml version="1.0" encoding="UTF-8"?> <ns1:opINFOWLResponse xmlns:ns1="http://www.acme.com/ws" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns1:responseINFOWL xsi:type="ns1:responseINFOWL"> <ns1:result>6003</ns1:result> <ns1:ndserr/> <ns1:transid>61437594</ns1:transid> <ns1:descriptionerr>BLAH.</ns1:descriptionerr> </ns1:responseINFOWL> </ns1:opINFOWLResponse> 

Everything works perfectly. Bummer.

Update (again) . Same behavior with both jaxb-RI and Moxy. Still don't know what happened.

Update (September 9th) . The suggestion below about the incorrect namespace name is interesting, but I assumed that wsimport would be ok. Anyway, this is my package-info.java

 @XmlSchema( namespace = "http://www.acme.com/ws", elementFormDefault = XmlNsForm.QUALIFIED) package it.sky.guidaTv.service.remote; import javax.xml.bind.annotation.XmlSchema; import javax.xml.bind.annotation.XmlNsForm; 

and this is the corresponding part of the responseINFOWL class

 /* * <p>Java class for responseINFOWL complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * &lt;complexType name="responseINFOWL"> * &lt;complexContent> * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * &lt;sequence> * &lt;element name="result" type="{http://www.w3.org/2001/XMLSchema}string"/> * &lt;element name="descriptionerr" type="{http://www.w3.org/2001/XMLSchema}string"/> * &lt;element name="transid" type="{http://www.w3.org/2001/XMLSchema}string"/> * &lt;element name="ndserr" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> * &lt;element name="wallet" type="{http://www.acme.com/ws}t_wallet" minOccurs="0"/> * &lt;/sequence> * &lt;/restriction> * &lt;/complexContent> * &lt;/complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "responseINFOWL", propOrder = { "result", "descriptionerr", "transid", "ndserr", "wallet" }) public class ResponseINFOWL { @XmlElement(required = true) protected String result; @XmlElement(required = true) protected String descriptionerr; @XmlElement(required = true) protected String transid; protected String ndserr; protected TWallet wallet; // getters, setters and all. } 

I tried to play a little with namespaces in package-info , but still I'm not happy.

+7
source share
2 answers

I recently ran into the same problem that you were facing, and it turned out that the service I was contacting returned something different from the one that advertised its WSDL. The service used an older version of Apache Axis (1.4) with behavior that conflicts with current JAX-WS implementations.

In particular, the namespace in the contents of the actual response body was NOT what was expected from the client code generated by the JSX-WS wsimport utility. For example, the actual answer looked something like this: serviceResponse and all its children in the http://foo.com namespace ":

 <?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> <serviceResponse xmlns="http://foo.com"> <messageReturn> <messageId>12345</messageId> <status>Ok</status> </messageReturn> </serviceResponse> </soapenv:Body> </soapenv:Envelope> 

Unlike what was actually returning, client stubs created by wsimport expected something like the answer below, with the serviceResponse element in the " http://foo.com " namespace and the messageReturn child element in the anonymous space contained in it names.

 <?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> <n1:serviceResponse xmlns:n1="http://foo.com"> <messageReturn> <messageId>12345</messageId> <status>Ok</status> </messageReturn> </n1:serviceResponse> </soapenv:Body> </soapenv:Envelope> 

Since I couldn't change the service I used, I wrote a new WSDL instead, which used the wrapped doc-literal binding to explicitly control the expected response structure (and request, of course). There is a really good article on WSDL binding types compared to IBM Developerworks.

The generated WSDL looked something like this:

 <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://foo.com" xmlns:tns="http://foo.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <!-- Define the XML types we need to send and receive (used by the message definitions below) --> <wsdl:types> <schema targetNamespace="http://foo.com" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <!-- Reusable types --> <complexType name="ResponseType"> <sequence> <element name="messageId" nillable="true" type="xsd:string" /> <element name="status" nillable="true" type="xsd:string" /> </sequence> </complexType> <complexType name="InputType"> <sequence> <element name="firstName" nillable="true" type="xsd:string" /> <element name="lastName" nillable="true" type="xsd:string" /> <element name="command" nillable="true" type="xsd:string" /> </sequence> </complexType> <!-- Specific input/output elements used in wsdl:message definitions --> <element name="serviceResponse"> <complexType> <sequence> <element name="messageReturn" type="tns:ResponseType" /> </sequence> </complexType> </element> <element name="serviceRequest"> <complexType> <sequence> <element name="message" type="tns:InputType" /> </sequence> </complexType> </element> </schema> </wsdl:types> <!-- Define the WSDL messages we send/receive (used by the port definition below) --> <wsdl:message name="serviceResponseMessage"> <wsdl:part name="part1Name" element="tns:serviceResponse" /> </wsdl:message> <wsdl:message name="serviceRequestMessage"> <wsdl:part name="part1name" element="tns:serviceRequest" /> </wsdl:message> <!-- Define the WSDL port (used by the binding definition below) --> <wsdl:portType name="ServicePort"> <wsdl:operation name="serviceOperation"> <wsdl:input message="tns:serviceRequestMessage" /> <wsdl:output message="tns:serviceResponseMessage" /> </wsdl:operation> </wsdl:portType> <!-- Define the WSDL binding of the port (used by the service definition below) --> <wsdl:binding name="ServiceSoapBinding" type="tns:ServicePort"> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="serviceOperation"> <wsdlsoap:operation soapAction="" /> <wsdl:input> <wsdlsoap:body use="literal" /> </wsdl:input> <wsdl:output> <wsdlsoap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <!-- Finally, define the actual WSDL service! --> <wsdl:service name="UserCommandService"> <wsdl:port binding="tns:ServiceSoapBinding" name="ServicePort"> <!-- This address is just a placeholder, since the actual target URL will be specified at runtime --> <wsdlsoap:address location="http://localhost:8080/blah" /> </wsdl:port> </wsdl:service> </wsdl:definitions> 

Using custom WSDL, I was able to use wsimport to create client stubs that work great with the service. In addition, with a complete documented approach to the document, I have full control over the expected structure and namespace of the request / response, so I can implement several namespaces in this XML, if necessary.

Enjoy ...

+2
source

Please correct me if I have the wrong use case.

You can disable:

 <?xml version="1.0" encoding="UTF-8"?> <ns1:opINFOWLResponse xmlns:ns1="http://www.acme.com/ws" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns1:responseINFOWL xsi:type="ns1:responseINFOWL"> <ns1:result>6003</ns1:result> <ns1:ndserr /> <ns1:transid>61437594</ns1:transid> <ns1:descriptionerr>BLAH.</ns1:descriptionerr> </ns1:responseINFOWL> </ns1:opINFOWLResponse> 

But can not be undone:

 <?xml version="1.0" encoding="UTF-8"?> <ns1:opINFOWLResponse xmlns:ns1="http://www.acme.com/ws" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns1:responseINFOWL xsi:type="ns1:responseINFOWL"> <result>6003</result> <ndserr /> <transid>61437594</transid> <descriptionerr>BLAH.</descriptionerr> </ns1:responseINFOWL> </ns1:opINFOWLResponse> 

This means that the namespace qualifications in your JAXB mappings are incorrect. The following may help:

If you can publish a class that displays this XML section, and a package-info class, if any, then I can help you change the mappings.

+1
source

All Articles