在表示层集成 .NET
 

2010-02-23 来源:microsoft.com

 

摘要: 使用 XBikes 示例来说明在希望集成 ASP.NET 表示层的同时,如何保持现有的 J2EE 业务层。这可使公司保留其在 J2EE 上的现有投资,并利用 ASP.NET 提供的丰富的客户端体验。

本页内容
简介 简介
使用 Web 服务来达到互用性 使用 Web 服务来达到互用性
使用 JNBridgePro 来实现互用性 使用 JNBridgePro 来实现互用性
使用 Ja.NET 来实现互用性 使用 Ja.NET 来实现互用性
小结 小结
参考资料 参考资料
 

简介

您现在应该了解 XBikes 应用程序的体系结构和 XBikes 使用的互用性技术。在本章中,您可以查看允许 XBikes 开发人员通过集成 ASP.NET 表示层应用程序和 J2EE 业务层来实现互用性的代码细节。

向 J2EE 应用程序添加 ASP.NET 表示层时,无论决定使用哪种技术,均需注意三个方面:

  • 用于互用性的数据格式。
  • 如何在J2EE 应用程序中设计和构建服务接口。
  • 如何在 .NET Framework 应用程序中设计和构建互用性适配器。

决定最适合您的项目的互用性技术时,需要考虑几个因素。性能、符合标准以及成本只是影响选择的因素中的一部分,并且每种选择都有其优缺点。

Web 服务提供了一个行业标准解决方案,该方案受多种平台(包括 .NET 和 Java)的多数供应商支持。然而,作为比较简单的实现方案,Web 服务不提供第三方二进制互用性技术的实现。

JNBridge 的 JNBridPro 和 Intrinsyc 的 Ja.NET 均提供高性能及高可控性的二进制解决方案,尽管它们不完全符合公开的行业标准。

除非性能是首要要求,否则请选择 Web 服务作为互用性技术。这是因为 Web 服务符合公开的标准,并且是确保与未来应用程序和行业开发互用性的最好方法。

有关选择互用性技术的详细论述,请参阅第 3 章到第 5 章。

确定数据交换格式和类型

从第 3 章“互用性基本原理”可知,Java 和 .NET 复杂数据类型不太可能在两个平台之间相关联。其中还论述了通过使用由通用 XML 架构生成的自定义序列化类,来创建通用格式以用于在两个平台间交换数据的可能性。

在第4章“互用性技术:点对点”中,讲述了 Ja.Net 和 JNBridgePro 如何为 .NET Framework 应用程序随后使用的 Java 数据类创建代理。虽然这是从 Java 和 .NET 得到数据的两种有效解决方案,但是在 .NET 表示层内使用自定义数据类或者代理 Java 类或许并非所需。可能您希望使用本机 .NET 数据类型(例如类型化 DataSet)来利用 ASP.NET 提供的多种功能(如数据绑定)。

为了解决这个问题,需要在 Java 端将 Java 数据打包成用于 .NET 的格式,或发送 Java 数据并在 .NET 端将其重新打包。为此,服务接口和互用性适配器可能需要操作数据。在 XBikes 应用程序中,映射技术根据互用性技术而有所不同。

有关数据交换因素的详细论述,请参阅第 3 章。

设计和构建服务接口

XBikes 示例应用程序遵循第 6 章“实现互用性设计元素”中所述的最佳实践,因此访问业务层是通过会话 bean BusinessServiceFacade 实现的。为了向 .NET Framework 应用程序公开此功能,开发人员创建了一个公开 BusinessServiceFacade 的服务接口。根据使用的互用性技术,这个服务接口类或者 直接调用现有的服务外观,或者 在调用服务外观前操作数据。此外,在返回路径上,服务接口直接将数据返回到服务接口调用方,或在返回数据前对其进行操作。此安排如图 7.1 所示。

7.1 通过实现服务接口和服务外观来将 J2EE 业务层链接到 .NET 表示层。

有关服务接口的详细论述,请参阅第 6 章。

设计和构建互用性适配器

在 XBikes 应用程序中,开发人员为每个用例创建一个互用性适配器。这个选择允许在用例级别挑选互用性技术。

在用例级别实现互用性适配器主要用于演示。您的应用程序可能不需要此粒度级别。图 7.2 显示了将 ASP.NET 应用程序链接到服务接口的互用性适配器。

7.2将 ASP.NET 应用程序连接到服务接口的互用性适配器

有关实现互用性适配器的详细信息,请参阅第 6 章。

使用 Web 服务来达到互用性

除非性能或者其他考虑因素要求二进制解决方案,否则推荐使用 Web 服务作为互用性技术。本节着眼于如何使用 Web 服务来实现互用性。内容涵盖数据格式选择、如何使用 Mind Electric(最近被 webMethods 公司购并)的 GLUE 为 Java 中的 Web 服务建立服务接口,以及如何构建 .NET 互用性适配器。

决定数据格式

通过 Web 服务接口,示例将使用该服务接口来返回复杂类型,允许适配器创建这些复杂类型的代理并进行使用。然而,因为是在 Web 服务中处理基于 XSD 的复杂类型,所以不是所有的 Web 服务堆栈都可兼容。经验显示,对一个 Web 服务堆栈进行操作可能会中断另外一个堆栈。若要解决这个问题,您应当查看只交换基元数据类型(例如字符串和整数等)。所有的 Web 服务堆栈都支持这些数据类型,并提供最大限度的灵活性和客户端访问。

如果使用基元数据类型并且需要返回更复杂的数据类型(如顺序),则必须将这些数据打包成字符串。对此最好的解决方案是用数据的 XML 表示来填充字符串。这个 XML 编码应该遵循认可的架构。

因为 Web 服务必须将 Java 数据序列化成 XML,所以直接传递 Java 数据类型和将其序列化并作为字符串进行传递相比,在性能上差别不大。

在 XBikes 应用程序中,J2EE 和 .NET 开发团队对 Web 服务的通用数据格式做出决定。他们从这个设计中创建一个 XSD 架构,双方都使用它来创建合适的类和映射文件。

在 J2EE 中构建服务接口

现在需要创建一个服务接口以通过 Web 服务公开 J2EE 业务层外观。这就成了 J2EE Web 服务的服务接口。这个发布将此作为 WS 服务接口。

建立 Java Web 服务是一个非常直观的过程。首先,依据 XSD 架构为消息创建 Java 数据类。然后需要创建 Java Helper 类,根据 XSD 架构分析数据类,并将数据与 XML 格式化字符串进行相互转换。之后,可将 Java 数据类序列化为 XML 格式化字符串,使用 Helper 类再次将其转换回。

随后建立为 Web 服务公开正确方法的 Java 类。这个类接受并返回基元数据类型,在 Web 服务使用的和业务层服务外观期望使用的数据间执行任何数据转换,以及在服务外观上调用正确的方法。一旦创建了这个 Java 类,就可以使用 Web 服务堆栈提供的任何技术将其作为 Web 服务进行公开。

