[AIX索拉里斯HP-UXLinux视窗][z/OS]

从现有 WSDL 文件开发 SCA 服务(已弃用)

从现有 Web Service 描述语言 (WSDL) 文件开始时,可以开发服务组件体系结构 (SCA) 服务实现。

在你开始之前

找到定义要实现的 SCA 服务的 WSDL 文件。 可以开发 WSDL 文件,或从现有 SCA 服务获取一个 WSDL 文件。 此 WSDL 文件将服务接口描述为 WSDL portType,且包括业务数据的 XSD 模式定义。

该产品支持同样符合 WS-I 基本概要文件 V1.1 和简单 SOAP 绑定概要文件 1.0 标准并使用文档文字样式的 Web Service 描述语言 (WSDL) V1.1 定义。 所有这些条件都是支持所必需的。

关于此任务

开发 SCA 服务实现有两种方法:
  • 从现有的 Web 服务描述语言 (WSDL) 开始进行自上而下的开发
  • 从使用 Java XML 绑定架构 (JAXB) 数据类型的现有 Java™ 代码开始进行自下而上的开发

自顶向下开发方法利用可互操作的基于 XML 的 WSDL,以及 XSD 接口和数据定义。

此任务描述了使用自上而下的开发方法从 WSDL 接口和 XSD 数据定义开始用 Java 开发 SCA 服务实现的步骤。

最佳实践:使用自上而下的方法来开发 SCA 服务实现是一种最佳实践,因为这种方法使用了 XML 接口描述的功能,并更易于跨平台、绑定和编程语言实现互操作性。

使用wsimport当现有 WSDL 文件将所需的 SCA 服务接口描述为 WSDL 时,命令行工具可生成业务服务接口和业务数据的 Java 表示portType,以及您的业务数据的 XSD 模式定义。 wsimport 工具会生成 Java 类,供您用来编写对业务逻辑进行反映的 Java 实现。 结果是使用生成的 JAXB 数据类型生成的接口的普通老式 Java 对象 (POJO) 实现。 通过将@Service注释添加到Java实现中,该注释将Java实现定义为SCA服务实现。

生成的与您的业务数据相对应的带注释的 Java 类包含 JAXB 运行时环境构建和解析 XML 以进行编组和解组所需的所有必要信息。 换句话说,数据编程模型只能进行对象实例化及使用 getter 方法和 setter 方法,并且在 XML 有线格式和 Java 应用程序之间转换数据时,您不需要编写代码。

支持的配置:该产品使用 JAXB 定义的 XML 编组来跨远程接口编组和解组数据。 如果你从远程 Java 接口开始实现,而不是从 WSDL 开始portType接口,在选择输入和输出 Java 数据类型时要小心,并确保您了解在 JAXB 编组和解组过程中保留了哪些数据。 然而,在本地接口上编写实现时,可以使用任何 Java 类型,因为本地接口使用“按引用传递”语义,这意味着不会复制任何数据。
支持的配置:当 Java 映射需要 holder 类时,该产品不支持使用 WSDL 文件。 该产品使用 JAX-WS 规范来定义 WSDL 文件与 Java 之间的映射,包括 WSDLportType对象和 Java 接口。 当你有 WSDL 时portType对于使用输入输出参数的操作或使用多个输出参数的操作的对象,JAX-WS 规范使用javax.xml.ws.Holder WSDL 映射中的类portType对象到 Java 接口。 使用该产品时,如果 Java 映射需要 holder 类,请不要使用 WSDL 文件。 相反地,请使用不映射到 Holder 类的 WSDL 文件。

如果在开发 SCA 服务时从现有 WSDL 文件开始,那么会将接口视为远程接口。 远程接口使用“按值传递”语义,这意味着会复制数据。

您可以将生成的 Java 实现用作复合定义中定义的 SCA 组件并进行部署。 组合定义会定义 SCA 工件,例如,服务引用、导入和导出。 组件是根据 WSDL、Java 实现和部署期间定义的绑定等开发工件来定义的。

