使用 IBM BPM Advanced Integration Service 开发分布式 WS-AT 事务,第 2 部分: 配置事务支持

本系列文章介绍了如何利用 IBM Business Process Manager V8.0.1 Advanced 中的 Advanced Integration Services (AIS) 功能实现一个分布式 WS-AT 场景,该场景涉及两个不同的数据库(Microsoft® SQL Server 和 IBM® DB2®),它们安装在两个不同的机器上,可通过两个 Web 服务对它们进行访问。该实现演示了一些自动回滚功能,这些功能由 AIS 中基于 SCA 的管理与 WS-AT 协议协同提供。在第 2 部分中,您将为示例场景中的 Credit 和 Charge 操作配置事务支持,并实现两个事务 Web 服务(一个使用 .NET® 实现,另一个使用 JEE 实现)。

Carlo Randone, 认证 IT 架构师 , IBM

Carlo Randone 是位于意大利的 IBM 全球企业咨询服务部的一名 IBM 认证 IT 架构师和 Open Group Master 认证 IT 架构师。Carlo 拥有在异构环境和操作系统上使用不同开发平台和中间件的丰富知识。作为一位经过认证的培训师和软件开发人员,他曾为一家 Microsoft® 认证的合作伙伴工作多年。

自 2000 年加入 IBM 以来,Carlo 的主要工作兴趣涉及 SOA 和 BPM、与它们相关的软件工程方法和支持平台,以及企业架构规划和设计。他喜欢收集与 IT 的历史发展相关的文档和硬件零部件,而且为了支持这一爱好,他成为了 Charles Babbage Institute 的一员。



2013 年 12 月 26 日

简介

本系列的第 2 部分将会介绍为示例场景中的 Credit 和 Charge 操作配置事务支持并实现两个事务 Web 服务的步骤:一个 .NET Web 服务,用于从机器 A 上的 SQL Server 上的 Bank1 扣取资金,一个 JEE Web 服务,用于向机器 B 上的 DB2 上的 Bank2 贷入资金。

我们将介绍以下步骤:

  1. 配置安全性证书。我们将在 Windows .NET 机器 A 上创建一个证书并将它导入 WebSphere 机器 B 中,然后在 WebSphere 机器 B 上创建一个证书并将它导入 Windows .NET 机器 A 中。
  2. 在 WebSphere 机器 B 上配置 MSDTC 和 WS-AT。
  3. 在 Windows 机器 A 上的 WebSphere 中配置事务支持。

配置安全性证书

如 IBM developerWorks 文章 在 WebSphere Application Server 和 Microsoft .NET 中使用 WS-AtomicTransaction 构建事务 Web 服务使用 WS-Atomic 事务实现 WebSphere ESB 服务网关和 Microsoft .NET WCF 之间的互操作性(以及 MSDN 上为基于解决方案的 .NET 的部分 配置 WS-Atomic Transaction 支持)中所述,WS-AT 协议服务需要管理员显式创作各个帐户来参与分布式事务。我们在示例场景中将配置机器 A 和 B,通过交换正确的证书集,将它们安装在合适的证书库中,以及使用合适的工具将每个机器的证书添加到另一个机器的授权参与者证书列表中,从而建立一种相互信任关系。这一步对使用 WS-AT 在两个机器之间执行分布式事务很有必要。WebSphere Application Server 支持安全或非安全的事务协议消息(比如 Register、Prepare、Commit、Rollback)交换。本文中给出的场景需要使用 SSL 相互身份验证保护协议消息。这意味着您需要配置 SSL 安全性并设置证书,WS-AT 才能跨两个平台操作。

在生产环境中,将为每个参与者使用来自一个公认证书颁发机构的一个证书。但是,为了保持此示例的简单性,我们将为 Windows .NET 和 WebSphere 生成一个自签名证书。

在本节中,我们将在机器 A 和 B 之间建立一种相互信任关系。这是一种完整的配置,对我们希望在 A 与 B 之间建立完全双向的事务上下文传播能力的测试环境很有用。在这里描述的场景中,事务协调器是服务器 B 上的 WebSphere 事务服务,一个参与者是机器 A 上的 Microsoft Distributed Transaction Coordinator (MSDTC)。

