posts - 15,  comments - 34,  trackbacks - 27

本文讨论如何让用 CORBA 支持的任何语言编写的客户端能够访问 Enterprise JavaBeansTM 组件 (“EJBTM 组件”)。本文针对深入了解 JavaTM 2 Platform, Enterprise Edition ("J2EETM") 和公共对象请求代理结构(Common Object Request Broker Architecture,CORBA)的程序员。

J2EE 技术简化了企业应用程序,因为它将它们建立在标准、模块化和可重用组件的基础上,而该组件又基于 Enterprise JavaBeansTM (EJBTM) 体系结构,它也提供了完整的一组针对于那些组件的服务,并自动处理应用程序行为的许多细节。通过自动化应用程序开发的许多耗时且困难的任务,J2EE 技术使企业开发人员能够将重点放在增值上,也就是增强业务逻辑,而不是放在构建基础结构上。

EJBTM 服务器端组件模型简化了事务型、可伸缩和可移植的中间件组件的开发。Enterprise JavaBeans 服务器减少了中间件开发的复杂程度,因为它为诸如事务、安全、数据库连接等中间件服务提供了支持。

CORBA 是一个对象管理组织(Object Management Group,OMG)标准,它是一个开放的、供应商无关的体系结构和基础结构,计算机应用程序可以使用它来通过网络一起工作。由于使用了标准的 Internet Inter-ORB Protocol,(IIOP),因些来自任何供应商的基于 CORBA 的程序可以与来自相同或其他供应商的基于 CORBA 程序进行互操作,前一程序可以在几乎所有的计算机、操作系统、编程语言和网络上,后一程序可以在几乎所有的其他计算机、操作系统、编程语言和网络上。 要进一步学习 CORBA,请访问 http://www.omg.org/gettingstarted/gettingstartedindex.htm

CORBA 技术补充了 Java 平台,因为它提供了分布式对象框架、支持此框架的服务以及与其他语言的互操作性。CORBA 技术是 Java 2 平台的主要部分,它正用于 Enterprise JavaBeans 组件、 运行在 Internet Inter-ORB 协议上的Java 远程方法调用 API ("Java RMI-IIOP"),以及 Java IDL API ("Java IDL")。

OMG 接口定义语言(Interface Definition Language,IDL)可用于描述一些接口,该接口由远程对象实现。IDL 可用于定义接口的名称,以及定义每个属性和方法的名称。一旦创建 IDL 文件,就可以在任何语言中,使用 IDL 编译器来生成客户端存根模块 (stub) 和服务器骨架语句 (server skeleton),OMG已经为此定义了这种语言映射的规范。要进一步了解 OMG IDL,请访问 http://www.omg.org/gettingstarted/omg_idl.htm

