2011-08-24 6 views
7

Tengo un servicio web de terceros para el que genero un cliente usando wsimport. Cada llamada al servicio web se completa con éxito, pero el objeto de respuesta que recibo tiene todos sus campos establecidos en nulo. Monitoreo de la red Puedo ver que en el cable todos los elementos XML en el mensaje de respuesta tienen valores en ellos, por lo que el objeto debe tener datos no nulos en él. Además, un cliente para el mismo servicio generado con old axis1 y llamado con los mismos datos devuelve una respuesta no vacía. ¿Alguna idea de lo que está pasando? (En caso de que haya alguna diferencia, estoy usando la implementación de MOXy de JAXB).Mi cliente de servicio web jax-ws solo devuelve objetos vacíos

Actualización: He podido reducirlo. El wsdl define el objeto en su propio espacio de nombres, digamos http://www.acme.com/ws. La respuesta que recibo de servicio es

<?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 ... 

y es unmarshalled a un no nulo OpINFOWLResponse que se envuelve alrededor de un objeto no nulo responseINFOWL con todos los campos establecidos en null. Sólo por diversión He intentado escribir un par de líneas para deserializar el fragmento anterior (después de quitar la sobrecarga de SOAP)

JAXBContext ctx = JAXBContext.newInstance(OpINFOWLResponse.class); 
Unmarshaller u = ctx.createUnmarshaller(); 

OpINFOWLResponse o = (OpINFOWLResponse) u.unmarshal(new StringReader(theSnippetAbove)); 
ResponseINFOWL w = o.getResponseINFOWL(); 

y obtener el mismo resultado. Si cambio el XML anterior a

<?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> 

Todo funciona bien. Gorrón.

actualización (de nuevo): El mismo comportamiento tanto con jaxb-RI y Moxy. Todavía no tengo idea de lo que está mal.

Update (Sep. de 9): La sugerencia por debajo de la calificación de espacio de nombres a equivocarse es interesante, pero supone wsimport sería hacer las cosas bien. De todos modos, esta es mi 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; 

y esta es la parte pertinente de la clase

/* 
* <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. 

} 

ResponseINFOWL He intentado jugar un poco con los espacios de nombres en package-info pero todavía no hay alegría.

+0

¿Puede proporcionar muestras de los mensajes y clases? Esto ayudará a determinar dónde está la falta de coincidencia en el mapeo. –

+0

Tal vez podría publicar un archivo wsdl y una clase de prueba anonimizados adecuadamente, todo lo demás en mi caso es generado por wsimport. Lo curioso es que otros servicios del mismo tercero funcionan bien. – agnul

Respuesta

1

Corrígeme si tengo su caso de uso incorrecto.

Puede deserializar:

<?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> 

pero no puede unmarshal:

<?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> 

Esto significa que la calificación de espacio de nombres en sus asignaciones de JAXB es incorrecta. Lo siguiente puede ayudar:

Si usted puede publicar la clase que se asigna a esta sección de XML y la clase package-info si hay uno, entonces yo puedo ayudarle a modificar las asignaciones.

2

Recientemente me encontré con exactamente el mismo problema que encontré, y se redujo al hecho de que el servicio al que me estaba contactando devolvía algo diferente de lo que anunciaba WSDL. El servicio utilizó una versión anterior de Apache Axis (1.4) con un comportamiento que entra en conflicto con las implementaciones actuales de JAX-WS.

En particular, el espacio de nombre en el contenido del cuerpo de respuesta real NO era el esperado por el código de cliente generado por la utilidad wsimport de JAX-WS. Por ejemplo, la respuesta real se veía algo como esto, con el serviceResponse y todos sus hijos en espacio de nombres "http://foo.com":

<?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> 

A diferencia de lo que realmente estaba volviendo, los recibos de cliente generados por wsimport esperaban algo así como la respuesta a continuación, con el elemento serviceResponse en el espacio de nombres "http://foo.com" y el elemento contentReturn contenido en el espacio de nombres anónimo.

<?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> 

Como no podía cambiar el servicio que estaba consumiendo, Yo en cambio escribió un nuevo WSDL mí mismo que utiliza un documento literal de unión para controlar de forma explícita la estructura esperada de la respuesta (y solicitar, por supuesto) envueltos. Hay un muy buen artículo sobre tipos de enlace WSDL sobre IBM Developerworks.

El WSDL creé visto algo como esto:

<?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> 

Con el WSDL personalizada, yo era capaz de utilizar wsimport para generar stubs cliente que funcionan perfectamente con el servicio Además, con el enfoque literal doc ajustado, controlo completamente la estructura y el espacio de nombres esperados de la solicitud/respuesta, de modo que puedo implementar múltiples espacios de nombres en ese XML si es necesario.

Disfrute ...

Cuestiones relacionadas