【问题标题】:How can I call one web-service from another web-service (within in the same WAR)如何从另一个 Web 服务调用一个 Web 服务(在同一个 WAR 中)
【发布时间】:2012-05-31 04:31:44
【问题描述】:

上下文:应用服务器是 Glassfish 3.1.2。技术是JavaEE JAX-WS。 IDE 是 Netbeans 7.1.1。

我使用 wsimport 从 WSDL 创建了 2 个 Web 服务。 EJB 也不是。它们都使用 @WebService 注释。他们都生活在同一个 WAR 中(不确定这应该是相关的,但它可能是相关的)。使用 SOAP-UI 作为客户端,我可以非常愉快地单独部署和测试这两种服务。

我现在想让 WebService1 在运行时调用 WebService2。我不想只使用 java 调用 webservice2 的 impl(可以这么说)——我想将 webservice2 作为 web 服务正确调用,以创建更松散的耦合。

在 IDE 中,我可以使用提供的“生成代码:Web 服务调用操作”功能生成 Web 服务调用所需的代码。这添加了一个 @WebServiceRef(wsdlLocation = "WEB-INF/wsdl/servicename.wsdl") 和一些代码来创建端口并调用目标 web 服务操作。

    // Call Web Service Operation
   Identity port = service.getIdentityPort();
   String req = "";
   javax.xml.ws.Holder<StructureMessageHeader> idHeader = new javax.xml.ws.Holder<StructureMessageHeader>();
   String result = port.getIdentifier(req, idHeader);

这编译得很好,但在运行时它会失败。部署是成功的,服务都已启动并且通常都很满意(只要您不调用此代码),但是当一个 web 服务尝试调用另一个时,我得到一个

ClientTransportException: The server sent HTTP status code 404: Not Found.

更多详情如下。

有谁知道为什么会发生这种情况?我哪里做错了?我忽略了什么?

任何帮助,非常感谢。

------------ 例外 ---------