JAXB API 要求您注册想要使用 JAXBContext 类进行编组或解组的 Java 类类型。 产品运行时环境通过检查您的 Java 接口为您注册这些 Java 类类型。 进行这些自省时,应注意使用多态性(继承)时的可能问题。 按照基本超类类型定义接口并且您想要在运行时传递派生子类类型的参数实例时,子类对 JAXBContext 类未知(如果只是自省接口参数类型)。

在 JAXB 中,可使用 javax.xml.bind.annotation.XmlSeeAlso 注释来解决多态性问题。 放置@XmlSeeAlso使用生成的 Java 接口上的注释生成@WebService注释,用于引用添加到 JAXBContext 类的其他 JAXB 派生子类以及从接口参数进行自省的类。

过程

  1. 使用wsimport命令行工具来开发您的业务服务接口和业务数据的 SCA Java 表示。

    wsimport工具处理 WSDL 文件并生成用于创建 SCA 服务的 Java 类和 JAXB 数据类型。

    将所有生成的类包含在应用程序档案中非常重要,其中包括您可能不会在 Java 实现中直接引用的类。 即使您的简单接口传递简单参数类型(如字符串和整数),或任何 JAXB 数据类型都不是必要的,仍请确保在此代码生成步骤中包括所有类,其中包括间接引用。

    • 运行 wsimport 命令以生成工件。

    wsimport工具位于应用程序服务器根目录/bin/目录。

    [Windows]
    app_server_root\bin\wsimport.bat -keep wsdl_URL 
    [Linux][AIX][HP-UX][Solaris]
    app_server_root/bin/wsimport.sh -keep wsdl_URL
    [IBM i]
    app_server_root/bin/wsimport -keep wsdl_URL

    -保持选项指定保留生成的Java源文件和编译后的类文件。

  2. 找到与您的 WSDL 直接对应的 Java 接口portType从生成的工件中。
    接口是通过@WebService注释,它是一个接口而不是一个类文件。
  3. 完成 SCA 服务的实现。
    编写生成的 Java 接口的 Java 实现来反映您的业务逻辑。 Java 实现是使用生成的 JAXB 数据类型对生成的接口的普通老式 Java 对象 (POJO) 实现。 此实现是根据 SCA Java 组件实现编程模型进行注释的。
  4. 注释 Java 实现。
    将 @Service 注释添加到 Java 实现以指定此实现是 SCA 服务。 完成此步骤后,就已创建 SCA 组件实现。
  5. 使用此组件实现以在组合定义中定义组件。
    在您的组合定义中,定义组件以引用原始 WSDL portType 接口和 SCA 实现。
    1. 在下面<component>元素,创建一个<implementation.java>引用 POJO 组件实现的类名的子元素。
    2. 在下面<component>元素,创建一个<service>子元素。
    3. 在下面<service>元素,创建一个<interface.wsdl ..>引用 WSDL 的元素portType。
      <service> 元素的 @name 属性必须与 Java 接口的未限定类名相匹配。

    您的组件现在具有明确定义的组件名称和服务名称及明确定义的接口。

    除了这些开发过程所描述的组件定义方面之外,还有其他关于定义组件的方面。 这些方面包括添加绑定、配置属性值、定义意向、连接策略集以及解析引用。 可以使用此相同实现来创建多个组件,但就本步骤中所描述的 <implementation.java><interface.wsdl><service> 元素而言,所有组件定义都是相同的。

  6. 根据可部署组合来创建 SCA 业务级应用程序,以部署 SCA 服务。

    在上述步骤中,您定义了一个在组合定义中提供 SCA 服务的组件。 该组合件要么是可部署组合件,要么是可作为更高级别组合件中的组件的组合实现而递归使用的组合件。 要了解如何部署 SCA 服务,请参阅“部署和管理业务级应用程序”。

结果

