2011-03-24 28 views
8

Tengo dificultades para realizar con éxito una llamada de servicio web a un servicio web SOAP desde una página web. El servicio web es un servicio web Java que utiliza JAX-WS.Llamadas al servicio web SOAP desde Javascript

Aquí es el método web que estoy tratando de llamar:

@WebMethod 
public String sayHi(@WebParam(name="name") String name) 
{ 
    System.out.println("Hello "+name+"!"); 
    return "Hello "+name+"!"; 
} 

He intentado hacer la llamada de servicio web utilizando la biblioteca jQuery jqSOAPClient (http://plugins.jquery.com/project/jqSOAPClient).
Este es el código que he utilizado:

var processResponse = function(respObj) 
{ 
    alert("Response received: "+respObj); 
}; 

SOAPClient.Proxy = url; 
var body = new SOAPObject("sayHi"); 
body.ns = ns; 
body.appendChild(new SOAPObject("name").val("Bernhard")); 

var sr = new SOAPRequest(ns+"sayHi",body); 
SOAPClient.SendRequest(sr,processResponse); 

Sin respuesta parece estar regresando. Cuando estoy en jqSOAPClient.js, registro el miembro de datos xData.responseXML que obtengo 'indefinido'. En el servicio web veo la advertencia

24 Mar 2011 10:49:51 AM com.sun.xml.ws.transport.http.server.WSHttpHandler handleExchange ADVERTENCIA: no puede manejar método HTTP: OPCIONES

También he intentado utilizar una biblioteca javascript, soapclient.js (http://www.codeproject.com/kb/Ajax/JavaScriptSOAPClient.aspx). El código del lado del cliente que uso aquí es

var processResponse = function(respObj) 
{ 
    alert("Response received: "+respObj); 
}; 

var paramaters = new SOAPClientParameters(); 
paramaters.add("name","Bernhard"); 
SOAPClient.invoke(url,"sayHi",paramaters,true,processResponse); 

He bypassed en la parte soapclient.js que obtiene el WSDL, ya que no funciona (me sale un: IOException: An established connection was aborted by the software in your host machine en el lado servicio web) . El WSDL solo se recupera para el espacio de nombre apropiado para usar, por lo que acabo de reemplazar la variable ns con el espacio de nombre real.

Recibo exactamente la misma advertencia en el servicio web que antes (no puedo manejar el método HTTP: OPCIONES) y en la consola de error del navegador aparece el error "el documento es nulo". Cuando registro el valor de req.responseXML en soapclient.js, veo que es nulo.

¿Alguien podría aconsejarme sobre qué podría estar yendo mal y qué debería hacer para que esto funcione?

+0

Cuando despliego el servicio web a Glassfish, el cliente recibe las mismas respuestas ("indefinido" en el caso de jqSOAPClient.js y nulo cuando usa soapclient.js). – bgh

Respuesta

2

Me enteré de lo que estaba pasando aquí. Es el mismo escenario que en este hilo: jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox.

Básicamente estoy usando Firefox y cuando uno hace una llamada de dominio cruzado (el dominio de la dirección del servicio web no es el mismo que el dominio de la página web) desde Firefox usando AJAX, Firefox primero envía una OPCIONES Mensaje HTTP (antes de transmitir el mensaje POST), para determinar desde el servicio web si la llamada debe permitirse o no. El servicio web debe responder a este mensaje de OPCIONES para indicar si permite que la solicitud entre.

Ahora, la advertencia de JAX-WS ("No se puede manejar el método HTTP: OPTIONS") sugiere que no manejará ningún mensaje OPTIONS HTTP. Está bien, el servicio web finalmente se ejecutará en Glassfish. La pregunta ahora es cómo puedo configurar Glassfish para responder al mensaje OPTIONS.

En el hilo que se hace referencia más arriba Juha dice que él usa el siguiente código en Django:

def send_data(request): 
    if request.method == "OPTIONS": 
     response = HttpResponse() 
     response['Access-Control-Allow-Origin'] = '*' 
     response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' 
     response['Access-Control-Max-Age'] = 1000 
     response['Access-Control-Allow-Headers'] = '*' 
     return response 
    if request.method == "POST": 
     # ... 

Access-Control-Allow-Origen da un patrón que indica qué orígenes (direcciones de los destinatarios) será aceptado (el mío podría ser un poco más estricto que simplemente permitir cualquier origen) y Access-Control-Max-Age le cuenta después de cuántos segundos tendrá que volver a solicitar permiso el cliente.

¿Cómo puedo hacer esto en Glassfish?

+0

Uhm, ¿ayuda? ¿Nadie? – bgh

+0

He decidido evitar la llamada al servicio web multidominio ejecutando un proxy del servicio web PHP en el servidor en el que está alojado el sitio web. El Javascript llama a este servicio web PHP y el script PHP reenvía las solicitudes al servicio web objetivo. – bgh

1

¿De verdad ha probado que ws está funcionando correctamente?
Puede usar SoapUI para inspeccionar solicitudes/respuestas, etc. Cuando confirma que ws funciona desde SoapUI, inspeccione el formato del mensaje de Soap sin formato. Luego intente inspeccionar cómo se ve antes de enviar con el método .js y compárelos.

Podría ayudarle a comprender qué es lo que está mal.

+0

Gracias por la sugerencia. El servicio web funciona bien desde soapUI. He comparado el contenido de la solicitud enviada por soapUI con lo enviado por jqSOAPClient. – bgh

+0

Las solicitudes se dan a continuación: soapUI: ' Bernhard ' jqSOAPClient: ' Bernhard ' – bgh

+0

Hay diferencias menores, pero creo que' re ambos correctos. He tomado la solicitud que soapUI envía y lo he codificado en jqSOAPClient.js para que envíe exactamente esa cadena, pero el servicio web sigue dando las advertencias '24 de marzo 2011 2:36:32 PM com.sun.xml .ws.transport.http.server.WSHttpHandler handleExchange ADVERTENCIA: No se puede manejar el método HTTP: OPTIONS' y sin respuesta. El método web se ejecuta cuando uso soapUI, pero no se ejecuta cuando se llama desde la página web. – bgh

0

Comprobar si esto ayuda
http://bugs.jquery.com/attachment/ticket/6029/jquery-disable-firefox3-cross-domain-magic.patch

está marcado como no válido
http://bugs.jquery.com/ticket/6029
pero que podría dar alguna pista

Por otro lado, en lugar de redefinir los valores adecuados para secuencias de comandos entre dominios podría ser mejor si puede crear y llamar a la página local que solicitará ws y devolverá el resultado.
O mejor aún, puede crear una página que reciba url como parámetro y solicite esa url y simplemente devuelva el resultado. De esa forma será más genérico y reutilizable.

Cuestiones relacionadas