在 Weblogic Server 10 中使用 JAX-WS 和 JAXB:JAX-WS 自定义绑定
页面: 1, 2, 3

使用JAX-WS绑定声明指定处理程序链

我们可以通过 <javaee:handler-chains> 绑定声明指定生成的JSR-181 (Web Services Metadata for the Java Platform) 工件。它可以:

  1. 生成处理程序链XML配置文件
  2. 在生成的代码中插入 javax.jws.HandlerChain 注释。

以下内容摘录自我在服务提供者端使用的 <javaee:handler-chains> 绑定声明:

 

<bindings

   xmlns:jxb="http://java.sun.com/xml/ns/jaxb"

   xmlns="http://java.sun.com/xml/ns/jaxws"

                        
wsdlLocation="DataStagingService2.wsdl"
> ... <bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
node="wsdl:definitions"
>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee">

<javaee:handler-chain>

<javaee:handler>

<javaee:handler-name>VendorSOAPHandler</javaee:handler-name>

<javaee:handler-class>services.datastaging.VendorSOAPHandler</javaee:handler-class>

</javaee:handler>

</javaee:handler-chain>

</javaee:handler-chains>
</bindings> ... </bindings>

编写JAX-WS处理程序是一个相当棘手的过程,因此本文将略过这一点。大家只需注意 VendorSOAPHandler 类将处理SOAP报头,该报头由服务使用者端的JAX-WS处理程序生成。有关如何编写JAX-WS处理程序的深入信息,请阅读Young Yang的 "Get a handle on the JAX-WS API's handler framework" 这篇文章。

使用绑定声明示例JAX-WS代码

至此,我已经介绍了绑定声明文件的作用。下面,我将介绍有关服务使用者和服务提供者的一些示例代码:

  • 运行BEA wsdlc Ant任务时生成的代码

  • 使用运行BEA wsdlc Ant任务时生成的JAX-WS工件的代码 Ant task.

示例JAX-WS代码——在服务提供者中使用绑定声明

本文与第一篇文章中所使用服务提供者代码完成不同了。关键的区别包括:

  1. 从“从Java开始”编程模型转换到“从WSDL开始”编程模型。

  2. 我添加了一个绑定声明,将Web服务操作的名称从 dataStaging 修改为 sendInputURIs

  3. 我添加了一个绑定声明,使包装器样式类型在生成的框架SEI类中使用。

  4. 我添加了一个绑定声明,将生成的SEI接口类的名称修改为 DataStagingService2

  5. 我添加了一个绑定声明,以控制所添加的Exception类的新名称 ( DataStagingServiceException)。

  6. 我添加了一个AX-WS SOAP处理程序,以处理服务使用者端JAX-WS SOAP处理程序添加的 Vendor SOAP Header。

BEA wsdlc Ant任务生成的框架SEI类比较小,因此我决定完整地列出它的内容:


package services.datastaging;  

import javax.jws.WebService; 

import javax.xml.ws.BindingType; 

import javax.jws.HandlerChain;  

/**  

* services.datastaging.DataStagingServiceImpl class implements web service endpoint interface services.datastaging.DataStagingService2 

*/  

@WebService(

   portName="DataStagingServicePort",

   serviceName="DataStagingService",

   targetNamespace="http://services.irad.acmeworld.com/datastaging",

   endpointInterface="services.datastaging.DataStagingService2",

   wsdlLocation="/wsdls/DataStagingService2.wsdl"

) 

@BindingType(value="http://schemas.xmlsoap.org/wsdl/soap/http") 

@HandlerChain(

   file="jar:file:WebContent/WEB-INF/lib/DataStagingService2_wsdl.jar!/services/datastaging/DataStagingService2_handler.xml"

) 

public class DataStagingServiceImpl implements services.datastaging.DataStagingService2 

{

    public DataStagingServiceImpl() 

    {   

    }

    public com.acmeworld.irad.services.datastaging.DataStagingResponse.OutputURIs sendInputURIs(com.acmeworld.irad.services.datastaging.DataStaging.InputURIs inputURIs)

      throws services.datastaging.DataStagingServiceException 

    {

        //replace with your impl here

        return null;

    }

} 

每次运行BEA wsdlc Ant任务时,这个框架SEI类都会被重写。因此,我们需要防止意外运行所造成的代码损失。最安全的方法是定期备份该文件。另一种方法是将 build.xml 文件中出现的所有 depends 属性的 run-wsdlc Ant目标删除。

示例JAX-WS代码——在服务使用者中使用绑定声明

在第一篇文章中,我在JAX-WS客户机代码中使用了 Dispatch client API 方法。在本文中,我选择使用 Dynamic Proxy client API 方法。Dynamic Proxy client API涉及使用BEA clientgen Ant所生成的 服务代理类。Ant任务将从内部调用Sun wsimport Ant任务。

