Java Axis2 Web 服务调用 JAX-WS 客户端 jar

Java Axis2 Web Service calling JAX-WS client jar

我在 Tomcat 6 上部署了一个 Axis2 (1.5.1) Web 服务,我正在尝试调用 VMware Web 服务 SDK(JAX-WS 服务)。这失败了,因为我需要维护会话 (SESSION_MAINTAIN_PROPERTY = true)。在调用 JAX-WS 客户端 jar 时,有什么方法可以绕过 Axis2 吗?

这是堆栈跟踪:

javax.xml.ws.WebServiceException: Error: Maintain Session is enabled but none of the session properties (Cookies, Over-written URL) are returned.
    at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:173)
    at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
    at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:118)
    at org.apache.axis2.jaxws.BindingProvider.setupSessionContext(BindingProvider.java:242)
    at org.apache.axis2.jaxws.BindingProvider.checkMaintainSessionState(BindingProvider.java:209)
    at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:320)
    at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:159)
    at com.sun.proxy.$Proxy12.retrieveServiceContent(Unknown Source)
    at com.company.product.CredAuthHostSkeleton.getAuthKey(Unknown Source)
    at com.company.product.CredAuthHostMessageReceiverInOut.invokeBusinessLogic(Unknown Source)
    at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
    at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:114)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:173)
    at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:167)
    at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:142)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Unknown Source)

问题

问题原来是三方面的。第一个问题是过时的 Axis2 版本 (1.5.1),另外两个问题是基于代码的。

解决方案

将 Axis 版本升级到最新版本(从 1.5.1 到 1.7.4)后,以下代码更改修复了问题:

  1. 因为 Axis2 期望会话 cookie 的名称是 JSESSIONID 和 VMware returns vmware_soap_session,所以 CUSTOM_COOKIE_ID 属性 需要是设置以便 Axis2 检测到会话 cookie 已设置。

    VimService vimService = new VimService();
    VimPortType vimPort = vimService.getVimPort();
    
    Map<String, Object> ctxt = ((BindingProvider)vimPort).getRequestContext();
    ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url.toString());
    ctxt.put(org.apache.axis2.Constants.CUSTOM_COOKIE_ID, "vmware_soap_session");
    ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);
    
  2. 当 Axis2 维护会话时,它期望第一次调用设置会话 cookie。第一次调用 VMware API 检索服务内容不需要会话,因此它不需要 return cookie。这里的解决方案是添加另一个 VimService 和 VimPortType 专门用于检索服务内容。在这些更改之后,登录调用将起作用。

    VimService vimServiceRSC = new VimService();
    VimPortType vimPortRSC = vimService.getVimPort();
    
    Map<String, Object> ctxtRSC = ((BindingProvider)vimPortRSC).getRequestContext();
    ctxtRSC.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url.toString());
    
    ServiceContent serviceContent = vimPortRSC.retrieveServiceContent(this.getServiceInstanceRef());
    vimPort.login(serviceContent.getSessionManager(), "user", "password", null);
    

使用 VMware SDK 提供的示例代码片段显示了代码更改。