在 Windows .NET 机器 “A” 上创建一个证书并导入 WebSphere 机器 “B” 中

  1. 使用命令行工具 makecert(包含在 Windows 软件开发工具包 中)为 Windows 7 机器创建一个证书颁发机构,如下所示:
    makecert –sk testRootCA –sky signature –sr localmachine –n "CN=RootTrustedCA" 
    –ss TRUST –r RootTrustedCA.cer
  2. 基于该证书颁发机构创建一个可只想能够密钥交换的证书,如下所示:
    makecert –sk testServer –ss MY –sky exchange –sr localmachine –n "CN=myW7host" 
    –ic RootTrustedCA.cer –is TRUST myW7host.cer

    完成后,您将有一个 myW7host.cer 证书,您可在以后将它导入 WebSphere 机器 B 中。

  3. 但是首先,您需要使用设计来管理数字证书的 Microsoft Management Console (MMC) 管理单元,将此证书导入机器 A 的 Windows 证书库中。如果已配置了一个 Certificates 管理控制台管理单元,则可跳过前 5 步:
    1. 选择 Windows Start
    2. 在 Start 搜索框中,键入 mmc,然后选择 mmc.exe 并单击 Enter
    3. 选择 File => Add/Remove Snap-in
    4. 选择 Certificates 并单击 Add
    5. 选择 Computer Account,然后选择 Next 并确保已选择了 Local computer,然后单击 FinishOK。图 1 显示了包含 Certificates 管理单元的控制台。
      图 1. 包含 Certificates 管理单元的管理控制台
      包含 Certificates 管理单元的管理控制台

      点击查看大图

      图 1. 包含 Certificates 管理单元的管理控制台

      包含 Certificates 管理单元的管理控制台
    6. 右键单击 Trusted Root Certification Authorities 并选择 All Tasks => Import
    7. 执行向导,选择证书颁发机构文件名,比如 RootTrustedCA.cer
    8. 右键单击 Personal 并选择 All Tasks => Import
    9. 完成向导,选择密钥交换证书文件名,比如 myW7host.cer
  4. 您现在可将 Windows 机器 A 的证书导入机器 B 上的 WebSphere 信任库中了:
    1. 将 Windows 证书(比如 myW7host.cer)复制或共享到机器 B。
    2. 启动 BPM 机器 B 上的 WebSphere 管理控制台 (WebSphere Integrated Solutions Console)。
    3. 选择 Security => SSL certificate and key management
    4. 在右侧,单击 Key stores and certificates
    5. 选择 NodeDefaultTrustStore
    6. 在右侧,单击 Signer certificates
    7. 单击 Add
    8. 指定一个证书别名,比如 myW7host,然后在 File name 字段中,键入证书文件的完整路径。单击 OK,然后单击 Save

在 WebSphere 机器上定义一个证书并将它导入 Windows .NET 机器中

