invocar example desde crear consumir consume cliente cero java jaxb jax-ws moxy

desde - java consume web service wsdl example



Mi cliente de servicio web jax-ws devuelve solo objetos vacĂ­os (2)

Tengo un servicio web de terceros para el cual 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. Supervisión de la red Puedo ver que todos los elementos XML en el mensaje de respuesta tienen valores en ellos, por lo que el objeto debe contener datos no nulos. 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).

Actualización : he podido reducirlo. El wsdl define el objeto en su propio espacio de nombres, por ejemplo, http://www.acme.com/ws . La respuesta que recibo del 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 no está adaptado a una OpNFOWLResponse no nula que envuelve una responseINFOWL no nula OpINFOWLResponse con todos los campos establecidos en nulo. Solo por diversión, intenté escribir un par de líneas para desmarcar el fragmento de arriba (después de eliminar el SOAP de arriba)

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

y obtengo el mismo resultado. Si cambio el XML de arriba 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 (nuevamente) : el mismo comportamiento con jaxb-RI y Moxy. Todavía no tengo idea de lo que está mal.

Actualización (9 de septiembre) : La sugerencia a continuación sobre la calificación del espacio de nombres es incorrecta, pero supongo que wsimport haría las cosas bien. De todos modos, este 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 relevante de la clase ResponseINFOWL

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

Intenté jugar un poco con los espacios de nombres en package-info pero todavía no me gustó.


Por favor, corrígeme si tengo tu caso de uso incorrecto.

Puedes 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"> <ns1:result>6003</ns1:result> <ns1:ndserr /> <ns1:transid>61437594</ns1:transid> <ns1:descriptionerr>BLAH.</ns1:descriptionerr> </ns1:responseINFOWL> </ns1:opINFOWLResponse>

Pero no puede unmarse:

<?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 del espacio de nombres en sus asignaciones JAXB es incorrecta. Lo siguiente puede ayudar:

Si pudieras publicar la clase que se asigna a esta sección de XML, y la clase package-info si la hay, entonces puedo ayudarte a modificar las asignaciones.


Recientemente encontré exactamente el mismo problema que encontré, y todo se debió al hecho de que el servicio al que 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 nombres 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 más o menos así, con el serviceResponse y todos sus hijos en el 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>

En contraste con lo que realmente regresaba, los stubs de clientes generados por wsimport esperaban algo como la respuesta a continuación, con el elemento serviceResponse en el espacio de nombres " http://foo.com " y el elemento child content Return Return 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, escribí un WSDL nuevo que utilizaba un enlace literal doc envuelto para controlar explícitamente la estructura esperada de la respuesta (y la solicitud, por supuesto). Hay un artículo realmente bueno sobre tipos de enlace WSDL sobre IBM Developerworks.

El WSDL que creé se veía así:

<?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 personalizado, pude usar wsimport para generar stubs de clientes 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.

Disfrutar...