使用可嵌入 EJB 容器来开发应用程序

要使用可嵌入 Enterprise JavaBeans (EJB) 容器来开发应用程序,请执行本任务。在可嵌入容器中运行的应用程序启动速度更快,并且相对于在完整应用程序服务器中运行,需要的资源占用量更少。这是快速开发和测试可能最终在应用程序服务器上运行的应用程序的最佳环境。

开始之前

要创建可嵌入 EJB 容器应用程序,必须将开发环境设为使用 V8.0 的 Java™ Development Kit (JDK) V1.8 或更高版本。开发环境还必须将 WebSphere® 可嵌入容器的 Java 归档 (JAR) 文件包括在类路径中。com.ibm.ws.ejb.embeddableContainer_9.0.jar 文件位于 WebSphere Application Server 安装目录下的 \runtimes 目录中。
限制: EJB 瘦客户机 com.ibm.ws.ejb.thinclient_9.0.jar 和 EJB 可嵌入 JAR 文件 com.ibm.ws.ejb.embeddableContainer_9.0.jar 不能在同一个类路径中共存。
限制: com.ibm.ws.ejb.embeddableContainer_9.0.jar 文件仅限提供英文消息。如果您需要其他语言的支持,请使用 com.ibm.ws.ejb.embeddableContainer_nls_9.0.jar 文件取代 com.ibm.ws.ejb.embeddableContainer_9.0.jar。com.ibm.ws.ejb.embeddableContainer_nls_9.0.jar 位于 WebSphere Application Server 安装目录下的 \runtimes 目录中。

如果您的 Bean 将 javax.annotation.Resource 注释与 lookup 属性配合使用,那么还必须使用 Java Endorsed Standards Override Mechanism 来覆盖系统上的 JDK 中提供的 javax.annotation.Resource API。将 app_server_root\runtimes\endorsed\endorsed_apis_9.0.jar 文件复制到您选择的目标目录中。在 Java 命令上使用 java.endorsed.dirs 属性指定包含复制的 JAR 文件的目录。