使用管理控制台在 WebSphere 机器 B 上创建一个自签名证书,如下所示:

  1. 选择 Security => SSL certificate and key management => Key stores and certificates => NodeDefaultKeyStore => Personal certificates => Create a self-signed certificate
  2. 指定以下设置,然后单击 OK
    • Alias = <your_hostname> (for example IBMBPM)
    • Common Name = <your_hostname> (for example IBMBPM)
    • Organization = <your_organization_name>
  3. 单击 Save Changes to Master Configuration
  4. 要将新创建的证书设置为默认证书,可选择 Security => SSL certificate and key management => SSL configurations => NodeDefaultSSLSettings,然后为 Default server certificate aliasDefault client certificate alias 选择新创建的证书(例如 IBMBPM),然后单击 OK
  5. 要将签名者证书导入到信任库中,可选择 Security => SSL certificate and key management => Key stores and certificates,然后同时选择 NodeDefaultKeyStoreNodeDefaultTrustStore 并单击 Exchange signers>
  6. 选择新创建的证书,单击 Add,然后单击 OK,将它添加到 NodeDefaultTrustStore 中。
  7. 将 WebSphere 机器 B 证书导入到 Windows 机器 A 中,如下所示:
    1. 将 WebSphere Application Server 密钥库和信任库(key.p12 和 trust.p12,通常位于 %WAS_HOME%\profiles\<your-server>\config\cells\<your-cell>\nodes\<your-node> 中)复制或共享到 Windows 机器 A。
    2. 要使用 MMC 将 WebSphere 密钥库 key.p12 导入到 Windows 机器 A 的个人证书库中,可展开 Certificates, Personal,然后选择 Action => All Tasks => Import => Next => Browse,然后从上一步中选择的文件夹中选择 key.p12 文件。
    3. 指定以下设置:
      • Filename = <the key.p12 file>
      • Password = WebAS(密钥库的默认密码)
      • 通过选择 Personal 作为证书库,将该证书放在 Personal Certificate Authority 中。
    4. 要在 MMC 中将 WebSphere Application Server 密钥库 (key.p12) 和信任库 (trust.p12) 都导入 Windows Trusted Root Certification Authorities 库中,可展开 Certificates, Trusted Root Certificate Authority,然后选择 Action => All Tasks => Import => Next => Browse,随后从步骤 a 中选择的文件夹中选择 key.p12 文件。指定以下设置:
      • Filename = <the key.p12 file>
      • Password = WebAS
      • 通过选择 Trusted Root Certificate Authority 作为证书库,将该证书放在 Trusted Root Certificate Authority 中。
    5. 仍然在 Certificates, Trusted Root Certificate Authority 下,选择 Action => All Tasks => Import => Next => Browse,然后从步骤 a 中选择的文件夹中选择 trust.p12 文件。指定以下设置:
      • Filename = <the trust.p12 file>
      • Password = WebAS
      • 通过选择 Trusted Root Certificate Authority 作为证书库,将该证书放在 Trusted Root Certificate Authority 中。

在 Windows 机器上配置 MSDTC 和 WS-AT

必须配置 Microsoft Distributed Transaction Coordinator (MSDTC) 来支持 XA 事务协议,然后才能与 WebSphere Application Server 通信,还必须启用 WS-AT 协议。MSDTC 针对 XA 的初始配置已在第 1 部分中的 为 MSDTC 服务启用 XA 事务 中介绍。

配置 MSDTC 来支持 WS-AT 协议,需要在 DTC 配置工具中存在一个特定的 WS-AT 选项卡,如图 2 所示。

图 2. 在 MSDTC 中配置 WS-AT
在 MSDTC 中配置 WS-AT

如果 Windows 系统上的 DTC 配置工具中不存在 WS-AT 选项卡,可运行以下命令:regasm.exe /codebase WsatUI.dll。regasm.exe 命令位于 C:\Windows\winsxs 中。WsatUI.dll 是 Windows 软件开发工具包 的一部分。WsatUI 的安装过程已在 WS-AtomicTransaction 配置 MMC 管理单元 中详细介绍。

要配置 WS-AT 支持,如 中所示,可执行以下操作:

  1. 勾选 Enable WS-Atomic Transaction network support,保留默认值 443 作为 HTTPS 端口。
  2. Endpoint certificates 字段中,选择新导入的证书(来自 WebSphere 机器 B,使用您的主机名作为别名),然后单击 OK
  3. Authorized certificates 字段中,单击 Select 并选择 WebSphere 证书和 Windows 证书(在本演示中为 myW7host),然后单击 OK
  4. 单击 OK 并根据提示重新启动 MSDTC。

在 WebSphere 机器上配置事务支持

完成以下步骤,在 WebSphere 机器 B 上配置 WebSphere 事务服务(参见 图 3):

  1. 在 WebSphere 管理控制台中,选择 Servers => Server Types => WebSphere application servers => server1(或您的服务器的名称)=> Container Services => Transaction Service。单击 Configuration 选项卡。
  2. 取消选择 Enable transaction coordination authorization。必须禁用此选项才能实现互操作性。协议消息将仍使用 SSL 传输级安全性来保护,但禁用了收到的协议消息的基于角色的授权。仅在 WebSphere 与 WebSphere 的交互中支持对事务协议消息执行基于角色的授权。启用事务协调授权时,事务服务会验证调用方法是否拥有管理员角色的权限,然后再处理该事务。
  3. 对于 Default WS-Transaction specification level,可选择 1.1(我们的示例场景基于一个利用了其他 V1.1 版 WS-AT 规范的 WS-AT 实现)。
  4. 保存您的更改,停止并重新启动 BPM WebSphere Application Server。对于独立场景,可以重新启动该服务器,而对于网络部署,您需要重新启动整个单元。