com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 404: Not Found at com.sun.xml.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:321) at com.sun.xml.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:270) at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:228) at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:143) at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:110) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775) at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:116) at com.sun.enterprise.security.webservices.ClientSecurityPipe.processSecureRequest(ClientSecurityPipe.java:196) at com.sun.enterprise.security.webservices.ClientSecurityPipe.process(ClientSecurityPipe.java:184) at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775) at com.sun.xml.ws.client.Stub.process(Stub.java:429) at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:168) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:102) at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:151) at $Proxy219.getIdentifier(Unknown Source) at com.soagrowers.r20121231.product.master.services.ProductsEntityService.createProduct(ProductsEntityService.java:138) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.glassfish.webservices.InstanceResolverImpl$1.invoke(InstanceResolverImpl.java:143) at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:149) at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:94) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775) at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:116) at org.glassfish.webservices.MonitoringPipe.process(MonitoringPipe.java:142) at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775) at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:116) at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:212) at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:144) at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775) at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:386) at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:640) at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:263) at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:163) at org.glassfish.webservices.JAXWSServlet.doPost(JAXWSServlet.java:145) at javax.servlet.http.HttpServlet.service(HttpServlet.java:688) at javax.servlet.http.HttpServlet.service(HttpServlet.java:770) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) at com.sun.grizzly.ContextTask.run(ContextTask.java:71) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

    标签: java web-services glassfish jax-ws


    【解决方案1】:

    需要将 Web 客户端嵌入到第一个 Web 服务中,然后它会从第二个 Web 服务请求信息。 This client from apache 使用效果很好。

    有时,Web 服务库还包含嵌入式 Web 客户端以方便测试。如果您的库包含这样的客户端,您甚至不需要添加额外的 Web 客户端实现。

    --- 已编辑以回答有关 JAXWS API 是否提供“客户端”支持的问题 ---

    当然,JAX-WS 具有设置 Web 服务的一切,但我不确定它是否是规范的一部分,它还包含调用 Web 服务的所有内容。我还没有看到缺少这种工具的实现,因此响应库“偶尔”包含客户端的说法有点夸大其词了。

    无论如何,支持客户端的类只是简单地包装了 XML 生成器和 HTTP 客户端。

    如果我没记错的话,您会获得一份 WSDL 的副本,该副本由“编译器”读取,该“编译器”在指定的包命名空间中输出 Java 源代码。然后使用生成的类,您可以访问远程 Web 服务的 API 级别。最终结果是这样的

    public static void main(String[] args) {
        /* Create the service instance */
        CalculatorService service = new CalculatorService();
        CalculatorDelegate delegate = service.getCalculatorPort();
    
        /* Using the web service, perform the 4 calculations */
        System.out.println("1. 3+7=" + delegate.add(3, 7));
        System.out.println("2. 12-2=" + delegate.subtract(12, 2));
        System.out.println("3. 9*9=" + delegate.multiply(9, 9));
        System.out.println("4. 40/2=" + delegate.divide(40, 2));
    } 
    

    您通过构造一个 XXXService 对象来创建“服务的客户端视图”,然后将其附加到该对象上,从而生成一个 XXXDelegate 类型的委托对象。委托中的方法实际上生成封装请求的新对象(每个端口绑定“SomeCall.java”存在一个对象),并且响应由“SomeCallReply.java”文件处理,委托随后使用该文件解包响应并将值返回给“客户端”代码。

    可以在at the bottom of this tutorial 找到一个示例。同样,这是我对高级内容的理解,细节可能在 JAXWS 的较新版本中有所改变。当我深入挖掘时,它还处于游戏的早期阶段。从那以后,JAXWS 已经发布了很多版本。

    【讨论】:

    • 我想我明白你的意思,但是你有没有可以指点我的参考资料?
    • 我确信 JAX-WS 框架将提供我使用其他服务所需的一切,而无需求助于其他 HTTP 框架。这不是真的吗?
    • 据我所知,这是真的,但我不知道它是否总是正确,如果我夸大了“有时”,请见谅。再读一遍,我可以很容易地看出我是如何暗示它很少是真的。很抱歉造成混乱。
    【解决方案2】:

    解决此问题的更好方法是使 Web 服务成为一个层,然后调用应用程序逻辑。然后,当一组业务逻辑需要调用另一组时,就不必经历不必要的 http 往返。考虑使用带有@Service 和@Autowired 的Spring 之类的东西。在 EJB 世界中(我知道你说过你没有使用它)这是通过 @Local 接口和 @EJB 会话注入来完成的,因此你不会通过一个巨大的远程 API 堆栈来调用另一个类中的方法。

    【讨论】:

    • 我正在尝试应用合同集中化 SOA 模式,该模式主张服务合同应该是客户端使用服务的唯一方式。这是一种通过避免直接消费者到实现耦合(例如直接到 EJB)来实现更松耦合的方法。
    • 我并不是在提倡客户端直接与 Spring @Service@Stateless 会话 bean 对话。我是说业务逻辑应该被视为 Web 层与之对话的服务。然后一个给定的 Web 服务调用一个业务服务,而不知道该业务服务在内部做什么。然后,业务服务可以是业务服务的组合。
    【解决方案3】:

    我想我已经解决了它

    有 2 个问题,在修复了这些错误后,我的代码现在可以正常工作了。

    问题 #1。 (次要) jax-ws-catalog.xml 不包含对 WebService2 的 WSDL 或 XSD 文件的引用。这是帮助 JAX-WS 框架在运行时利用 WSDL 的本地副本而无需通过 HTTP 加载 WSDL 或 XSD 所必需的。

    问题 #2。 (主要) jax-ws-catalog 中引用的 WSDL 中的“服务”部分需要在其中具有准确的端点位置。在运行时,服务器将根据各种配置将 WSDL 的这一位重写为服务的正确 http 端点位置(例如 @webservice 注释中的详细信息)。当然,当您“从 WSDL 开始”时,此端点可能完全是虚构的,因为服务合同与任何实现都分离(就像我的情况一样)。因此,当 JAX-WS 从 jax-ws-catalog 中指定的位置获取 WSDL 时,它会找到一个不存在且无法解析的 http 位置。因此,“ClientTransportException: The server sent HTTP status code 404: Not Found.”——WSDL 中的 URL 有问题。

    总结。 解决方案是将 Web 服务的准确端点位置添加到 WSDL 的“服务”定义部分,并确保 WSDL 及其 XSD 在 jax-ws-catalog 中正确列出。

    【讨论】:

      猜你喜欢
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多