过程

  1. 创建 EJB 3.X 模块。 创建此模块时,您必须确保它仅包含 WebSphere 可嵌入容器支持的功能部件。要获取受支持功能的完整列表,请参阅可嵌入 EJB 容器功能主题。确保 EJB 模块在可嵌入容器的类路径中。您可以将 EJB 模块打包成类的目录,也可以将其打包成 EJB JAR 文件。
  2. 创建主类,这个类将启动可嵌入容器并在企业 Bean 上启动方法。 使用 javax.ejb.EJBContainer 类创建可嵌入容器的实例(并可以有选择地传递容器配置参数)、获取容器命名上下文以及关闭可嵌入容器。

    以下样本代码演示可嵌入容器的用法:

    //EmbeddableContainerSample.java
    import java.util.HashMap;
    import java.util.Map;
    import javax.ejb.embeddable.EJBContainer;
    import my.pkg.MyBeanIface; // this is the local business interface of the
                               // enterprise bean
    
    public class EmbeddableContainerSample {
    
       public static void main(String[] args) throws Throwable {
    
          // Create a properties map to pass to the embeddable container:
          Map<String,Object> properties = new HashMap<String,Object>();
    
          // Specify that you want to use the WebSphere embeddable container:
          properties.put(EJBContainer.PROVIDER, 
              "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
    
          // Create the container instance, passing it the properties map:
          EJBContainer ec = EJBContainer.createEJBContainer(properties);
    
          // Use the container context to look up a bean:
          MyBeanIface bean = ec.getContext().lookup(
              "java:global/MyEJBModule/MyBean!my.pkg.MyBeanIface");
    
          // Invoke a method on the bean instance:
          bean.doStuff();
    
          ...
    
    
          // Close the embeddable container:
          ec.close();
    
       }
    }
    

    在此样本代码中,您通过对 com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider 类指定 EJBContainer.PROVIDER 属性,并将该属性传递到 EJBContainer.createEJBContainer 方法而创建了可嵌入容器的实例。您使用了容器命名上下文来查找局部企业 Bean,例如 MyBean。此查找使用了可移植的全局命名语法。

    此样本代码依赖于可嵌入容器来自动扫描类路径,以查找 EJB 模块 MyEJBModule。或者,您可能已使用 EJBContainer.MODULES 属性指定了要启动的模块。 使用此属性指定 JVM 类路径中必须存在的模块名称的字符串或字符串数组。

    您还可以指定在类路径中不存在的模块的文件或文件数组。如果这些模块需要其他库,而 JVM 类路径中未设置这些库,那么此文件或文件数组方法可能要求您修改当前线程上的上下文类装入器。

    以下代码样本说明如何使用文件数组来启动可嵌入容器:

    ...
    // Create the properties object to pass to the embeddable container:
    Map<String,Object> props = new HashMap<String,Object>();
    
    // Specify the EJB modules to start when creating the container:
    File[] ejbModules = new File[2];
    ejbModules[0] = new File("/home/myusername/ejbs/ShoppingCartEJB.jar");
    ejbModules[1] = new File("/home/myusername/ejbs/OnlineCatalogEJB.jar");
    props.put(EJBContainer.MODULES, ejbModules);
    
    // In this example, both of these modules rely on code in a shared library.
    // In order for the embeddable container to load the shared library, the
    // context classloader must be able to load that shared library.
    
    // Set up the context classloader so that it can load the shared library:
    File sharedLibUtilityFile = new File("/home/myusername/ejbs/SharedLib.jar");
    ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
    ClassLoader newCL = new URLClassLoader(new URL[]{
       sharedLibUtilityFile.toURI().toURL()}, oldCL);
    Thread.currentThread().setContextClassLoader(newCL);
    
    // Now, create the embeddable container, passing it the properties map:
    EJBContainer ec = EJBContainer.createEJBContainer(props);
    
    // Invoke an EJB loaded by the embeddable container:
    ...

    在查找 Bean 实例之后,在其中启动方法。完成与容器相关的任务之后,关闭容器,这将启动被标记为 PreDestroy 的 Bean 方法并关闭可嵌入容器。请先关闭可嵌入容器实例,然后再创建新实例。

  3. 定制可嵌入容器。 您可以使用属性来定制可嵌入 EJB 容器运行时。 要获取受支持属性的完整列表,请参阅主题可嵌入 EJB 容器定制属性
  4. 如果您希望应用程序使用诸如数据源之类的资源,那么您可以在传递到可嵌入容器的属性映射中或在属性文件中创建和配置这些资源。

    可嵌入 EJB 容器的一个常见用法是测试最终在应用程序服务器中运行的应用程序。其中很多应用程序都依赖于使用管理控制台或 wsadmin 脚本编制工具在服务器中配置的 JDBC 数据源。由于可嵌入容器中不存在这些工具,因此您可以配置 WebSphere 可嵌入容器以通过将属性传递给此容器来提供这些资源。

    数据源配置属性还可以存储在属性文件中。可嵌入容器自动装入名为 embeddable.properties 的文件(位于当前工作目录中)中存储的属性。您可以通过将新文件位置指定为 com.ibm.websphere.embeddable.configFileName 系统属性的值来覆盖此文件位置。

    数据源配置属性均以 DataSource 开头,并且后面带有一个词汇,此词汇用于标识正在配置的数据源。例如,DataSource.myDataSource.someProperty 与名为 DataSource.anotherDS.someOtherProperty 的属性分别适用于不同数据源。数据源属性的列表位于可嵌入 EJB 容器定制属性信息中。

    以下是应用程序能够如何使用数据源的示例:

    ...
    InitialContext context = new InitialContext();
    DataSource ds = (DataSource) context.lookup("env/jdbc/AcctsPayableDS");
    Connection conn = ds.getConnection();
    // Use the connection to access the AcctsPayableDS database
    ...

    在服务器中,系统管理员已创建了一个数据源并在 JNDI 名称空间中将其绑定到 env/jdbc/AcctsPayableDS。或者,代码可能已在映射至 env/jdbc/AcctsPayableDS 的 java:comp namespace 中查找数据源,或者已指定了一个要与数据源一起插入的 EJB 字段。在所有情况下,数据源都必须在名称空间中绑定。使用以下代码在创建可嵌入容器实例时以编程方式完成此操作:

    ...
    // Create a properties map to store embeddable container config properties
    Map<String,Object> props = new HashMap<String,Object>();
    
    // Set the JNDI name to bind this data source:
    props.put("DataSource.ds1.name", "env/jdbc/AcctsPayableDS");
    
    // Set the data source class name ; this is a required property
    // This example uses a Derby JDBC driver
    props.put("DataSource.ds1.dataSourceClass",
       "org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource");
    
    // Set the database name
    props.put("DataSource.ds1.databaseName", "AcctsPayableTestDB");
    
    // Create the embeddable container instance with our custom properties
    EJBContainer ec = EJBContainer.createEJBContainer(props);
    
    // Now invoke an EJB in the embeddable container...
    ...

    先前代码将对名为 AcctsPayableTestDB 的 Apache Derby 数据库创建一个简单数据源,并在 env/jdbc/AcctsPayableDS 中绑定该数据源。您可以通过将以下文本放入到 JVM 当前工作目录中名为 embeddable.properties 的文件中,从而以声明方式完成这一相同任务。您还可以将此文本放在任何文本文件中,并在 com.ibm.websphere.embeddable.configFileName 系统属性中指定该文本文件。

    DataSource.ds1.name=env/jdbc/AcctsPayableDS
    DataSource.ds1.dataSourceClass=org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource
    DataSource.ds1.databaseName=AcctsPayableTestDB

    在发开 EJB 时使用资源引用(而非直接查找数据源)。

  5. 您的应用程序可以使用基于 Java EE 角色的安全性(以声明方式和编程方式)来验证基于 EJB 角色的安全性。 您可以完成以下操作以验证基于 EJB 角色的安全性:
    • 定义要用于授权的用户。
    • 将用户分配给 EJB 中声明的角色。
    • 在您的 EJB 中测试 EJBContext 方法 isCallerInRole() 和 getCallerPrincipal() 的使用。

    以下是应用程序能够如何使用声明式和程序化安全性的示例:

    import java.util.HashMap;
    import java.util.Map;
    import javax.ejb.EJBContainer;
    import my.pkg.MyBeanIface; // this is the local business interface of the
                               // enterprise bean
    public class EmbeddableContainerSample {
    
       public static void main(String[] args) throws Throwable {
          // Create a properties map to pass to the embeddable container:
          Map<String,Object> properties = new HashMap<String,Object>();
          // Specify that you want to use the WebSphere embeddable container:
          properties.put(EJBContainer.PROVIDER, 
              "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
          
          // Specify that you want security checking enabled:
          properties.put("com.ibm.websphere.securityEnabled", "true");
          
          // Assign the users bob, fred, and mary to the role employee:
          props.put("role.employee", "bob, fred, mary");
          // Assign the user fred to the role manager:
          props.put("role.manager", "fred");
          // The user fred will be used for the runAs role manager:
          props.put("role.runAs.manager", "fred");
          // The user fred will be used for role authorization when invoking 
          // methods on the EJB:
          props.put("user.invocation", "fred");
          // Create the container instance, passing it the properties map:
          EJBContainer ec = EJBContainer.createEJBContainer(properties);
          // Use the container context to look up a bean:
          MyBeanIface bean = ec.getContext().lookup(
              "java:global/MyEJBModule/MyBean!my.pkg.MyBeanIface");
          // Invoke a method on the bean instance:
          bean.doStuff();
          ...
          // Close the embeddable container:
          ec.close();
       }
    }

    先前代码启用安全性,然后创建两个角色:employeemanager,以及三个用户:bobmaryfred。然后,此代码指定在以 manager 角色运行时使用 fred 用户。在创建可嵌入容器之前,此代码将调用用户设置为 fred。这意味着,当 EJB 方法启动时,EJB 方法是由 fred 启动,这意味着,如果这些方法需要角色 employeemanager,那么 fred 可以访问这些方法。

  6. 您的应用程序可以为每个 Bean 指定局部事务包含范围 (LTC) 行为。有关 LTC 的说明,请阅读有关局部事务包含范围的信息。

    以下是应用程序能够如何指定 LTC 解析器和未解析操作的示例:

    import java.util.HashMap;
    import java.util.Map;
    import javax.ejb.EJBContainer;
    import my.pkg.MyBeanIface; // this is the local business interface 
                               // of the enterprise bean
    
     public class EmbeddableContainerSample {
    
       public static void main(String[] args) throws Throwable {
    
          // Create a properties map to pass to the embeddable container:
          Map<String,Object> properties = new HashMap<String,Object>();
          // Specify that you want to use the WebSphere embeddable container:
          properties.put(EJBContainer.PROVIDER, 
              "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
          
          // Specify that you want the LTC resolver container-at-boundary:
          properties.put("Bean.myApp1#moduleA#bean101.LocalTransaction.Resolver",
                                                          "ContainerAtBoundary");
          
          // Specify that you want the LTC unresolved action commit:
          properties.put("Bean.myApp1#moduleA#bean101.LocalTransaction.UnresolvedAction",
                                                          "Commit");
          
          // Create the container instance, passing it the properties map:
          EJBContainer ec = EJBContainer.createEJBContainer(properties);
          // Use the container context to look up a bean:
          MyBeanIface bean = ec.getContext().lookup(
              "java:global/MyEJBModule/MyBean!my.pkg.MyBeanIface");
          // Invoke a method on the bean instance:
          bean.doStuff();
          ...
          // Close the embeddable container:
          ec.close();
       }
    }

    先前代码将指定 Bean 的解析器操作设置为非缺省值 container-at-boundary,并且导致未解析操作成为落实事务的非缺省操作。

    如果启动可嵌入容器时未指定应用程序名称,那么必须省略 <application_name>。但是,您必须使用 # 定界符。例如:
    properties.put("Bean.#moduleA#bean101.LocalTransaction.UnresolvedAction", "Commit"); 

指示主题类型的图标 任务主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tejb_dvemcontainer
文件名:tejb_dvemcontainer.html