图 3. 在 WebSphere Application Server 上配置事务服务设置
在 WebSphere Application Server 上配置事务服务设置

配置事务 Web 服务

本系列中给出的场景使用了两个事务 Web 服务,以便从 SQL Server 数据库 Bank1 上的某个帐户转账到 DB2 数据库 Bank2 上的另一个帐户。Charge Web 服务在机器 A 上是使用 .NET 和 IIS(Internet 信息服务)实现的,Credit Web 服务在机器 B 上使用了 JAX-WS 和 WebSphere Application Server 实现(请注意,在我们的场景中,这个 Web 服务部署在与 BPM 引擎相同的 WebSphere Application Server 和相同机器上,但它也可以部署在该网络上一个可访问的不同 WebSphere 机器上)。

配置 .NET Web 服务以便从 Bank1 中扣费

这个事务场景中涉及的两个 Web 服务中的第一个服务是使用 C# (C-Sharp)(一种 .NET 语言)在 Microsoft Visual Studio 2010 开发环境中开发的。用来实现此 Web 服务的 .NET 库是 Windows Communication Foundation (WCF),它包含在 .NET Framework 4 中。WCF 是 .NET Framework 中的一个运行时和一组 API,用于构建互联、面向服务的应用程序。在 Microsoft .NET 平台上实现 Web 服务有两个主要选择:旧有 ASP.NET 方法和较新的基于 WCF 的方法。在我们的场景中,考虑到支持 WS-AT V1.1 和提供最新的版本和解决方案设计的需求,我们选择利用新的基于 WCF 的方法。

该 Web 服务设计用来在 SQL Server 数据库上实现一个 Charge 操作。该 Web 服务在一个 C# 项目 WSChargeBank1 中一个名为 Visual Studio 2010 解决方案中实现(第 1 部分 中提供了可供下载的 WSChargeBank1Soln.zip)。

清单 1 显示了该 Web 服务 C# 实现。

