【问题标题】:SOAP web service calls from Javascript来自 Javascript 的 SOAP Web 服务调用
【发布时间】:2011-07-21 23:32:59
【问题描述】:

我正在努力从网页成功地对 SOAP Web 服务进行 Web 服务调用。 Web 服务是使用 JAX-WS 的 Java Web 服务。

这是我试图调用的网络方法:

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

我尝试使用 JQuery 库 jqSOAPClient (http://plugins.jquery.com/project/jqSOAPClient) 进行 Web 服务调用。
这是我使用的代码:

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);

似乎没有回复。在 jqSOAPClient.js 中时,我记录了 xData.responseXML 数据成员,我得到“未定义”。在网络服务中,我看到了警告

2011 年 3 月 24 日上午 10:49:51 com.sun.xml.ws.transport.http.server.WSHttpHandler handleExchange 警告:无法处理 HTTP 方法:OPTIONS

我也尝试过使用 javascript 库soapclient.js (http://www.codeproject.com/kb/Ajax/JavaScriptSOAPClient.aspx)。我在这里使用的客户端代码是

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

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

我绕过了 soapclient.js 中获取 WSDL 的部分,因为它不起作用 (我在 Web 服务端得到一个:IOException: An established connection was aborted by the software in your host machine)。 WSDL 仅被检索以供适当的名称空间使用,因此我刚刚将变量 ns 替换为实际的名称空间。

我在 Web 服务上收到与以前完全相同的警告(无法处理 HTTP 方法:OPTIONS),在浏览器的错误控制台中我收到错误“文档为空”。当我在soapclient.js 中记录req.responseXML 的值时,我看到它为空。

任何人都可以就可能出现的问题以及我应该怎么做才能使其正常工作提供建议吗?

【问题讨论】:

  • 当我将 Web 服务部署到 Glassfish 时,客户端得到相同的响应(在 jqSOAPClient.js 的情况下为“未定义”,在使用 soapclient.js 时为空)。

标签: java javascript jquery soap jax-ws


【解决方案1】:

您是否实际测试过 ws 是否正常工作?
您可以使用 SoapUI 来检查请求/响应等。 当您确认 ws 在 SoapUI 中工作时,请检查原始 Soap 消息的格式。然后尝试在使用 .js 方法发送之前检查它的外观,并进行比较。

这可能会帮助您了解问题所在。

【讨论】:

  • 感谢您的建议。网络服务在soapUI 上运行良好。我将soapUI 发送的请求内容与jqSOAPClient 发送的内容进行了比较。
  • 请求如下:soapUI:<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="http://community.armadanetz.microworks/"> <soapenv:Header/> <soapenv:Body> <com:sayHi> <name>Bernhard</name></com:sayHi> </soapenv:Body> </soapenv:Envelope>jqSOAPClient:<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <sayHi xmlns="http://community.armadanetz.microworks/"> <name>Bernhard</name> </sayHi> </soapenv:Body> </soapenv:Envelope>
  • 存在细微差别,但我相信它们都是正确的。我接受了soapUI 发送的请求并将其硬编码到jqSOAPClient.js 中,以便它准确地发送该字符串,但Web 服务仍然给出警告24 Mar 2011 2:36:32 PM com.sun.xml.ws.transport.http.server.WSHttpHandler handleExchange WARNING: Cannot handle HTTP method: OPTIONS 并且没有响应。当我使用soapUI时,web方法确实执行了,但是从网页调用时它根本没有运行。
【解决方案2】:

我发现这里发生了什么。与此线程中的场景相同:jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox

基本上我使用的是 Firefox,当一个人使用 AJAX 从 Firefox 进行跨域调用(Web 服务地址的域与网页的域不同)时,Firefox 首先发送一个 OPTIONS HTTP -message(在它传输 POST 消息之前),从 Web 服务确定是否应该允许调用。然后,Web 服务必须响应此 OPTIONS 消息,以告知它是否允许请求通过。

现在,来自 JAX-WS 的警告(“无法处理 HTTP 方法:OPTIONS”)表明它不会处理任何 OPTIONS HTTP 消息。没关系 - Web 服务最终将在 Glassfish 上运行。 现在的问题是如何配置 Glassfish 以响应 OPTIONS 消息。

在上面引用的线程中,Juha 说他在 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-Origin 给出了一个模式,指示哪些来源(收件人地址)将被接受(我的可能比简单地允许任何来源更严格)并且 Access-Control-Max-Age 告诉在多少秒客户将不得不再次请求许可。

如何在 Glassfish 中执行此操作?

【讨论】:

  • 我决定通过在托管网站的服务器上运行代理 PHP Web 服务来避免跨域 Web 服务调用。 Javascript 调用此 PHP Web 服务,PHP 脚本将请求转发到目标 Web 服务。
【解决方案3】:

检查这是否有帮助
http://bugs.jquery.com/attachment/ticket/6029/jquery-disable-firefox3-cross-domain-magic.patch

它被标记为无效
http://bugs.jquery.com/ticket/6029
但它可能会给你一些提示

另一方面,如果您可以创建和调用将对 ws 进行请求并返回结果的本地页面,那么覆盖跨域脚本的正确设置可能会更好。
或者更好的是,您可以创建将接收 url 作为参数的页面,并对该 url 进行请求并返回结果。这样它会更加通用和可重用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    相关资源
    最近更新 更多