要构建 Java Web 服务,请完成以下任务:

  1. 为序列化创建基于 XSD 的数据类型和 XML 映射。
  2. 创建 Java Helper 类
  3. 创建和公开作为 Web 服务的 Java 类。

创建数据类型和XML 映射

创建 WS 服务接口的第一部分是创建所需要的所有数据操纵代码。因为应当使用 XSD 架构,所以可使用众多 Java XML 产品中的一种来从该架构中生成 Java 类。

许多 Java XML 产品包含映射文件,可将类中的字段映射到 XML 架构中的元素或者属性。有时现有的类无需中间媒介就可映射到正确的架构。如果是这样,则为现有的类创建映射文件,省却将现有 Java 类中的数据导入基于架构的 Java 类的步骤。

XBikes 开发人员将 GLUE 用作 Java Web 服务堆栈。GULE 在同样的软件包里也包含 Electric XML。Electric XML 包括用于从 XSD构建 Java 类的工具。Electric XML 还产生在从 Java 类读取或向其写入 XML 数据时 GLUE 使用的映射文件。

开发人员使用这些工具从 XSD 文件构建 Java 类。较为方便的是,生成的类几乎和现有的 Java 数据类完全一样。在这些情况下,开发人员修改创建的映射文件并随后序列化现有的类。

以下步骤阐释了开发人员如何使用 GULE 工具在 AuthenticateCustomer 用例中实现从 CustomerData XSD 文件创建 Java 类:

  1. XBikes 开发人员使用 Visusl Studio .NET 2003 中的 XSD 设计器设计 CustomerData XSD 文件。有关 XSD 设计器和 XSD 文件的详细信息,请参阅第 3 章。

    这些步骤假设计算机具有 GLUE 的许可证副本并且配置了有效的 Java 路径。

  2. 开发人员创建了基于 CustomerData.xsd 文件的 Java 类。GLUE 提供 schema2java 工具,开发人员通过运行下列命令,使用这个工具在项目正确的软件包中创建 Java 类。
    schema2Java CustomerData.xsd -g -p xbikes.common.dataconverters.customers
    

这个命令生成两个类,Customers_TYPE.Java CustomerData_TYPE.Java。该工具也生成 CustomerData.map,序列化程序用它来将字段映射到正确的 XML 元素。

创建 Java Helper 类

具备这些基于 XSD 的类后,应当将原始 Java 数据类中的数据移到基于 XSD 的类。填充 XSD 类后,需要将其序列化为 XML 格式化字符串。将序列化代码放入 Helper 类 具很有意义,并且 XBikes 开发人员就是这样做的。