清单 1. Charge Web 服务(使用 C# 和 .NET WCF 实现)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Data.SqlClient;
using System.Web;
using System.Web.Services;


namespace WSChargeBank1
{
 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
 [ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable,
     ConcurrencyMode = ConcurrencyMode.Single,
     InstanceContextMode = InstanceContextMode.PerSession,
     ReleaseServiceInstanceOnTransactionComplete = true)]
 public class WSChargeBank1Svc : IWSChargeBank1Svc
 {
     [WebMethod(false, System.EnterpriseServices.TransactionOption.Required)]
     // Use:
     // [TransactionFlow(TransactionFlowOption.Allowed)] to enable discovery and run in a non 
     // transational client
     // [TransactionFlow(TransactionFlowOption.Mandatory)] to allow ONLY transactional clients
     [TransactionFlow(TransactionFlowOption.Mandatory)]
     [OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
     public string Charge(string myConnection, string myTable, string myAccount, int myAmount)
     {
         string strSQL;
         string result = "Result OK from Charge operation";
         int HowManyRows;
         SqlConnection sqlConn=null;
         SqlCommand sqlComm;

         strSQL = "UPDATE " + myTable + " SET Amount = Amount - ";
         strSQL += myAmount.ToString();
         strSQL += " WHERE Description = '" + myAccount + "'";

         try
         {
             sqlConn = new SqlConnection(myConnection);
             sqlComm = new SqlCommand(strSQL, sqlConn);
             sqlConn.Open();
             HowManyRows = sqlComm.ExecuteNonQuery();
             if (HowManyRows != 1)
             {
                 // Invalid account
                 throw new Exception("Exception from Charge (-): Invalid account.");
             }
             sqlComm.Dispose();
             sqlConn.Close();
             return (result);
         }
         catch (Exception ex)
         {
             if (sqlConn != null)
             {
                 if (sqlConn.State == System.Data.ConnectionState.Open)
                 {
                     sqlConn.Close();
                 }
             }
             result = "Exception from Charge (-): myConnection: " + myConnection +"; strSQL: " 
                + strSQL + "; ex.Message: " + ex.Message;
             throw new FaultException(result);
         }
     }

 }
}

该 Web 服务的事务选项是在代码和配置文件中被声明和支持的。在上面的清单中,使用了属性 [TransactionFlow(TransactionFlowOption.Mandatory)] 来指定一个服务操作的事务流策略。由于使用了 Mandatory 设置,该事务必须执行。

请注意以下语句:

HowManyRows = sqlComm.ExecuteNonQuery();
if (HowManyRows != 1)
{
   // Invalid account
   throw new Exception("Exception from Charge (-): Invalid account.");
}

它们用于检查 execute 命令是否未返回任何行;例如,在该语句未在任何记录上执行时(通常由于 myAccount 参数中传递给 Charge 操作的帐户不可用)。在这种情况下,会抛出一个显式异常 Exception 和字符串 Invalid account。稍后,这种类型的异常或其他任何异常(例如帐户上的金额不足,由 SQL Server 数据库引擎触发)会由 FaultException 返回。在一个服务中,您可以使用泛型 FaultException 类来创建一个无类型的错误,以返回到客户端。另一个选择是将服务设计为返回强类型的 SOAP 错误,使用一个 FaultContractAttribute 来声明一个或多个特定的异常条件,这些条件被添加到服务操作的 WSDL 描述中,作为该操作返回的显式 SOAP 错误消息。

这个 Web 服务没有公开任何具体的 SOAP 错误,而且在服务的使用者中(在本场景中,为 BPM AIS 中的一个 SCA 中介模块),将会有一个无模型的错误管理功能。

Web.config Web 服务配置文件,如 清单 2 中所示,包含更多密钥配置。

清单 2. Charge Web 服务配置文件
<?xml version="1.0"?>
<configuration>
    
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <!-- <add assembly="System.Transactions, Version=4.0.0.0, Culture=neutral, 
PublicKeyToken=B77A5C561934E089"/> -->
      </assemblies>
    </compilation>
    
    <webServices>
      <protocols>
        <add name="AnyHttpSoap"/>
      </protocols>
    </webServices>
    
  </system.web>
  <system.serviceModel>
        
    <!-- Extension for single WSDL with inline schemas, from http://wcfextras.codeplex.com/ -->
    <extensions>
      <behaviorExtensions>
        <add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, WCFExtrasPlus" />
      </behaviorExtensions>
    </extensions>
    <!-- -->
    
    <services>
      <service name="WSChargeBank1.WSChargeBank1Svc">
        <endpoint address="" binding="customBinding" 
		bindingConfiguration="customBinding_IWSChargeBank1Svc"
          contract="WSChargeBank1.IWSChargeBank1Svc" 
		behaviorConfiguration="singleFileEndpointBehavior">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    
    <bindings>
    
      <customBinding>
        <binding name="customBinding_IWSChargeBank1Svc">
          <textMessageEncoding messageVersion="Soap11" />
          <!-- -->
          <!-- WS-AT 1.0 -->
          <!--
          <transactionFlow transactionProtocol="WSAtomicTransactionOctober2004" />         
          -->
          <!-- WS-AT 1.1 -->
          <transactionFlow transactionProtocol="WSAtomicTransaction11" />
          <!-- -->
          <!-- -->
          <httpTransport />
        </binding>
      </customBinding>

    </bindings>
    
    <behaviors>

      <endpointBehaviors>
        <behavior name="singleFileEndpointBehavior">
          <wsdlExtensions singleFile="True" />
        </behavior>
      </endpointBehaviors>
      
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and 
                  remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value 
                  below to true.  
                  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

代码部分:

<extensions>
 <behaviorExtensions>
  <add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, 
	WCFExtrasPlus" />
 </behaviorExtensions>
</extensions>

与以下声明结合使用:

<endpointBehaviors>
 <behavior name="singleFileEndpointBehavior">
  <wsdlExtensions singleFile="True" />
 </behavior>
</endpointBehaviors>

支持使用一个免费库(名为 WCFExtras,可在 http://wcfextras.codeplex.com/ 上找到),这里使用这个库来增强这个 Web 服务实现所生成的 WSDL 代码的可移植性。具体来讲,WCFExtras 中的一个功能是将外部类型合并到 WSDL 文件中,生成一个包含所有必须定义的平面 WSDL 文件。此配置显然不是强制性的,但它是 .NET/WCF 4.5 中一个有趣功能,该功能现在已包含在该平台中,不需要采用 WCFExtras 这样的外部库(请参阅 Windows Communication Foundation 4.5 中的新功能)。WCF 4.5 允许指定所有 WSDL 信息必须在单个文档中返回。要请求单个 WSDL 文档,可在从服务请求元数据时将 ?singleWSDL 附加到 URI。

配置部分:

<customBinding>
        <binding name="customBinding_IWSChargeBank1Svc">
          <textMessageEncoding messageVersion="Soap11" />
          <!-- -->
          <!-- WS-AT 1.0 -->
          <!--
          <transactionFlow transactionProtocol="WSAtomicTransactionOctober2004" />         
          -->
          <!-- WS-AT 1.1 -->
          <transactionFlow transactionProtocol="WSAtomicTransaction11" />
          <!-- -->
          <!-- -->
          <httpTransport />
        </binding>
      </customBinding>

定义了一个与 SOAP 1.1 和新 WS-AT V1.1 (WSAtomicTransaction11) 的自定义绑定。注释掉的 XML 代码与 1.0 版的旧规范相关。我们的场景基于 SOAP 1.1 和 WS-AT 1.1,而且机器 B 上的 WebSphere 配置将被设置为 WS-AT 1.1。(请注意,实际上,1.2 版的 WS-AT 标准在功能上与 V1.1 等效,但这些版本与 1.0 版相比有着显著的区别)。

此 Web 服务的 Visual Studio 项目也部署在 Windows 机器 A 上的本地 IIS 中。举例而言,如果 .NET Web 服务项目是 C:\Projects\WSChargeBank1Soln\WSChargeBank1,那么您需要创建一个新应用程序 WSChargeBank1,如 图 4 中所示。

图 4. IIS 中的 Web 服务应用程序 WSChargeBank1
IIS 中的 Web 服务应用程序 WSChargeBank1

图 5 显示了这种类型的 Web 应用程序的高级设置,该应用程序被配置用来托管 .NET Web 服务。

图 5. 在 IIS 上配置 Web 服务应用程序
在 IIS 上配置 Web 服务应用程序

公开的 Web 服务端点位于 http://<<machineA>>/WSChargeBank1/WSChargeBank1Svc.svc 上(可认为 <<machine A>> 是 Windows/.NET/SQL Server 机器的真实名称的占位符)。WSDL 已在 http://<<machineA>>/WSChargeBank1/WSChargeBank1Svc.svc?wsdl 上公开。

配置 JEE Web 服务来向机器 B 上的 Bank2 贷入资金

我们的事务场景中涉及的两个 Web 服务中的第二个服务使用了 Java® 和 IBM Integration Designer(包含在 IBM BPM 中)实现。该 Web 服务使用 Integration Designer 所提供的 JAX-WS 支持功能和 WebSphere 运行时平台来实现。Java API for XML web services(JAX-WS,JSR-224)是一种用于创建 Web 服务的 Java 编程语言 API,它包含在 Java EE 平台中。

JAX-WS 是一个编程模型,它简化了应用程序开发,支持使用某种标准的、基于注释的模型来开发 Web 服务应用程序和客户端。JAX-WS 定义了一个模型,以便使用 Java 注释来开发 Web 服务提供程序和 Web 服务客户端。此外,与 JAX-RPC 相比,因为无需使用任何特定于供应商的工件,JAX-WS Web 服务客户端和 Web 服务提供程序更容易移植。JAX-WS 技术在战略上与如今更加以文档为中心的消息模型发展的行业趋势相一致,取代了 JAX-RPC 所定义的远程过程调用编程模型。IBM 红皮书 IBM WebSphere Application Server V7.0 Web 服务指南 深入介绍了在 WebSphere Application Server 上开发 JAX-WS Web 服务的方法。

该 Web 服务被设计用来在 DB2 数据库上实现一个 Credit 操作,它在一个名为 WSCreditBank2Project 的 IBM Integration Designer 项目(位于 WSCreditBank2Project.zip 中,可在 第 1 部分 中下载)中实现。

清单 3 显示了该 Web 服务的 Java 实现。

清单 3. Credit Web 服务(使用 Java 和 JAX-WS 实现)
package org.tempuri;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;


@javax.jws.WebService (endpointInterface="org.tempuri.IWSCreditBank2Svc", 
targetNamespace="http://tempuri.org/", serviceName="WSCreditBank2Svc", 
portName="CustomBinding_IWSCreditBank2Svc")
public class CustomBinding_IWSCreditBank2SvcImpl{

    public String credit(String myConnection, String myTable, String myAccount, 
        Integer myAmount) throws Exception  
    {
    	String result = "Result OK from Credit operation";
        int HowManyRows;
    
        /**/
        // Credit (+) (on Bank2 DB) operation
        
        Context ctx = null;
        DataSource ds = null;
        Connection  con = null;		
        String strSQL;

        strSQL = "UPDATE " + myTable + " SET Amount = Amount + ";
        strSQL = strSQL + String.valueOf(myAmount);
        strSQL = strSQL + " WHERE Description = '" + myAccount + "'";

      try
      {
          ctx = new InitialContext();
          ds = (DataSource) ctx.lookup(myConnection);
          con = ds.getConnection();
          
          Statement stmt = con.createStatement();
          
          HowManyRows = stmt.executeUpdate(strSQL);
          if (HowManyRows!=1)
          {
                 // Invalid Account
                 throw new Exception("Exception from Credit (+): Invalid account.");
          }
          
      }
      catch(Exception ex)
      {   
             result = "Exception from Credit (+): myConnection: " + myConnection +
             "; strSQL: " + strSQL + "; ex.getMessage(): " + ex.getMessage();
             //ex.printStackTrace();
             throw new Exception(result, ex);
      }
      finally
      {
          if (ctx!=null)
          {
             try {ctx.close();}
             catch(javax.naming.NamingException ex2){}
          }
          try
          {
             if(con!=null && !con.isClosed())
             {
                 con.close();     
             }
          }
          catch (SQLException e)
          {
             // ignore
            
          }
      }         
      /**/
            return(result);
     }

}

Accounts 表上的 Update 操作按照传统的 JEE 执行路径来实现,通过在 Context 上进行查找,可以获取一个 DataSource,然后通过 DataSource 上的一个 getConnection 来建立连接,最后使用 createStatement(在 Connection 对象上)和 ExecuteUpdate(在 Statement 对象上)方法。

请注意以下语句:

HowManyRows = stmt.executeUpdate(strSQL);
if (HowManyRows!=1)
{
   // Invalid Account
   throw new Exception("Exception from Credit (+): Invalid account.");
}

它们用于检查 execute 命令是否未返回任何行;例如,在该语句未在任何记录上执行时(通常由于 myAccount 参数中传递给 Credit 操作的帐户不可用)。在这种情况下,会抛出一个异常和字符串 Invalid account。这个异常和其他任何异常由 catch(Exception ex) 捕获处理程序捕获,该处理程序随后再将这些异常抛出给调用方(在本例中为 ESB 中介模块)。

这个 Web 服务公开了一个特定的 SOAP 错误(可查看 WSDL 来检验),而且在服务的使用者中(在我们的场景中为 BPM AIS 中的一个 SCA 中介模块),将会有一个建模的错误管理功能。

公开的 Web 服务端点位于 http://<<machineB>>:9080/WSCreditBank2Project/WSCreditBank2Sv 上(可将这里的 <<machine B>> 视为 WebSphere DB2 机器的真实名称的一个占位符),WSDL 位于 http://<<machineB>>:9080/WSCreditBank2Project/WSCreditBank2Svc?wsdl 上。


结束语

本系列的第 2 部分介绍了事务支持的配置和两个事务 Web 服务的实现(针对 Credit 和 Charge 操作),这两个服务分别基于 JEE 和 .NET 技术。在第 3 部分中,您将学习如何使用 IBM Business Process Manager Advanced 中的 IBM Process Designer 定义和实现 BPMN 业务流程。


致谢

感谢同事 Giuseppe Bottura 和 Simone Chiucchi 审阅本文,感谢同事 Stefano Angrisano、Matteo Franciolli 和 Daniele Rossi 对本文所做的贡献。还要感谢 Andrew J. Howes、Billy Lo、Frank I. Toth、Dave Screen、Callum Jackson、Konstantin Luttenberger 和 Oliver Rebmann 提供富有启发性的、引人深思的 developerWorks 文章。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=958557
ArticleTitle=使用 IBM BPM Advanced Integration Service 开发分布式 WS-AT 事务,第 2 部分: 配置事务支持
publish-date=12262013