您从现有 WSDL 文件开始创建了 SCA 实现。

示例

以下示例说明如何使用现有的 WSDL 接口生成 Java 接口,该接口用于创建 SCA 服务的 Java 实现。

  1. 将以下样本 account.wsdl WSDL 文件复制到临时目录。
    <?xml version="1.0" encoding="UTF-8"?> 
    
    <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
         xmlns:account="https://www.myaccount.com/account"
         targetNamespace="https://www.myaccount.com/account"
         name="AccountService">
    
          <wsdl:types>
             <schema targetNamespace="https://www.myaccount.com/account"
                 xmlns="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:account="https://www.myaccount.com/account">
    
                   <element name="computeAccountAverage">
                     <complexType>
                         <sequence>
                             <element name="account" type="account:Account" />
                             <element name="days" type="xsd:int" />
                         </sequence>
                     </complexType>
                 </element>
                 <element name="computeAccountAverageResponse">
                     <complexType>
                         <sequence>
                             <element name="return" type="xsd:float" />
                         </sequence>
                     </complexType>
                 </element>
    
                 <complexType name="Account">
                     <attribute name="accountNumber" type="xsd:int" />
                     <attribute name="accountID" type="xsd:string" />
                     <attribute name="accountType" type="xsd:string" />
                     <attribute name="balance" type="xsd:float" />
                 </complexType>
    
              </schema>
         </wsdl:types>
    
         <wsdl:message name="computeAccountAverageRequest">
             <wsdl:part element="account:computeAccountAverage"
                 name="parameters" />
         </wsdl:message>
    
         <wsdl:message name="computeAccountAverageResponse">
             <wsdl:part element="account:computeAccountAverageResponse"
                 name="parameters" />
         </wsdl:message>
    
         <wsdl:portType name="AccountService">
             <wsdl:operation name="computeAccountAverage">
                 <wsdl:input message="account:computeAccountAverageRequest" name="accountReq"/>
                 <wsdl:output message="account:computeAccountAverageResponse" name="accountResp"/>
             </wsdl:operation>
         </wsdl:portType>
    
         <wsdl:binding name="AccountServiceSOAP" type="account:AccountService">
             <soap:binding style="document"
                 transport="http://schemas.xmlsoap.org/soap/http" />
             <wsdl:operation name="computeAccountAverage"> 
                <soap:operation
                     soapAction="computeAccountAverage" />
                 <wsdl:input name="accountReq"> 
                    <soap:body use="literal" />
                 </wsdl:input>
                 <wsdl:output name="accountResp">
                     <soap:body use="literal" />
                 </wsdl:output>
             </wsdl:operation>
    
          </wsdl:binding>
    
         <wsdl:service name="AccountWSDLService">
             <wsdl:port binding="account:AccountServiceSOAP"
                 name="AccountServicePort">
                 <soap:address location=""/>
             </wsdl:port>
         </wsdl:service>
    </wsdl:definitions>
  2. 跑过wsimport命令来自应用程序服务器根目录/bin/目录。
    [Windows]
    app_server_root\bin\wsimport.bat -keep -verbose account.wsdl
    [Linux][AIX][HP-UX][Solaris]跑过wsimport命令,
    app_server_root/bin/wsimport.sh -keep -verbose account.wsdl 
    [IBM i]
    app_server_root/bin/wsimport -keep -verbose account.wsdl
    使用 wsimport 命令生成模板文件后,将生成下列 Java 文件:
    com/myaccount/account/Account.java
    com/myaccount/account/AccountService.java
    com/myaccount/account/AccountWSDLService.java
    com/myaccount/account/ComputeAccountAverage.java
    com/myaccount/account/ComputeAccountAverageResponse.java
    com/myaccount/account/ObjectFactory.java
    com/myaccount/account/package-info.java
  3. 通过生成的类来标识生成的 Java 接口。
    //
    // Generated By:JAX-WS RI IBM 2.1.1 in JDK 6 (JAXB RI IBM JAXB 2.1.3 in JDK 1.6)
    //
    package com.myaccount.account;
    ...
    @WebService(name = "AccountService", targetNamespace = "https://www.myaccount.com/account")
    …
    public interface AccountService {
        /**
         *
         * @param days
         * @param account
         * @return
         *     returns float
         */
        @WebMethod(action = "computeAccountAverage")
        @WebResult(targetNamespace = "")
        @RequestWrapper(localName = "computeAccountAverage", targetNamespace = "https://www.myaccount.com/account",
                className = "com.myaccount.account.ComputeAccountAverage")
    
        @ResponseWrapper(localName = "computeAccountAverageResponse", targetNamespace = "https://www.myaccount.com/account",
                className = "com.myaccount.account.ComputeAccountAverageResponse")
        public float computeAccountAverage(
            @WebParam(name = "account", targetNamespace = "")
            Account account,
            @WebParam(name = "days", targetNamespace = "")
            int days);
    
    }

    这个代码示例是一个 Java 接口,而不仅仅是一个 Java 类。 @WebService 注释存在于此 Java 接口中。 必须了解本示例与生成的 @WebServiceClient 类 (com.myaccount.account.AccountWSDLService) 不同,此类不是接口且不为 SCA 应用程序所需。

  4. 通过编写此生成的 Java 接口的 Java 实现来完成 SCA 服务的实现。 确保将 SCA @Service 注释添加到实现。
    package com.myaccount.account;
    import org.osoa.sca.annotations.Service;
    @Service(AccountService.class) 
    public class AccountServiceImpl implements AccountService
        public float computeAccountAverage( Account account, int days) {
    
            // Write your business logic here.  Account is a 
            // generated JAXB type and so use the JAXB programming model. 
            // For example, object instantation is performed using  
            // the ObjectFactory.createAccount()) method. 
        }
    }

    在完成此步骤后,您就完成了组件实现。 此组件实现不仅是 Java 接口的 Java 实现,而且 @Service 注释还表明这是一个 SCA 服务接口的 Java 组件实现。 实现类本身并不需要所有 JAX-WS 或 JAXB 注释。 运行时环境会从实现所引用的生成类中装入相应的注释。

  5. 使用组件实现来创建组件。 在对原始 WSDL portType 接口和 SCA 实现进行引用的组合中,创建组件定义。 在 SCA 中,组件是已配置的组件实现实例。 此处未显示其他关于定义组件的方面,例如,配置绑定、配置属性值、定义意向、连接策略集以及解析引用。 此处显示的组件创建方面,对于使用在本示例中开发的实现的所有组件定义是通用的。 本示例也包括您可以针对其他使用此组件实现的组件,修改或省略的绑定。
    <?xml version="1.0" encoding="UTF-8"?>
    
    <composite xmlns="https://www.osoa.org/xmlns/sca/1.0"
         targetNamespace="http://account.customer"
             name="accountComposite">
         <component name="BankingComponent">
             <implementation.java class="com.myaccount.account.AccountServiceImpl"/>
    
             <!-- The @name value matches the contents of the @Service which in turn
                  comes from the WSDL portType. -->
    
             <service name="AccountService">
    
                  <!-- This statement specifies the QName of the WSDL portType,
                        “https://www.myaccount.com/account#AccountService” in the syntax as 
                        illustrated in the interface.wsdl statement. -->
    
                 <interface.wsdl interface="https://www.myaccount.com/account#wsdl.interface(AccountService)" />
                 <binding.ws/>
    
      <!-- This example uses the SCA web services binding.  However, it does not matter which SCA binding
           you choose.  -->
    
              </service>
         </component>
    </composite>
  6. 在直接或递归地通过将组件的一个或多个层与组合实现配合使用,以将组件定义为可部署组合的一部分之后,就可通过创建 SCA 业务级应用程序来部署 SCA 服务。