下列步骤说明了开发人员如何为 CustomerData 基于XSD 的类创建 Java Helper 类:

  1. 开发人员创建了包含从字符串读取或向其写入数据的两种方法的 Helper 类。这些方法接受希望转换的数据类型的单个参数,并返回已转换类型的单个值。以下方法签名显示了该过程。
    public static String orderToString(Order o);
    public static Order StringToOrder(String o);
    
  2. 然后开发人员向 Java 项目添加在步骤 1 和 2 中创建的文件,便于访问起见,将它们放入公共软件包中。正如在步骤 1 中的 schema2Java 命令行所见,软件包的目标位置是 xbikes.common.dataconverters.customers
  3. 因为 GULE 是选定的环境,所以开发团队向构建路径添加 Glue.jar。
  4. 然后开发人员生成 Helper 类来执行 Java 类到字符串的相互转换。他们向 xbikes.common.dataconverters 软件包添加名为 CustomerConverter 的新类。
  5. 开发人员向 CustomerConverter 类添加两种方法,一种将 Java 数据转换为字符串,另一种将字符串转换为 Java 数据。这些方法使用 GLUE 序列化程序来读取和写入 XML。因为现有的 Java CustomerData 类与该架构不兼容,需要填充 CustomerData_TYPE 和 Customers_TYPE 类作为转换的一部分。以下代码列表显示了完成的 CustomerConverter 类。
    public final class CustomerConverter
    {
        private static final String WRITER = "CustomerData";
        private static final String NAMESPACE = 
            "http://tempuri.org/CustomerData.xsd";
        
        public static CustomerData stringToCustomerData(String xml)
            throws XBikesInteropException
        {
            try
            {
                // Need to convert the string into xml
                Document d = new Document(xml);
                IReader reader = new LiteralReader(d);
                CustomerData_TYPE myCustomer =
                    (CustomerData_TYPE) reader.readObject(CustomerData_TYPE.class);
                Customers_TYPE customer = myCustomer.getCustomers();
                CustomerData cd = new CustomerData();
                cd.setAddress(customer.getEmailAddress());
                cd.setCustomerID(customer.getCustomerID());
                cd.setName(customer.getFullName());
                cd.setPassword(customer.getPassword());
                cd.setZip(customer.getZipCode());
                return cd;
            }
            catch (Exception e)
            {
                System.out.println(e.getMessage());
                throw new XBikesInteropException(e.getMessage());
            }
        }
        public static String customerDataToString(CustomerData cd) 
            throws XBikesInteropException
        {
            try
            {
                // Move the data from the internal Java classes into those 
                // generated by the schema tool
                Customers_TYPE customer = new Customers_TYPE();
                customer.setCustomerID(cd.getCustomerID());
                customer.setEmailAddress(cd.getAddress());
                customer.setFullName(cd.getName());
                customer.setPassword(cd.getPassword());
                customer.setZipCode(cd.getZip());
                CustomerData_TYPE customerData = new CustomerData_TYPE();
                customerData.setCustomers(customer);
                // Write the object to a string, via the LiteralWriter / Document 
                // and StringBuffer
                IWriter writer = new LiteralWriter(WRITER);
                writer.writeObject(customerData);
                writer.writeNamespace("", NAMESPACE);
                Document d = writer.getDocument();
                String sCustomerData = "";
                StringWriter sw = new StringWriter();
                d.write(sw);
                sCustomerData = sw.getBuffer().toString();
                return sCustomerData;
            }
            catch (Exception e)
            {
                System.out.println(e.getMessage());
                throw new XBikesInteropException(e.getMessage());
            }
    }
    

创建Java 类并将其作为 Web 服务公开

最后的任务是建立并公开 Java Web 服务。这一严格的机制取决于决定使用的 Web 服务堆栈。XBike 开发人员使用的是 GLUE,因此有些步骤您可能在自己选定的堆栈中无需执行。

Mind Electric(如同许多其他的 Java Web 服务供应商)通过 servlet 在 GLUE 中实现 Web 服务。因此,需要一个 Web 应用程序来宿主这个组件。这个 Web 服务需要包含希望从 BusinessServiceFacade 中公开的所有方法,而不是返回 Java 数据类型,您应该返回字符串。因而此 Web 服务应该将所有的 Java 数据类型转换成包含 XML 的字符串(已根据 XSD 文件进行了格式化)。在以下示例中,Helper 类中已具有了用于此目的的代码,因此只需简单地进行方法调用即可。任意 Web 服务方法中的逻辑流如下所示:

  1. 应用程序调用 Web 服务方法。
  2. Web 服务将任何需要转换的数据传递到 Helper 类。
  3. Web 服务为 BusinessServiceFacade 会话 bean 创建主接口。
  4. Web 服务调用 BusinessServiceFacade 上的适当方法,传递已转换的数据。
  5. 如果 BusinessServiceFacade 返回数据,则使用 Helper 类将其转换成字符串。
  6. 重新将数据的字符串表示返回到调用应用程序。

图 7.3 显示了该过程。

7.3 在 Web 服务中使用数据 Helper 类

现在您已经了解了 Web 服务的构建过程。因为 GLUE 将 Web 服务堆栈作为 servlet 来实现,所以需要在 XBike 解决方案中创建一个 Web 项目来宿主这个 servlet。

如果不使用应用程序服务器,则 GLUE 同样提供自身的容器来运行 GLUE Web 服务。

XBikes 开发人员执行以下步骤来实现 Web 服务:

  1. 开发人员在 IBM WebSphere Studio 中创建名为 XBikesBLLServiceInterface 的新 Web 项目。然后将这个项目添加到现有的名为 SingleTierXBikes 的企业应用程序项目中。
  2. Web 服务需要在项目 XBikesCommonXBikesBiz 内调用对象,因此开发人员将这些项目作为模块依赖项进行添加。
  3. GLUE 提供一个可供使用的模板应用程序。这个模板包含在应用程序服务器上运行 GLUE Web 服务所需的所有文件。应当在文件夹 C:\Tme\Glue\App-Template 中找到这些文件。开发人员将这些文件复制到该项目中,以得到基本的 GULE 文件和要求的文件夹结构。他们还将 Glue.jar 文件添加到构建路径。
  4. 然后,开发人员构建应用程序作为 Web 服务公开的类。这个类的方法与 BusinessServiceFacade 相同,但使用字符串作为数据类型,而不是现有的 Java 类。
  5. 团队根据 BusinessServiceFacade, 中的方法创建新的接口和类,用字符串替换数据类型。他们将这些类添加到 xbikes.bll.serviceinterface.j2ee.ws 软件包中。下列代码示例显示了添加到 IBLLWSServiceInterface 的方法。
    public String authenticateCustomer(String email, String password)
            throws XBikesInteropException;
    public String getCategories() throws XBikesInteropException;
    public String getProductsByCategory(int categoryID)
            throws XBikesInteropException;
    public String getSearchResults(String keyword)
            throws XBikesInteropException;
    public String placeOrder(String order) throws XBikesInteropException;
    public String getCustomerOrders(int customerID)
            throws XBikesInteropException;
    
  6. 下列代码显示了 XBikesBLLServiceInterface 类中的 AuthenticateCustomer 的方法实现。
    package xbikes.bll.serviceinterface.j2ee.ws;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.rmi.PortableRemoteObject;
    
    import xbikes.bll.facade.BusinessServiceFacade;
    import xbikes.bll.facade.BusinessServiceFacadeHome;
    import xbikes.common.data.CustomerData;
    import xbikes.common.dataconverters.CustomerConverter;
    import xbikes.common.exceptions.XBikesInteropException;
    
    public class BLLWSServiceInterface implements IBLLWSServiceInterface
    {
        private static final String BUSINESS_FACADE_JNDI = 
            "ejb/xbikes/bll/facade/BusinessServiceFacadeHome";
        /**
        * @see
        xbikes.bll.serviceinterface.j2ee.ws.IBLLWSServiceInterface#authenticate
        Customer(String, String)
         */
        public String authenticateCustomer(String email, String password)
            throws XBikesInteropException
        {
            try
            {
                BusinessServiceFacade facade = getFacadeHome().create();
                CustomerData cd = facade.authenticateCustomer(email, password);
                String sCustomerData = CustomerConverter.customerDataToString(cd);
                // We now have a string that contains the xml.
                // We shall return that!
                return sCustomerData;
            }
            catch (Exception e)
            {
                throw new XBikesInteropException(e.getMessage());
            }
        }
    }
    

    在该类中,开发人员创建了 Helper 方法以更为便捷地访问 BusinessServiceFacade 会话 bean。

  7. 因为现在已经为 Web 服务创建了提供功能的类,所以只需通知 GLUE 即可。在 XBikes中,开发人员从文件夹 XBikesBLLServiceInterface\Web Content\WEB-INF\services 中复制并重命名示例配置文件 Sample.xml,以创建新的 BLLWSServiceInterface.xml 文件。
  8. 开发人员修改该文件,用 xbikes.bll.serviceinterface.j2ee.we.BLLWSServiceInterface 修改 constructor 标记。他们将标记 description 更改为 Bikes Unsecure Web Service,,将公布标记更改为 yes 以及 style 更改为 document。他们还修正了 interface 标记,用 xbikes.bll.serviceinterface.j2ee.ws.IBLLWSServiceInterface 替换 electric.util.sample.ISample 并将 targetNamespace 更改为 http://www.xbikes.com/
  9. 然后将早先创建的映射复制到文件夹 Web Content\WEB-INF\Maps 中。
  10. 为了测试 Web 服务,开发人员编译并启动服务器。在使用 GULE 控制台调用 authenticateCustomer 方法之前,他们打开了浏览器并将其指向 http://localhost:9080/XBikesBLLServiceInterface/Console

在 .NET 中创建互用性适配器

现在已经在 Java 中创建了 Web 服务服务接口,因此可以接着构建 .NET 互用性适配器。步骤如下:

  • 构建基于 XSD 架构的 .NET 数据类。
  • 使用 Visual Studio .NET 中的工具构建 Web 服务代理。
  • 为整个服务接口创建一个适配器,或者为每个用例各创建一个适配器。

在 XBike 中,开发人员为每个用例各创建了一个适配器。

互用性适配器调用代理,该代理随后调用 Web 服务。该适配器还必须对所有 .NET 数据和基于 XSD 架构的正确字符串/XML 格式进行相互转换。

适配器的逻辑流如下所示:

  1. 应用程序调用适配器方法。
  2. 适配器将所有复杂数据转换为 XML 字符串表示。
  3. 适配器创建 Web 服务代理实例。
  4. 应用程序调用 Web 服务代理中的适用方法。
  5. 如果代理返回数据,则将其转换成正确的 .NET 格式(如有必要)。
  6. 将数据返回到调用应用程序。

图7.4 为操作流程。

7.4 具备 .NET 框架应用程序的 Web 服务代理操作

创建基于 XSD 的数据类

为了让 .NET Framework 应用程序使用来自 Java Web 服务的数据,需要具备可用返回的 XML 字符串填充的 .NET 类。可以再次使用将架构转换成类的工具,即 XSD.EXE 工具。

XSD.EXE 接受 /dataset 开关项来生成子类数据集。如果从头建立 .NET Framework 应用程序,或许值得考虑使用 XSD 在 .NET Framework 应用程序中生成的数据集。这就避免了从基于 XSD 的类转换到不同格式或者结构化 .NET 类的需求。

XBikes 开发人员使用带有 /dataset 开关项的 XSD 工具来生成 .NET 数据集类。然后在整个 .NET Framework 应用程序中使用这些数据集以避免 Java Web 服务返回数据和专用 .NET 类间的转换。

另一项技术是使用图形工具,例如 Visual Studio .NET 2003 中的 XML 架构设计器。

为了在 .NET 中创建 CustomerData 数据类型,开发人员打开 Visual Studio .NET 2003 命令提示并执行以下命令:

xsd CustomerData.xsd /dataset /namespace:xbikes.common.schemas

然后将生成的文件复制到 XBikes-Common 项目中。

创建 .NET Web 服务代理

下一项任务是为 Web 服务构建代理类。可以根据自己的喜好使用 Visual Studio .NET 或者 wsdl.exe 命令行工具。如果使用 Visual Studio .NET,则向包含互用性适配器的项目添加 Web 引用。创建 Web 引用时,输入 Java WSDL 文件的 URL。如果喜欢 wsdl.exe 命令行工具,则应当指定开关项以在正确的命名空间中创建代理类。

向 Visual Studio .NET 中的项目添加 Web 引用时,其默认名称与 URL(Web 服务的 WSDL 所处位置)中的服务器名相同。这个由 Web 引用生成的代理类属于后缀为 Web 引用名的项目的默认命名空间。将 Web 引用(代理命名空间)命名为默认名称是最佳做法。

因为 XBike 使用简单的 Web 服务,所以开发人员使用 Visual Studio .NET 中的 Add Web Reference 函数来创建代理。他们将这个代理添加到 XBikes-UseCaseInteropAdapters 项目中。Java WSDL 的 URL 是 http://localhost:9080/XBikesBLLServiceInterface/services/BLLWSServiceInterface.wsdl。开发团队重命名 Web 引用,将其默认值 localhost 更改为 J2EE.BLLWSSI。这个新的名字反映出这个 Web 引用适用于 J2EE 业务逻辑层 WS 服务接口。然后,由这个 Web 引用生成的代理类就属于XBikes.UseCaseInteropAdapters.J2EE.BLLWSSI 命名空间。

创建 .NET 互用性适配器

现在具备了数据类和 Web 服务代理,可以构建互用性适配器了。正如本章先前所述,根据所需的控制级别,可以选择每个 Web 服务一个适配器,或为每个用例各创建一个适配器。XBikes 开发人员为每个用例各创建一个适配器,以提供最大限度的灵活性。

XBikes 用例遵循命令模式,提供执行和初始化方法,并实现了名为 IUseCaseCommand 的接口。适配器从它们改编的命令获得名称,因此 AuthenticateCustomerInteropAdapter 链接到 AuthenticateCustomerCommand

AuthenticateCustomer 用例创建互用性适配器非常直观。在 XBikes-UseCaseInteropAdapters 项目中,开发人员将一个称为 AuthenticateCustomerInteropAdapter 的新类添加到 J2EE\WS 文件夹。然后,更改类来实现 IUseCaseCommand 接口。这要求他们实现方法 executeinitialise 并且将代码添加到类构造函数中。下列代码列表对方法 ConstructorInitialise 进行了说明。

public AuthenticateCustomerInteropAdapter()
{
    try
    {
        // Instantiate the BLL service interface proxy.
        // Creates a J2EE-side BLL service interface
        _facade = new BLLWSServiceInterface();
    }
    catch (Exception e)
    {
        throw new XBikesInteropException("[AuthenticateCustomer]:
                  J2EE WS Interop Adapter error: ", e);
    }
}
private string _email;
private string _password;

public void Initialise(object[] parameters)
{
    _email = (string) parameters[0];
    _password = (string) parameters[1];
}

方法 execute 需要创建早些时候生成的 Web 服务代理实例。然后返回的字符串需要在被返回前打包到数据集中。以下代码列表显示了方法 execute

public DataSet Execute()
{
    try
    {
        //Retrieve customer data as an XML Document in 
        //a string format.
        StringReader sr = new 
            StringReader(_facade.authenticateCustomer
              (_email,_password));
        CustomerData ds = new CustomerData();
        //Load result string back into CustomerData typed DataSet.
        ds.ReadXml(sr);
        return ds;
    }
    //soap error
    catch (System.Web.Services.Protocols.SoapException soapExp)
    {
        string soapFaultMsg = soapExp.Message;
        //Parse SoapException message to get exception type.
        string ExceptionType =
            ExceptionHelper.GetSoapExceptionType(soapFaultMsg);
        //Throw the appropriate exception type based on the
        //exception type found in the SoapException.
        switch (ExceptionType)
        {
            case "Interop":
                throw(new XBikesInteropException(soapFaultMsg));
            case "Application" :
                throw(new XBikesApplicationException(soapFaultMsg));
            default:
                throw(new XBikesApplicationException(soapFaultMsg));
        }//switch
    }
    //general error
    catch (Exception e)
    {
        //Wrap in Interop Exception
        XBikesInteropException intExp = new 
            XBikesInteropException("AuthenticateCustomer WS Interop 
        Adapter error.",e);
        //Throw up the stack to client for logging.
        throw (intExp);
    }
}

执行该步骤时,Web 服务返回的字符串数据应该是符合CustomerData 的公共 XML 架构的正确格式。因为 CustomerData 类型化 DataSet 基于公共架构,所以可通过使用 ReadXML() 方法将 Web 服务返回的 XML 字符串加载到 DataSet 中。

该代码示例假设返回的 XML 字符串与正确的架构格式匹配,否则应用程序会产生异常。您可能希望通过 XSD 架构文件的验证过程来运行返回的 XML 字符串,从而在试图使用 ReadXML() 方法将字符串加载到类型化 DataSet 之前确认二者匹配。

在本节中,您将了解如何在使用 Web 服务进行交互的 Java 和 .NET 中创建互用性适配器和服务接口在下一节中,您将了解如何使用 JNBridgePro 和 Ja.NET 来提供更高性能的互用性解决方案,以实现互用性适配器和服务接口。

使用 JNBridgePro 来实现互用性

本节说明了如何使用 JNBridgePro 在 .NET Web 层和 J2EE 业务层之间执行桥接。其中包括数据格式选择、如何构建服务接口以及如何构建互用性适配器。

确定数据格式

JNBridgePro 具有为 Java 数据类在 .NET 中生成代理类的功能。然后,可在 .NET 应用程序中使用这些生成的数据类。然而,因为本章中已经提及的原因,将该数据放入数据集中或许更有意义,方便随后您在 .NET 表示层中使用。

在 .NET 中构建互用性适配器时,极有可能要执行某些数据转换操作。

为 JNBridgePro 构建服务接口

JNBridgePro 可以向 .NET 公开现有的 Java 类,因此可选择向 .NET 公开现有的服务外观。然而,应当使用分层方法来保护代码不会被更改。为此,需要创建其他 Java 类(即服务接口)。因为可用 JNBridgePro 将本机 Java 数据类型返回到 .NET,所以该服务接口只需调用服务外观上适当的方法并返回所有结果数据类型即可。

将 JNBridgePro 用于实现互用性的应用程序需要 .NET 和 J2EE 双方的 JNBridge 运行库组件。Java 端运行库组件充当 .NET Framework 远程服务器,封送处理和解除封送处理参数、返回值、调度方法以及管理 .NET 引用的 Java 对象的生命周期。

根据创建服务接口类的模式,开发人员构建可正确实现与现有 BusinessServiceFacade 会话 bean 方法相同的 Java 类。本节给出了开发人员如何创建 AuthenticateCustomer 用例的全部过程。

  1. 开发人员创建了一个名为 JNBridgeBLL 的新 Web 项目,并将其添加到现有的 SingleTierXBikes EAR。.然后他们将 XBikesCommonXBikesBiz 项目作为模块引用包括进来。
  2. 之后将 JNBridgePro Java 端运行库组件 JNBCORE.JAR 安装到 WEB-INF\lib 文件夹,并将 jnbcore_tcp.properties 文件添加到文件夹 WEB-INF(从 JNBridge 安装文件夹复制这些文件)。
  3. 接下来,将 JNBServlet 添加到 Web Deployment Descriptor,指定 Load on startup 并将 Load Order 设置为 -1,这样当应用程序服务器启动时就可加载类。
  4. 开发人员在 xbikes.bll.serviceinterface.j2ee.jnbridge 软件包中创建 BLLServiceInterface 类。这个类只是将所有的方法调用传递到现有的服务外观。下一个代码示例显示了 BLLServiceInteface 类。
    Source Code Listing
    
    package xbikes.bll.serviceinterface.j2ee.jnbridge;
    
    import javax.naming.*;
    import javax.rmi.*;
    import java.rmi.*;
    import xbikes.bll.facade.*;
    import xbikes.common.data.*;
    
    
    public class BLLServiceInterface {
    
        BusinessServiceFacade facade=null;
        private final String BUSINESS_FACADE_JNDI =
            "BusinessServiceFacade";
        private final String BUSINESS_FACADE_CLASS =
            "xbikes.bll.facade.BusinessServiceFacadeHome";
    
        /**
         * Constructor for BLLServiceInterface.
         */
        public BLLServiceInterface() {
            try
            {
                InitialContext ic = new InitialContext();
                Java.lang.Object objRef = ic.lookup(BUSINESS_FACADE_JNDI);
                BusinessServiceFacadeHome home =
                    (BusinessServiceFacadeHome) PortableRemoteObject.narrow(objRef,
                    Java.lang.Class.forName(BUSINESS_FACADE_CLASS));
                facade = home.create();
            }
            catch (Exception excp)
            {
                System.out.println(excp.getMessage());
            }
        }
    
        public CustomerData authenticateCustomer(String email, String password)
        throws Exception
        {
            return facade.authenticateCustomer(email, password);
        }
    
        public CategoriesListData getCategories()
        throws Exception
        {
            return facade.getCategories();
        }
    
        public OrderListData getCustomerOrders(int customerID)
        throws Exception
        {
            return facade.getCustomerOrders(customerID);
        }
    
        public ProductsListData getProductsByCategory(int categoryID)
        throws Exception
        {
            return facade.getProductsByCategory(categoryID);
        }
    
        public ProductsListData getSearchResults(String keyword)
        throws Exception
        {
            return facade.getSearchResults(keyword);
        }
    
        public void placeOrder(OrderData theOrder)
        throws Exception
        {
            facade.placeOrder(theOrder);
        }
    }
    

BLLServiceInterface 主要是到现有 BusinessServiceFacade EJB 的传递。包装类提供的附加功能是构造函数,它封装查找和访问 EJB 必需的代码。

可以使用 JNBridgePro 来生成直接访问 BusinessServiceFacade 和支持 JNDI 类的代理,如果在 Java 端完全执行这些操作并将这些操作封装在包装内会更为有效。在其他情况下(即不更改 J2EE 代码),您必须直接访问 JNDI 和 EJB 类。第 9 章“实现异步互用性”中的“使用 MSMQ-MQSeries 桥”一节,讲述了如何创建访问 MQSeries API 的适配器,并演示了在不可能更改 J2EE 代码的情况下如何创建这种适配器。

使用 JNBridgePro 构建互用性适配器

构造了希望 .NET 应用程序使用的服务接口之后,需要为 .NET 生成代理程序集。这个程序集包含服务接口的 .NET 代理以及服务接口使用的所有数据类。因此如果服务接口返回 CustomerData 类型的 Java 数据,则 JNBridgePro 生成的 .NET 程序集将包含该类的代理。

在代码中,代理类的前缀名考虑使用产生代理类的平台名,例如,如果 .NET 类是 CustomerData,则 Java 代理类是 javaCustomerData

可以使用 JNBridgePro 提供的 GUI 工具来生成这些代理类。只需选择希望为之生成代理的类,JNBridge 就会创建它们。

然后可将这个程序集作为引用,与所需的 JNBridgePro 配置文件一同添加到 .NET 项目中,应用程序可以像任何其他的 .NET 类(例如,互用性适配器)那样进行使用。此外,应根据所需的互用性适配器的控制等级,为每个用例实现一个适配器或者为整个服务接口实现一个适配器。

XBikes 开发人员为每个用例实现一个互用性适配器。

创建 Java 代理类

在 XBikles 中创建互用性适配器的第一步是为 Java 服务接口生成代理。基于 GUI 的代理生成工具是用于此的 JNBridgePro 的一部分。

第一次执行该工具时,必须设置 Java 环境。通过指定 Java.exe 程序文件的位置即可。完成后,开发人员继续以生成适配器:

  1. 开发人员用正确的 Java 配置加载和配置 JNBProxy 工具,然后将服务接口要求的所有项目文件夹和 Project Utility Jars 添加到早先创建的类路径。其中包括下列 J2EE 项目文件夹和 Project Utility Jars:
    • C:\xbikes\J2EE-IBM\XBikesBiz\ejbModule,业务外观类的根目录。
    • C:\xbikes\J2EE-IBM\XBikesCommon,通用数据传输对象的根目录。
    • C:\xbikes\J2EE-IBM\JNBridgeBLL\Web Content\WEB-INF\classes,外观包装类的根目录。
    • C:\Program Files\IBM\WebSphere Studio\runtimes\base_v5\lib\j2ee.jar,该库包含各种与 J2EE 和EJB 相关的类和异常。
    • C:\Program Files\IBM\WebSphere Studio\runtimes\base_v5\mqjms\Java\lib\jndi.jar,这个库包含各种与 JNDI 相关的类和异常。

    根据您的安装,该文件夹和文件路径可能有所不同。

  2. 开发团队必须选择要从 .NET 访问的类,最后添加下列类,以及所有支持类:
    • xbikes.bll.serviceinterface.j2ee.jnbridge.BLLServiceInterface
    • xbikes.common.data.CategoriesData
    • xbikes.common.data.CategoriesListData
    • xbikes.common.data.CustomerData
    • xbikes.common.data.OrderData
    • xbikes.common.data.OrderDetailsData
    • xbikes.common.data.OrderListData
    • xbikes.common.data.ProductsData
    • xbikes.common.data.ProductsListData
  3. JNBProxy然后加载所需的 Java 类。这只公开上面列出的类,开发人员将它们添加到公开的代理面板。
  4. 因为目标是创建加载到 GAC 中的程序集,所以开发人员配置了 JNBProxy 以构建一个强名称,提供1.0.0.0的版本号以及强名称密钥文件。
  5. 最后开发人员指示JNBProxy 用该名称构建程序集。 Jnbridgebllproxies.dll.

JNBridgePro 也附带有配置文件,其中包含 .NET Framework 客户端如何与 Java 应用程序通讯的设置,例如 URL 或 Java 应用程序的位置。这个文件的名字是 jnbproxy_tcp.config,现在已经生成了代理,下一个任务是将其集成到 ASP.NET 表示层。

本例着重于 AuthenticateCustomer 用例,不过其余部分都一样。

实现互用性适配器

开发人员打开 .NET XBikes 解决方案并且添加一个名为 XBikes-UseCaseInteropAdapters-JNBridge的新项目。在这个项目中,开发人员将一个名为 AuthenticateCustomerInteropAdapter 的新类添加到J2EE\JNBridge 文件夹。

JNBridge 和 JaNET 用例互用性适配器驻留在单独的 Visual Studio 项目中,与其他 XBikes .NET 用例互用性适配器分开。这避免了在同一项目中使用 JaNET 和 JNBridge 元素时发生冲突。在生产环境中,不太可能同时需要使用 JaNET 和 JNBridge。

因为互用性适配器使用 JNBridge,所以开发人员将创建的代理程序集,Jnbridgebllproxies.dll 以及 JNBridge.NET 支持程序集 Jnbshare.dll 复制到 .NET 计算机,并将它们作为项目引用进行添加。他们还将配置文件 Jnbproxy_tcp.config 复制到这台计算机上的 WWWroot 文件夹,并将其重命名为 Jnbproxy.config。

对客户进行身份验证时,AuthenticateCustomerInteropAdapter 处理 .NET Web 层和 J2EE 业务层间的桥接。它实现 IUseCaseCommand 接口,这意味着它实现两个方法:

  • Initialise() - 设置用例适配器并为即将进行的操作分配参数。
  • Execute() - 使用例适配器执行其操作。

互用性适配器为基于 J2EE 的 BLLServiceInterface 对象创建由 JNBridge 生成的代理,该对象通过类别执行产品查找。互用性适配器的构造函数创建代理,并作为该操作的一部分创建基础 J2EE BLLServiceInterface 对象。

Initialise() 的调用只是获取类别标识符(整数)并将其保存,从而在执行命令时可用。对 Execute() 的调用调用 BLLServiceInterface 代理对象中的 authenticateCustomer() 方法,这可引起在 J2EE 中执行等同的方法,并向 J2EE CustomerData 对象返回引用。

在 .NET 端,这个 CustomerData 对象是 J2EE CustomerData 对象的代理。Execute() 的剩余部分将 J2EE CustomerData 对象转换成等价的本机 .NET CustomerData 对象。它通过循环访问 J2EE CustomerData 对象中的单独产品数据、提取产品细节并将新的本机 .NET CustomerRow 对象分配到本机 .NET CustomerData 对象来完成此操作。

命名空间 ndatajdata 代表更长的 .NET 和 J2EE 命名空间以提高可读性,并允许您更为容易地识别和区分基于 .NET 和基于 J2EE 的对象。

using System;
using System.Data;
using XBikes.Common.Exceptions;
using XBikes.Common.Interfaces.Architecture;
// namespace of the J2EE BLL Service interface
using xbikes.bll.serviceinterface.j2ee.jnbridge;
// namespace for J2EE version of common data objects
using jdata = xbikes.common.data;
// namespace for .NET version of common data objects
using ndata = XBikes.Common.Schemas;

namespace XBikes.UseCaseInteropAdapters.J2EE.JNBridge
{
    /// <summary>
    /// Use case adapter to authenticate customer information.
    /// <summary>
    public class AuthenticateCustomerInteropAdapter : IUseCaseCommand
    {
         private BLLServiceInterface facade = null;
         /// <summary>
         /// Summary description for AuthenticateCustomerCommand.
         /// <summary>
         public AuthenticateCustomerInteropAdapter()
         {
            try
            {
                facade = new BLLServiceInterface();
            }
            catch (Exception e)
            {
                throw new XBikesInteropException
                    ("[AuthenticateCustomer]: JNBridge Interop 
                    Adapter error: ", e);
            }
        }

        private string _email;
        private string _password;

        public void Initialise(object[] parameters)
        {
            _email = (string) parameters[0];
            _password = (string) parameters[1];
        }
        public DataSet Execute()
        {
            try
            {
                // perform the customer authentication
                // on the J2EE side
                // and retrieve the customer data
                jdata.CustomerData cust =
                    facade.authenticateCustomer(_email,_password);

                // copy the Java data into a .NET data object
                // create the .NET data object
                ndata.CustomerData ds =
                    new ndata.CustomerData();
                // create a new row in the .NET data object
                ndata.CustomerData.CustomersRow cr =
                    ds.Customers.NewCustomersRow();
                // copy the individual fields from the
                // J2EE data object to the .NET data object
                cr.CustomerID = cust.getCustomerID();
                cr.EmailAddress=cust.getAddress();
                cr.FullName=cust.getName();
                cr.Password=cust.getPassword();
                cr.ZipCode = cust.getZip();

                // add the data row to the data set
                ds.Customers.AddCustomersRow(cr);
                return ds;
}
            catch (XBikesInteropException intExp)
            {
                //This will already have been logged on its own tier.
                //re-throw up the stack for logging at the client.
                throw (intExp);
            }
            catch (XBikesApplicationException appExp)
            {
                //This will already have been logged on its own tier.
                //re-throw up the stack for logging at the client.
                throw (appExp);
            }
            catch ( Exception e )
            {
                throw new XBikesInteropException
                    ("[AuthenticateCustomer]: JNBridge Interop 
                    Adapter error: ", e);
            }
        }
    }
}

开发人员进行的最后一部分配置位于 XBike 应用程序的 .NET 端,他们需要配置这个文件以告知两台计算机如何通讯。这个文件是 Jnbproxy.config,位于文件夹 WWWroot 中。开发人员将名称 LOCALHOST 更改为指向 J2EE 计算机。他们还将 Jnbshare.dll 和 Jnbridgebllproxies.dll 安装在全局程序集缓存中。

使用 Ja.NET 来实现互用性

本节内容说明了如何使用 Ja.NET 来执行 .NET Web 层应用程序和 J2EE 业务层间的桥接。如同之前有关 JNBridgePro 的章节一样,其中包括数据格式选择、如何构建服务接口以及如何构建互用性适配器。

确定数据格式

Ja.NET 也具有为 Java 数据类提供带有代理类的 .NET 的功能,以允许您在 .NET 应用程序中使用这些生成的数据类。因为本章中已经提及的原因,将这个数据放入数据集中更有意义,方便随后在 .NET 表示层中使用。因此在 .NET 中构建互用性适配器时可能需要执行某些数据转换。

为 Ja.NET 构建服务接口

如同 JNBridgePro 一样,您可以选择向 .NET 公开现有的服务外观。然而,应该通过实现分层方法来保护代码不被更改。可通过将另一个 Java 类创建为服务接口来完成此操作。因为可使用 Ja.NET 将本机 Java 数据类型返回到 .NET,所以这个服务接口只需调用服务外观上的适当方法并返回结果数据类型即可。

使用 Ja.NET 来实现互用性的应用程序需要 J2EE 端上的 Ja.NET 运行库组件,以及 .NET 端上的代理定义库(DLL)。Java 端运行库组件充当 .NET Framework 远程服务器,封送处理并解除封送处理参数、返回值、调度方法以及管理 .NET 引用的 Java 对象的生命周期。

此外,开发人员创建 Ja.NET 服务接口作为 Java 类。这个类将方法调用传递到现有的会话。这个例子也显示了AuthenticateCustomer 用例:

  1. 开发人员创建了新的名为 JaNetBLL Web 项目。他们将其添加到现有的 SingleTierXBikes EAR。如同以往,他们将 XBikesCommonXBikesBiz 项目作为模块引用包括进来。
  2. 开发人员使用 Janetor 工具创建 Web 项目内容。该工具可创建包含 Ja.NET 运行库和已配置的 Web.xml 文件的 WAR。许可证安装完成后,他们必须配置应用程序服务器的主机名,然后导出 WAR。随后将这个 WAR 导入到新创建的 JaNetBLL 项目,按需要覆盖文件。
  3. 为了允许 JaNet 项目与会话 bean 通话,开发人员在 Web 项目中创建了 EJB 引用以指向 BusinessServiceFacade 会话 bean。
  4. 最后,在 xbikes.bll.serviceinterface.j2ee.janet 软件包中创建一个名为 BLLServiceInterface 的 Java 类。这个类具有与 BusinessServiceFacade 相同的方法,并且只需将方法调用传递到这个会话 bean上。

    这个类和 JNBridge 部分中的细节完全相同。

使用 Ja.NET 来生成直接访问 BusinessServiceFacade 和支持 JNDI 类的代理时,如果在 Java 端执行全部操作并将这些操作封装在包装中会更为有效。在其他情况下,不能更改 J2EE 代码,必须直接访问 JNDI 和 EJB 类。在第 9 章“实现异步互用性”中的“使用 MSMQ-MQSeries 桥”一节中,讲述了如何创建访问 MQSeries API 的适配器,并示范了如何在不可能更改 J2EE 代码的情况下创建这种适配器。

使用 Ja.NET 构建互用性适配器

构造了 .NET 应用程序要使用的服务接口后,需要为 .NET 生成代理程序集。这个程序集包含服务接口的 .NET 代理,以及服务接口使用的数据类。例如,如果服务接口返回 Java 类型 CustomerData 的数据,则 Ja.NET 生成的 .NET 程序集将包含此类的代理。

可使用 Ja.NET 工具来生成这些代理类。选择希望生成代理的类,由 Ja.NET 来创建它们。

然后可将这个程序集作为引用添加到 .NET 项目,以及所需的 Ja.NET 配置文件,然后象使用其他 .NET 类(如互用性适配器)一样进行使用。此外,必须根据互用性适配器的控制等级,为每个用例实现一个互用性适配器或者为整个服务接口创建一个互用性适配器。

创建 Java 代理类

在 XBikes 中创建互用性适配器的第一步是为 Java 服务接口生成代理。开发人员使用的基于 GUI 的代理生成工具 GenNet 是 Ja.NET 的一部分。

  1. 开发人员启动 GenNet 并添加下列文件夹和 Project Utility Jars:
    • C:\xbikes\J2EE-IBM\JaNetBLL\Web ContentWEB-INF\classes
    • C:\xbikes\J2EE-IBM\XBikesCommon
    • C:\Program Files\IBM\WebSphere Studio\runtimes\base_v5\lib\j2ee.jar
    • C:\xbikes\J2EE-IBM\XBikesBiz\ejbModule
  2. 然后添加 BLLServiceInterface 类和 xbikes.common.data 软件包中的所有类。更改数据类以传递值来改善性能。
  3. 然后开发人员将生成的代理程序集另存为带有强名称的 JanetBLLEjb.dll。GenNet 代理生成工具还生成远程配置文件(名为 Remoting_http.config),其中包含能够与 Java 组件通讯的 .NET Remoting 设置。

现在他们已经生成了代理,下一个任务是将其集成到 ASP.NET 表示层。

这个例子着重于 AuthenticateCustomer 用例,不过其余部分遵循相同的模式。

实现互用性适配器

开发人员打开 .NET XBikes 解决方案并且添加一个名为 XBikes-UseCaseInteropAdapters-JaNET 的新项目。在这个项目中,开发人员将名为 AuthenticateCustomerInteropAdapter 的新类添加到 J2EE\JaNET 文件夹中。

JNBridge 和 JaNET 用例互用性适配器驻留在单独的 Visual Studio 项目中,与其他 XBikes .NET 用例互用性适配器分开。这避免了在同一项目中使用 JaNET 和 JNBridge 元素时发生冲突。在生产环境中,不太可能同时需要 JaNET 和 JNBridge。

因为互用性适配器使用 Ja.NET 生成的 Java 代理,所以开发人员将 JanetBLLEjb.dll 复制到 .NET 计算机并将其安装在 GAC 中。然后他们将其作为引用添加到 XBikes-UseCaseInteropAdapters-JaNET 项目中。

对客户的身份进行身份验证时,AuthenticateCustomerInteropAdapter 处理 .NET Web 层和 J2EE 业务层间的桥接。它实现 IUseCaseCommand 接口,这意味着它实现两个方法:

  • Initialise() - 设置用例适配器并为即将到来的操作分配参数。
  • Execute() - 使用例适配器执行其操作。

互用性适配器为基于 J2EE 的 BLLServiceInterface 对象(执行客户身份验证的对象)创建 Ja.NET 生成的代理。互用性适配器的构造函数创建代理并(作为该操作的一部分)创建基础 J2EE BLLServiceInterface 对象。

Initialise() 的调用只是获得客户的电子邮件地址和密码(都是字符串),并进行保存,以便在命令执行时可用。对 Execute() 的调用调用了 BLLServiceInterface 代理对象中的 authenticateCustomer() 方法,这会引起等同的方法来执行 J2EE,并返回 J2EE CustomerData 对象的传值副本。这和第 4 章“互用性技术:点对点”中的“Ja.NET 最佳实践”一致。

在 .NET 端,这个 CustomerData 对象是 J2EE CustomerData 对象的代理。Execute() 的剩余部分将 J2EE CustomerData 对象转换为等价的本机 .NET CustomerData 对象。它通过循环访问 J2EE CustomerData 对象中的单独产品数据、提取产品细节并将新的本机 .NET CustomerRow 行对象分配到本机 .NET CustomerData 对象来完成此操作。

using System;
using xbikes.bll.serviceinterface.j2ee.janet;
using xbikes.common.data;
using XBikes.Common.Interfaces.Architecture;
using XBikes.Common.Schemas;
using System.Data;
using XBikes.Common.Exceptions;


namespace XBikes.UseCaseInteropAdapters.J2EE.JaNET
{
    /// <summary>
    /// Class that implements the IUseCaseCommand interface.
    /// This class performs the task of
    /// AuthenticateCustomerInteropAdapter.
    /// It calls into the J2EE Server to get at its BLL Service
    /// Interface
    /// and calls the authenticateCustomer method on the
    /// BLLServiceInterface contained
    /// in the JaNetBLL servlet.
    /// In actual fact, you could use Ja.NET and the JNDIContext
    /// object
    /// to directly call the BLL Bean in the app server.
    /// For this Case Study, there is an extra layer that has been
    /// added, namely
    /// that of
    /// xbikes.bll.serviceinterface.j2ee.janet.BLLServiceInterface
    /// that lives in the JaNetBll servlet.
    /// <summary>
    public class AuthenticateCustomerInteropAdapter : IUseCaseCommand
    {
        private string m_szPassword = "";
        private string m_szEmail = "";

        // the proxy for the BLL service interface object
        private BLLServiceInterface  _facade = null;

        /// <summary>
        /// The constructor for the authenticate 
        /// customer use case adapter.
        /// <summary>
        public AuthenticateCustomerInteropAdapter()
        {
            try
            {
                // instantiate the BLL service interface .
                 _facade = new BLLServiceInterface();
            }
            catch (Exception e)
            {
                throw new 
                    XBikesInteropException("[AuthenticateCustomerInteropAdapter]: 
                       J2EE JaNET Interop Adapter error: ", e);
            }
        }

        /// <summary>
        /// Sets the parameters for this UseCaseAdapters
        /// <summary>
        /// <param name="parameters"></param>
        public void Initialise(object[] parameters)
        {
            m_szPassword = (string) parameters[0];
            m_szEmail = (string) parameters[1];
        }

        /// <summary>
        /// The Actual Execute Method
        /// <summary>
        /// <returns>DataSet object</returns>
        public DataSet Execute()
        {
            try

            {
                // Create the return DataSet Object
                XBikes.Common.Schemas.CustomerData custData = 
                        new XBikes.Common.Schemas.CustomerData();

                // Get the EJB Data
                xbikes.common.data.CustomerData ejbCustData = 
                   _facade.authenticateCustomer
                     (m_szPassword, m_szEmail);
                // We need a row
                XBikes.Common.Schemas.CustomerData.CustomersRow cr = 
                        custData.Customers.NewCustomersRow();
                // Fill in the values
                cr.CustomerID = ejbCustData.getCustomerID();
                cr.EmailAddress = ejbCustData.getAddress();
                cr.FullName = ejbCustData.getName();
                cr.Password = ejbCustData.getPassword();
                cr.ZipCode = ejbCustData.getZip();
                custData.Customers.AddCustomersRow(cr);
                return custData;

            }
            catch (XBikesApplicationException ae)
            {
                throw ae;
            }
            catch (XBikesInteropException ae)
            {
                throw ae;
            }
            catch (System.Runtime.Remoting.RemotingException sre)
            {
                // Is it a problem with the network?
                string message = sre.Message;
                if (message.IndexOf("com.intrinsyc.janet") >= 0)
                {
              throw new XBikesInteropException(sre.Message, sre);
                }
                else
                {
                    // or is it an application error?
                    throw new 
  XBikesApplicationException(sre.Message, sre);
                }
            }
            catch (Exception eX)
            {
                // generic catch/rethrow
                throw new XBikesApplicationException(eX.Message, eX);
            }

        }
    }
}

实现 JaNET 互用性适配器的最后是设置配置文件。在 ASP.NET Web 应用程序中,必须在 web 应用程序的 Application_OnStart 事件的事件处理程序期间读取所有的 .NET Remoting 配置设置。JaNET 使用 .NET Remoting 与 Java 组件通讯,并且互用性适配器作为 .NET 表示层的 ASP.NET 应用程序的一部分运行。因此在 ASP.NET 应用程序的 Application_OnStart 事件的事件处理程序期间,也必须读取 JaNET 配置设置。Application_OnStart 事件的事件处理程序位于 Web 应用程序的 Global.asax.cs 文件中。此处介绍应用程序体系结构的两个次要因素:

  • 如果您的 ASP.NET 应用程序与任何其他使用 .NET Remoting 的组件通讯,则这些组件的远程配置设置必须位于同样的文件中,并作为 Application_OnStart 事件同时加载。
  • 通过从 ASP.NET 应用程序的 Global.asax.cs 文件加载 JaNET 配置设置,互用性适配器不再提供完整的抽象。

为了满足 ASP.NET 应用程序的远程配置要求,XBikes 开发人员随后使用从代理工具生成的 Remoting_http.config 文件的客户端部分内容更新 XBikes-Web 中的远程配置文件 Remoting.config。

您只能配置 .NET Remoting 配置文件中通道类型的一个实例。因此每次只能配置一个 HTTP 通道,如果在使用 .NET Remoting 进行通讯的 ASP.NET 应用程序中已有组件,则可能引发问题。如果 Remoting.config 文件中已经具有配置好的通道,则将 Ja.NET 配置设置从 Remoting_http.config(生成的配置文件)复制到 Remoting.config 文件时,注意不要两次复制同样类型的通道定义。

如果 .NET 和 J2EE 组件在不同的计算机上,则需要确保在 Remoting.config 文件中的 JaNET 配置设置的<client> 标记中指定的 URL 包含宿主 J2EE 组件的计算机名。

小结

本章讲述了开发人员如何在 XBikes 应用程序中实现互用性。您可以了解到如何在表示层实现 ASP.NET 应用程序,然后将其连接到现有的 J2EE 业务层。您还可以了解到如何实现用例适配器、服务接口和服务外观来完成此任务。以及如何使用运行库桥接来连接 J2EE 和 Web 服务不适合的 .NET。

参考资料

有关 GLUE 的详细信息

http://www.themindelectric.com/

- 或者 -

http://www.webmethods.com/

转到原英文页面


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织