Java IDL 使得分布式 Java 应用程序能够透明地调用远程网络服务上的操作,而该服务使用对象管理组织 (http://www.omg.org/) 定义的行业标准  OMG IDL 和 IIOP。运行在 IIOP API 上的 Java RMI 使得可以通过 javax.rmi API 来对 CORBA 服务器和应用程序进行编程。

编写 EJB 组件的开发人员可以遵循 Java RMI 编程模型,并将它用于他们的分布式对象模型,在该模型中,跨越所有应用程序服务器常见的所需传输是 Java RMI-IIOP。在异构服务器环境中,到 CORBA 的 EJB 体系结构的标准映射使得能够进行下述的互操作:

  • 使用来自某一供应商 ORB 的客户端可以访问驻留在服务器上的企业 bean,而该服务器支持由另一供应商提供的 Enterprise JavaBeans 技术(“EJB 服务器”)。
  • 一台 EJB 服务器上的企业 bean 可以访问另一台 EJB 服务器上的企业 bean。
  • 除了Java 编程语言之外,用某一语言编写的 CORBA 客户端可以访问任何 EJB 组件,前提是要有一个从 OMG IDL 到那种编程语言的映射。

本文档的其余部分提供了 CORBA 客户端应用程序的例子,该应用程序访问了企业 bean 对象。在本文档中,CORBA 客户端就是使用 CORBA 支持的任何语言编写的客户端应用程序,这些编程语言包括 Java 编程语言、C++、C、Smalltalk、COBOL、Ada、Lisp 或 Python。虽然本例中的 Java 代码特定于企业 bean,但开发 CORBA 的客户端的过程是相同的,并且开发的 CORBA 客户端可以访问使用 Java RMI-IIOP API 创建的服务器。

可以在 链接到类似例子 中找到一些链接,它们指向其他实现了 J2EE 技术的供应商提供的类似应用程序。




开发访问 Enterprise JavaBean 组件的 CORBA 客户端

这是一个关于如何开发 CORBA 客户端应用程序以便访问 EJB 组件的例子。在本例中,客户端是用 C++ 编程语言编写的,但客户端可以是由 CORBA 支持的任何语言编写的。

下面的几节展示了 CORBA 客户端的一般开发过程,开发完的 CORBA 客户端可以访问企业 bean:

  1. 编写 Enterprise JavaBean 组件
  2. 生成 CORBA IDL
  3. 创建 CORBA 客户端
  4. 部署 Enterprise JavaBean 组件
  5. 运行客户端可执行文件

本文档也包括:

为了使例子变得简单,我们采取了一些捷径。有关构建更加高级的解决方案的信息,请参阅 针对复杂接口的技巧

    第 1 部分:编写 Enterprise JavaBean 组件

    下面的一些例子展示了企业 bean 的代码,它将从 Java RMI-IIOP 和 CORBA 客户端接收发送给应用程序服务器的字符串日志消息。企业 bean 将在服务器上把它们与当前服务器时间一起打印出来。

  1. /Java/src/ejbinterop 目录中创建如下文件:Logger.javaLoggerHome.javaLoggerEJB.java LogMessage.java。

    Logger.java

    Logger.java 文件是企业 bean 的远程接口,因此,它扩展了 EJBObject。远程接口提供了 EJB 对象的远程客户端视图,并定义了可由远程客户端调用的 business 方法。

    
    //Code Example 1: Logger.java
    package ejbinterop;
    
    import javax.ejb.EJBObject;
    import java.rmi.RemoteException;
    
    /**
     * Accepts simple String log messages and prints
     * them on the server.
     */
    public interface Logger extends EJBObject
    {
        /**
         * Logs the given message on the server with
         * the current server time.
         */
        void logString(String message) throws RemoteException;
    }

    LoggerHome.java

    LoggerHome.java 文件扩展了 EJBHomeEJBHome 接口必须由所有 EJB 组件的远程 home 接口来扩展。home 接口定义了一些方法,使得远程客户端可以创建、查找和删除 EJB 对象,以及创建、查找和删除不针对 EJB 实例的 home business 方法。

    
    //Code Example 2: LoggerHome.java
    package ejbinterop;
    
    import java.rmi.RemoteException;
    import javax.ejb.EJBHome;
    import javax.ejb.CreateException;
    
    public interface LoggerHome extends EJBHome
    {
        Logger create() throws RemoteException, CreateException;
    }

    LoggerEJB.java

    LoggerEJB.java 文件包含了会话 bean 的代码。会话 bean 是一种企业 bean,它由客户端创建,并且通常只在一个客户/服务器会话期间存在。会话 bean 执行像计算或访问客户端数据库这样的操作。在本例中,企业 bean 从客户端接收简单的字符串日志消息,并在服务器上打印它们。

    
    //LoggerEJB.java
    package ejbinterop;
    
    import javax.ejb.*;
    import java.util.*;
    import java.rmi.*;
    import java.io.*;
    
    /**
     * Accepts simple String log messages and prints
     * them on the server.
     */
    public class LoggerEJB implements SessionBean {
    
        public LoggerEJB() {}
        public void ejbCreate() {}
        public void ejbRemove() {}
        public void ejbActivate() {}
        public void ejbPassivate() {}
        public void setSessionContext(SessionContext sc) {}
    
        /**
         * Logs the given message on the server with
         * the current server time.
         */
        public void logString(String message) {
            LogMessage msg = new LogMessage(message);
    
            System.out.println(msg);
        }
    }

    LogMessage.java

    LogMessage.java 文件取得当前的日期和时间,然后创建格式化字串来显示消息,并将消息打印到服务器。

    //LogMessage.java
    package ejbinterop;
    
    import java.io.Serializable;
    import java.util.Date;
    import java.text.*;
    
    /**
     * Simple message class that handles pretty
     * printing of log messages.
     */
    public class LogMessage implements Serializable
    {
        private String message;
        private long datetime;
    
        /**
         * Constructor taking the message. This will
         * take the current date and time.
         */
        public LogMessage(String msg) {
            message = msg;
            datetime = (new Date()).getTime();
        }
    
        /**
         * Creates a formatted String showing the message.
         */
        public String toString() {
            StringBuffer sbuf = new StringBuffer();
            DateFormat dformat
                = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
    	DateFormat.LONG);
            FieldPosition fpos = new
                FieldPosition(DateFormat.DATE_FIELD);
            dformat.format(new Date(datetime), sbuf, fpos);
            sbuf.append(": ");
            sbuf.append(message);
            return sbuf.toString();
        }
    }

  2. 编译本节编写的文件,例如:

    javac -classpath $J2EE_HOME/lib/j2ee.jar:.. *.java

    这些命令在当前目录中为所有的 .java 文件创建了类文件。这个命令和本文中的其他命令假定已经正确设置了 J2EE_HOME 环境变量。使用 $J2EE_HOME 是 Unix® 操作系统的规定。当在 Microsoft Windows 操作环境中,请替换 %J2EE_HOME%

    第 2 部分:生成 CORBA IDL

    本节讨论如何从 Java 类文件中生成接口定义语言(Interface Definition Language,IDL),并且假定 Java 类文件已在前一节中生成。在本例中,我们将使用 rmic 编译器,以便将 Java 代码映射到 IDL。IDL 提供了纯声明性的、编程语言无关的方式来指定对象的 API。

  3. 针对 Java 类文件运行 rmic 编译器,该 Java 类文件已在前一步骤中生成,其命令如下:
    rmic -idl -noValueMethods -classpath 
      $J2EE_HOME/lib/j2ee.jar:<path_to_ejbinterop_dir> 
      -d <path_to_where_idl_files_should_be_generated> 
      ejbinterop.Logger ejbinterop.LoggerHome
    

    在前面的例子中,我们包括了 .jar 文件和 ejbinterop 文件的目录,.jar 文件中包含有 javax.ejb 包的定义。如果您正在使用 JavaTM 2 Platform, Enterprise Edition (J2EETM), version 1.3 Reference Implementation (RI),那么 .jar 文件就位于 $J2EE_HOME/lib/j2ee.jar

    在上面的 rmic 命令行中,我们推荐了一种捷径——使用 noValueMethods 选项。这个选项告诉 rmic 跳过具有参数或返回类型的任何方法,这里的返回类型将被映射到 CORBA 值类型。有利的方面在于它将防止我们生成许多不必要的 IDL,在 C++客户端中,我们可能必须实现这些 IDL。不利的方面在于我们只能使用原始的数据类型、数组和字符串,而不能使用自己的 Java 类类型来作为参数或返回类型。 有关进一步信息,请阅读 针对复杂接口的技巧

    在 Java 类文件上运行 rmic 编译器会生成下面的一些文件,文件所处的目录由上面 rmic 语句的 -d 选项指出:

    • java/lang/Ex.idl
    • java/lang/Exception.idl
    • java/lang/Object.idl
    • java/lang/Throwable.idl
    • java/lang/ThrowableEx.idl
    • javax/ejb/CreateEx.idl
    • javax/ejb/CreateException.idl
    • javax/ejb/EJBHome.idl
    • javax/ejb/EJBMetaData.idl
    • javax/ejb/EJBObject.idl
    • javax/ejb/Handle.idl
    • javax/ejb/HomeHandle.idl
    • javax/ejb/RemoveEx.idl
    • javax/ejb/RemoveException.idl
    • ejbinterop/Logger.idl
    • ejbinterop/LoggerHome.idl

     

    注意:许多生成文件包含了只能在 Java 编程环境中使用的 API 。 例如,目前 EJBMetaData 实现特定于每个应用程序服务器,因此很难开发等效设施,以便在除 Java 平台外的平台上继续超时工作。一种选择是将它们从 IDL 中删除,但如果这样做,那么每次改变 Java 接口,并从 rmic 编译器中重生成 IDL 文件时,就必须从 IDL 中删除它们。

    注意: 由于 CORBA 异常不支持继承,因此针对 IDL 映射的 Java 语言创建了 Ex 类,它包含了代表实际 Java 异常的 CORBA 值类型。在这个基本的例子中,不必过多担心异常支持。有关异常的进一步信息,请参阅 http://java.sun.com/j2se/1.4.2/docs/guide/idl/jidlExceptions.html

  4. 使用 C++ 供应商的“IDL to C++”编译器来编译 IDL 文件,以便生成对应于 IDL 的 C++ 代码。不同的供应商之间,这个过程的步骤会有区别,因此有必要参考产品文档,取得针对供应商的特定步骤。

    第 3 部分:创建 CORBA 客户端

    客户端应用程序可以使用 CORBA 支持的任何语言编写。下面的例子提供了针对于 C++ 客户端的代码,只要给予对象请求代理人( Object Request Broker,简称 ORB)和 LoggerHome 对象的 corbaname URL,它就会在服务器上将简单字符串消息记录到日志中。您必须根据 C++ ORB 供应商的库来调整 include 语句,并修改注册值工厂的代码。本例是针对  ORBacus for C++ 4.0.5 编写的,因此本例中的一些 C++ 代码是特定于该产品的。

    corbaname URL 是可阅读的 URL 格式,它允许您访问 CORBA 对象。它用于从特定命名上下文解析字符串化的名称。这是 J2EE v 1.3 平台中的新特性,它作为 CORBA 互操作命名服务(Interoperable Naming Service,简称 INS)的一部分。INS 是 CORBA 对象服务(CORBA Object Services,简称COS)命名服务的扩展,在以前版本的 J2EE 平台中已经交付使用。为了进一步了解 INS,请访问 http://java.sun.com/j2se/1.4.2/docs/guide/idl/jidlNaming.html#INS

    在本例中,客户端代码执行下面的一些操作:

    • 创建对象请求代理(ORB)。ORB 将对象请求服务连接到提供它们的对象。

    • 注册值工厂。

    • 在命名上下文中查找 corbaname URL 指向的 LoggerHome 对象。

    • 从返回给 LoggerHome 对象的对象中执行安全的向下转换。

    • 创建 LoggerEJB 对象引用。

    • 在日志中记录消息。

    • 告诉应用程序服务器不再使用 EJB 引用。

  5. 使用类似于下面的 C++ 代码来创建客户端。准确的代码可能与 C++ 实现有关。这些代码是针对于 ORBacus for C++ 4.0.5 编写的,因此本例中的一些 C++ 代码可能特定于该产品。

    //Code Example: Client.cpp
    #include <fstream.h>
    
    // C++ ORB Vendor specific include files
    // These are from C++ ORBacus 4.0.5
    
    #include <OB/CORBA.h>
    #include <OB/OBORB.h>
    
    // Include files generated from our IDL
    #include <java/lang/Exception.h>
    #include <java/lang/Throwable.h>
    #include <javax/ejb/CreateException.h>
    #include <javax/ejb/RemoveException.h>
    #include <ejbinterop/Logger.h>
    #include <ejbinterop/LoggerHome.h>
    
    /**
     * Given an ORB and a corbaname URL for a LoggerHome
     * object, logs a simple string message on the server.
     */
    void
    run(CORBA::ORB_ptr orb, const char* logger_home_url)
    {
      cout << "Looking for: " << logger_home_url << endl;
    
      // Look up the LoggerHome object in the naming context
      // pointed to by the corbaname URL
      CORBA::Object_var home_obj
        = orb->string_to_object(logger_home_url);
    
      // Perform a safe downcast
      ejbinterop::LoggerHome_var home
        = ejbinterop::LoggerHome::_narrow(home_obj.in());
    
      assert(!CORBA::is_nil(home));
    
      // Create a Logger EJB reference
      ejbinterop::Logger_var logger = home->create();
    
      CORBA::WStringValue_var msg =
        new CORBA::WStringValue((const CORBA::WChar*)L"Message 
          from a C++ client");
      
      cout << "Logging..." << endl;
    
      // Log our message
      logger->logString(msg);
    
      // Tell the application server we won't use this
      // EJB reference any more
      logger->remove();
    
      cout << "Done" << endl;
    }
    
    /**
     * Simple main method that checks arguments, creates an
     * ORB, and handles exceptions.
     */
    int
    main(int argc, char* argv[])
    {
      int exit_code = 0;
      CORBA::ORB_var orb;
    
      try {
    
      // Check the arguments
      if (argc != 2) {
        cerr << "Usage: Client <corbaname URL of LoggerHome>" << endl;
        return 1;
      }
    
      // Create an ORB
      orb = CORBA::ORB_init(argc, argv);
    
      // Register value factories
    
      // NOTE: This is overkill for the example since we'll never
      // get these exceptions.  Also, the _OB_id method is a
      // proprietary feature of ORBacus C++ generated code.
      CORBA::ValueFactory factory = new java::lang::Throwable_init;
      orb -> register_value_factory(java::lang::Throwable::_OB_id(),
        factory);
      factory -> _remove_ref();
    
      factory = new java::lang::Exception_init;
      orb -> register_value_factory(java::lang::Exception::_OB_id(),
        factory);
      factory -> _remove_ref();
    
      factory = new javax::ejb::CreateException_init;
      orb -> 		    register_value_factory(javax::ejb::CreateException::_OB_id(),
          factory);
      factory -> _remove_ref();
    
      factory = new javax::ejb::RemoveException_init;
      orb ->
        register_value_factory(javax::ejb::RemoveException::_OB_id(),
          factory);
      factory -> _remove_ref();
    
      // Perform the work
      run(orb, argv[1]);
    
    } catch(const CORBA::Exception& ex) {
      // Handle any CORBA related exceptions
      cerr << ex._to_string() << endl;
      exit_code = 1;
    }
    
      // Release any ORB resources
      if (!CORBA::is_nil(orb)) {
        try {
          orb -> destroy();
        } catch(const CORBA::Exception& ex) {
          cerr << ex._to_string() << endl;
          exit_code = 1;
        }
      }
    
      return exit_code;
    }
  6. 使用 C++ 编译器来编译所有的 C++ 文件,包括 Client.cpp 文件,创建客户端可执行文件。不同平台之间,这样的一些工具的区别甚大,因此有必要参考产品文档,获得它的说明。

    第 4 部分:部署 Enterprise JavaBean 组件

  7. 使用满意的应用程序服务器部署企业 bean。下面的一些步骤描述了如何部署 LoggerEJB 组件,它使用了 J2EE 1.3 Reference Implementation (RI)。

    1. 通过键入如下命令,从终端窗口或命令行提示中启动 RI 应用程序:
      	$J2EE_HOME/bin/j2ee -verbose

    2. 当 J2EE 1.3 RI 指出“J2EE 启动完成”时,键入如下命令,从另一终端窗口或命令提示中运行部署工具:

      	$J2EE_HOME/bin/deploytool

    3. 从部署工具中,选择 File -> New -> Application。

    4. 在 Application File Name 字段中,输入 Logger.ear,以指出要在其中创建应用程序的文件。

    5. 在 Application Display Name 字段中,输入 Logger。

    6. 选择 OK 来保存设置,关闭这个对话窗口。

    7. 从部署工具中,选择 File -> New -> Enterprise Bean。

    8. 如果出现 Introduction 屏幕,选择 Next,否则继续。

    9. 在 New EnterpriseBean Wizard 中,在 Contents 框中选择 Edit。

    10. 扩展 Available Files 列表,添加下面的 4 个 .class 文件,它们来自 ejbinterop 包:Logger.classLoggerHome.classLoggerEJB.class LogMessage.class。选择 OK,然后选择 Next。

    11. 选择 Stateless Session Bean Type。

    12. 选择 ejbinterop.LoggerEJB 用于 Enterprise Bean Class

    13. 选择 ejbinterop.LoggerHome 用于 Remote Home Interface

    14. 选择 ejbinterop.Logger 用于 Remote Interface

    15. 选择 Next 按扭,直到看到 Security Settings 页。

    16. 选择 Deployment Settings 按扭。

    17. 选择 Support Client Choice .

    18. 选择 OK 保存设置并关闭这个对话窗口。

    19. 选择 Finish.

    20. 从部署工具中,选择 Tools -> Deploy。

    21. 如果只运行 Java RMI-IIOP 客户端,选择 Return Client JAR。

    22. 选择 Next。

    23. JNDI Name for our LoggerEJB 字段中输入 ejbinterop/logger

    24. 选择 Finish。

    25. 选择 File -> Exit 来退出部署工具。

    现在已经部署了具有 LoggerEJB 组件的 Logger 应用程序,它准备接收消息。

    第 5 部分:运行客户端可执行文件

  8. 运行客户端可执行文件。运行客户端可执行程序的一种方法是,切换到包含可执行客户端文件的目录,然后在终端窗口中输入下面的 URL:

    Client corbaname:iiop:1.2@localhost:1050#ejbinterop/logger

    在这个 URL 中,

    • Client 是要运行的应用程序的名称。

    • corbaname 指出将从特定的命名上下文中解析字符串化的名称。

    • iiop:1.2 告诉 ORB 使用 IIOP 协议和 GIOP 1.2。

    • 要在其上查找引用的宿主计算机是 localhost——本地计算机。为了扩展这个例子,以便在两台计算机上运行,请输入计算机的 IP 地址和主机名,而不是 localhost,服务器要在该计算机上运行。

    • 1050 是端口号,命名服务会在该端口上侦听请求。 在 J2EE v.1.3 RI 中,默认情况下,命名服务要在其上侦听的默认端口号是端口 1050。到目前为止,散列标记 (hash mark) 上的引用部分( Client corbaname:iiop:1.2@localhost:1050 ) 是某个 URL,它返回根命名上下文。

    • ejbinterop/logger 是要在命名上下文中解析的名称。

    如果您正在使用 J2EE 1.3 Reference Implementation,应该会看到类似于如下的一条消息,该消息是在应用程序服务器上被打印的:

    
    Sep 21, 2001 3:33:07 PM PDT: Message from a C++ client ejbinterop/
    logger is the name to be resolved from the Naming Service.
    

    第 6 部分:停止 J2EE 服务器

  9. 停止 J2EE 服务器。为了停止服务器,可以在终端窗口或命令行提示中,输入这条命令。
    $J2EE_HOME/bin/j2ee -stop

    不同的操作系统之间,停止运行中进程的过程是不同的,因此如果正在使用不同的服务器,可以参考系统文档以取得详细信息。




创建 Java RMI-IIOP 客户端应用程序

使用相同的例子,可以容易地开发连接到企业 bean 的 Java RMI-IIOP 客户端,。与使用 C++ 的例子的区别在于:

  • 在客户端 CLASSPATH 中,必须包括客户端 .jar 文件的位置,该文件是由运行需要的企业 bean 的应用程序服务器创建的。那个 .jar 文件包含了必要的客户端存根模块。

  • 当使用 J2EE 1.3 RI 部署应用程序时,检查 Deploy 屏幕第一页上的 Deploytool 中的 Return Client Jar 框。

下面的代码是 Java RMI-IIOP 版本的 LoggerEJB 组件客户端。遵循与 C++ 客户端例子所展示的相同步骤。当运行客户端时,使用与 C++ 例子中相同的 URL。

    //Code Example: LogClient.java
    package ejbinterop;
    
    import java.rmi.RemoteException;
    import javax.rmi.*;
    import java.io.*;
    import javax.naming.*;
    import javax.ejb.*;
    
    /**
     * Simple Java RMI-IIOP client that uses an EJB component.
     */
    public class LogClient
    {
        /**
         * Given a corbaname URL for a LoggerHome,
         * log a simple String message on the server.
         */
        public static void run(String loggerHomeURL)
            throws CreateException, RemoveException,
                   RemoteException, NamingException
        {
            System.out.println("Looking for: " + loggerHomeURL);
    
            // Create an InitialContext. This will use the
            // CosNaming provider we will specify at runtime.
            InitialContext ic = new InitialContext();
    
            // Lookup the LoggerHome in the naming context
            // pointed to by the corbaname URL
            Object homeObj = ic.lookup(loggerHomeURL);
    
            // Perform a safe downcast
            LoggerHome home
                = (LoggerHome)PortableRemoteObject.narrow(homeObj,
    	LoggerHome.class);
    
            // Create a Logger EJB reference
            Logger logger = home.create();
    
            System.out.println("Logging...");
    
            // Log our message
            logger.logString("Message from a Java RMI-IIOP client");
    
            // Tell the application server we won't use this
            // EJB reference anymore
            logger.remove();
    
            System.out.println("Done");
        }
    
        /**
         * Simple main method to check arguments and handle
         * exceptions.
         */
        public static void main(String args[])
        {
            try {
    
                if (args.length != 1) {
                    System.out.println("Args: corbaname URL of LoggerHome");
                    System.exit(1);
                }
    
                LogClient.run(args[0]);
    
            } catch (Throwable t) {
                t.printStackTrace();
                System.exit(1);
            }
        }
    }

使用 Java RMI-IIOP 客户端运行应用程序

当使用 Java RMI-IIOP 客户端,而不是 C++ 客户端运行示例应用程序时,请遵循这些步骤:

  1. 使用下面的命令,在 ejbinterop / 目录中编译 . java 文件:
    javac -classpath $J2EE_HOME/lib/j2ee.jar:<ejbinterop_directory> *.java
    

  2. 部署 Enterprise JavaBean 组件中所描述的那样部署 Enterprise JavaBean 组件。当运行 Java RMI-IIOP 客户应用程序时,记得在 Tools -> Deploy 页中选择 Return Client JAR 。 Deployment 主题中的一些命令指导您启动 J2EE RI 或其他应用程序服务器。

  3. 使用类似于如下命令运行客户应用程序:

    java -classpath $J2EE_HOME/lib/j2ee.jar:
    <path to LoggerClient.jar>/LoggerClient.jar:
    <directory_above_ejbinterop>:<ejbinterop_directory>
    ejbinterop.LogClient 
    corbaname:iiop:1.2@localhost:1050#ejbinterop/logger 

    在 J2EE RI 正在运行的窗口中,将会看到:

    Jan 31, 2002 2:27:47 PM PST: Message from a Java RMI-IIOP client
    

    在运行客户端的窗口中,将会看到:

    Looking for: corbaname:iiop:1.2@localhost:1050#ejbinterop/logger
    Logging...
    Done
    

  4. 停止 J2EE 服务器。




超越基本应用程序

本部分包括下述信息:

如何增强应用程序

要增强应用程序,您可以:

  • 开发使用值类型的例子。

    为达到此目的,当运行 rmic 时删除 -noValueMethods 开关。重新运行 C++ 语言的 IDL 的映射编译器,检查它是否支持已经生成的值类型。

  • Logger 中添加另一方法,它实际取得 LogMessage

针对复杂接口的技巧

对于运用不同语言的客户端和服务器之间的通信,接口是关键。为了在这方面获得成功,应该考虑下面的建议:

  • 避免将复杂的 Java 类,比如 java.util 中的集合,用于方法参数或返回类型。

    在将这些类开映射到 IDL 后,将强制您使用客户端编程语言实现它们。此外,由于 Java Object Serialization 和 RMI-IIOP API 使得类的线路格式和内部表示能够随时间不断发展,因此您的 CORBA 客户端应用程序可能在不同的 JavaTM 2 Platform, Standard Edition (J2SETM) 实现或版本上不兼容。

  • 从 IDL 开始。

    您可能想在返回类型或方法参数中使用复杂的数据结构。在本例中,试着从 IDL 开始。在 IDL 中定义数据结构,甚至定义异常,然后将它们用在 EJB 接口中。这将可以防止逆向映射的产出物进入 CORBA 接口。

    例如,刚开始试着在 IDL 中定义 LogMessage 类,然后在 Logger EJB 组件中,将 IDL 编译的 Java 语言结果类用作方法参数。

  • 避免重载 EJB 接口。

    CORBA IDL 不支持方法重载,符合 IDL 映射规范的 Java 语言解决了这一点,其方式是创建 IDL 方法定义,将方法名与它的所有 IDL 参数类型组合起来。对于使用非 Java 编程语言的开发人员来说,这带来了非常不友好的方法名。

  • 考虑使用桥。

    如果可用的选项仍然太有限,或者影响到想编写的代码,就可以考虑使用服务器端桥。在“链接到类似例子”一节列出了一些站点,您可以从这些站点中获得更多有关如何构建桥的信息。

链接到类似例子

实现 J2EE 技术的几个供应商都有一些优秀的例子和技巧,用于集成 CORBA 和 Enterprise JavaBeans 技术:

posted on 2005-02-04 11:28 jacky 阅读(250) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(10)

随笔档案

文章分类

文章档案

相册

收藏夹

java

搜索

  •  

最新评论