项目的 etc/client-jaxws.jbd 文件中包含服务使用者端使用的绑定声明。这些绑定声明的作用是:

  1. 在服务代理类中生成异步方法。我在示例JAX-WS客户机中使用这些方法异步地调用SEI方法。
  2. 修改服务代理接口类中所使用的方法的名称。
  3. 修改服务代理接口类中所使用的参数的名称。
  4. 为使用者端JAX-WS处理程序链生成JSR-181工件。

以下是执行异步方法调用的代码:


        ... 

        DataStagingService service = new DataStagingService();  

        service.setExecutor(Executors.newSingleThreadExecutor());          

        DataStaging port = service.getDataStagingServicePort();         

        ... 

这段代码演示了如何使用一个单线程的线程模型调用 void handleResponse(Response) 回调方法。客户机的 java.xml.ws.Service 实例中的 setExecutor() 方法用于指定该方法。下面是实现 javax.xml.ws.AsyncHandler 接口的代码片断:


... 

private class ClientCallback implements AsyncHandler<datastagingresponse> 

{

     public void handleResponse(Response<datastagingresponse> response)

     {

         try

         {

           log("handleResponse(Response<datastagingresponse>)", (new StringBuffer()).append("Callback method was invoked.").toString());

           printDataStagingResponse(response.get());

         }

         catch (Exception e)

         {

             e.printStackTrace();

         }

     }

}

... 

通过阅读这些教程,我们已经了解使用绑定声明可以实现许多操作。教程还提供了关于如何在 WebLogic Server 10中使用它们的详细步骤。提供这些信息的原因有以下两个:

  1. 我发现一些用户在BEA NewsWeb新闻组网站上发表了一些问题,但是都没有得到回复。如果在WebLogic Server 10中使用JAX-WS和JAXB遇到了任何问题,用户可通过该站点寻求帮助。我使用本文回答了其中的部分问题,同时传播了一些关于使用WebLogic Server 10进行JAX-WS开发的知识。

  2. 我希望提供一些资料作为Sun提供文档的“补充参考”(关于此主题)。

当您在WebLogic Server 10中使用JAX-WS实现遇到问题时,这些内容足以解决大多数问题,从而减少Google搜索的使用数量。

建议使用教程列表直接找到您需要实施的用例。

结束语

JAX-WS绑定声明为您提供了一种强大的机制,用于影响和改变由Sun wscompilewsimport Ant任务生成的工件。这些绑定声明可以嵌入到WSDL中,或者存放含有XML文档(符合XML模式,名称空间为 http://java.sun.com/xml/ns/jaxws)的文件中。推荐使用存放在文件中的方法。

WebLogic Server 10 Web服务栈所提供的BEA Ant任务(即 clientgenwsdlcjwsc)可从内部调用上面提到的Sun Ant任务。您可以使用它们所提供的 <binding> 子元素指定要使用的JAX-WS(和/或JAXB)绑定声明。

拥有这种控制很好,但是它确实带来了成本的复杂性问题。Java EE开发曾被认为是“过度复杂的”,而JAX-WS绑定声明也并未有所改变。在文本编辑器中“手动编写”JAX-WS绑定声明文件并不是大多Java开发人员所乐意的,并且还需要较好的IDE支持。

展望未来

本系列的最后一篇文章将介绍 Glassfish JAX-WS Commons 项目中的一些高级功能。我的研究表明该项目中的JAR文件可以与Glassfish JAX-WS 2.0中的JAR文件一起使用,前提是Glassfish JAX-WS 2.0中的JAR文件可以在WebLogic Server 10使用。我将主要介绍以下内容:

  1. 使用Spring beans作为服务实现。

  2. 使用Spring配置框架创建可同时支持多种绑定类型的JAX-WS服务。 javax.xml.ws.BindingType 注释只允许您使用其中之一。

  3. 在WebLogic Server 10上创建、托管和调用REST服务。它们并不是“真正”的REST服务,并不是使用 HTTP GET 方法和长查询字符串的HTTP端点。

  4. 在WebLogic Server 10上创建、托管和调用JSON (Java-Script Object Notation) 服务。

  5. 创建调用JSON服务的JSON服务使用者。

敬请期待。

参考资料

有关本文所讨论主题的其他信息,请阅读以下文章:

Mike Wooten 是 BEA 享有声望的技术解决方案小组(Technical Solutions Group,TSG)的一名高级首席解决方案工程师。他的工作时间都在帮助将BEA客户的抽象技术概念转变为能创造价值的解决方案。这些解决方案所提供的功能往往令其竞争者们望尘莫及。