+

Search Tips   |   Advanced Search

Develop applications using the embeddable EJB container

Use this task to develop applications using the embeddable EJB container. Applications running in the embeddable container start faster and require a smaller footprint than when running in the full application server. It is an optimal environment for quickly developing and testing applications that might eventually run on the application server.

To create an embeddable EJB container application, set the development environment to use Version 6.0 of Java Development Kit (JDK) Version 1.6 or higher. Your development environment must also include the WebSphere embeddable container JAR file in the class path. The com.ibm.ws.ejb.embeddableContainer_8.0.0.jar file is located in the \runtimes directory under the installation directory of WAS.

Restriction: The EJB thin client, com.ibm.ws.ejb.thinclient_8.0.0.jar, and the EJB embeddable JAR file, com.ibm.ws.ejb.embeddableContainer_8.0.0.jar, cannot coexist in the same class path.

Restriction: The com.ibm.ws.ejb.embeddableContainer_8.0.0.jar file is limited to providing messages in English. If we need support for additional languages use the com.ibm.ws.ejb.embeddableContainer_nls_8.0.0.jar file in place of com.ibm.ws.ejb.embeddableContainer_8.0.0.jar. The com.ibm.ws.ejb.embeddableContainer_nls_8.0.0.jar is located in the \runtimes directory under the installation directory of WAS.

If wer beans use the javax.annotation.Resource annotation with the lookup attribute, which is new in EJB 3.1, you must also use the Java Endorsed Standards Override Mechanism to override the javax.annotation.Resource API that is available in the JDK on the system. Copy the app_server_root\runtimes\endorsed\endorsed_apis_8.0.0.jar file into a target directory of the choice. Use the java.endorsed.dirs property on the Java command to specify your directory containing the copied JAR file.

  1. Create an EJB 3.X module. When creating this module, you must ensure that it only contains features that are supported by WebSphere embeddable container. For a full list of supported functions, see the Embeddable EJB container functions topic. Ensure that the EJB modules are on the class path of the embeddable container. We can package the EJB module as directories of classes or as EJB JAR files.

  2. Create the main class that launches the embeddable container and starts methods on the enterprise beans. Use the javax.ejb.EJBContainer class to create an instance of the embeddable container (optionally passing container configuration parameters), get the container naming context, and close the embeddable container.

    The following sample code illustrates usage of the embeddable container:

    //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 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();
    
       }
    }
    

    In this sample code, created an instance of an embeddable container by specifying the EJBContainer.PROVIDER property to the com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider class, and passing that property to the EJBContainer.createEJBContainer method. You used the container naming context to look up a local enterprise bean, for example, MyBean. The lookup uses the portable global naming syntax.

    This sample code relies on the embeddable container to automatically scan the class path to find the EJB module, MyEJBModule. Alternatively, you could have specified the modules we wanted to start using the EJBContainer.MODULES property. Specify a string or string array of module names that must exist in the JVM class path.

    We can also specify a file or file array of modules that do not exist in the class path. This file or file array approach might require you to modify the context class loader on the current thread, if these modules require additional libraries that are also not on the JVM class path.

    The following code sample illustrates how to start the embeddable container using a file array.

    ...
    // 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:
    ...

    After looking up the bean instance, start methods on it. When you finish the container-related tasks, close the container, which starts the bean methods marked as PreDestroy and closes the embeddable container. Close the embeddable container instance before creating a new one.

  3. Customize the embeddable container. We can use properties to customize the embeddable EJB container run time. For a full list of supported properties, see the topic Embeddable EJB container custom properties.

  4. If we want the application to use resources like data sources, then we can create and configure those resources in the properties map passed to the embeddable container or in a properties file.

    One common usage of the embeddable EJB container is to test applications that eventually run in the application server. Many of these applications rely on JDBC data sources configured in the server using the console or wsadmin scripting tool. Since these tools do not exist in the embeddable container, we can configure the WebSphere embeddable container to provide these resources by passing properties to it.

    The data source configuration properties can also be stored in a properties file. The embeddable container automatically loads properties stored in a file called embeddable.properties in the current working directory. We can override this file location by specifying the new file location as the value of the com.ibm.websphere.embeddable.configFileName system property.

    The data source configuration properties all start with DataSource, and are followed by a term that identifies which data source is being configured. For example, DataSource.myDataSource.someProperty applies to a different data source than one named DataSource.anotherDS.someOtherProperty. The list of data source properties are located in the embeddable EJB container custom properties information.

    Here is an example of how the application can use data sources:

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

    In the server, a systems administrator has created a data source and bound it in the JNDI name space to env/jdbc/AcctsPayableDS. Alternatively the code might have looked up the data source in a java:comp namespace, which is mapped to env/jdbc/AcctsPayableDS or specified an EJB field to be injected with the data source. In all cases, a data source must be bound in the namespace. Use the following code to complete this action programmatically when creating the embeddable container instance:

    ...
    // 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...
    ...

    The preceding code creates a simple data source to an Apache Derby database called AcctsPayableTestDB and binds it at env/jdbc/AcctsPayableDS. We can complete this same task declaratively by putting the following text into a file called embeddable.properties in the current working directory of the JVM. We can also put this text in any text file, and specify that text file in the com.ibm.websphere.embeddable.configFileName system property.

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

    Use resource references when developing the EJB rather than looking up data sources directly.

  5. Your application can use Java EE role-based security, both declarative and programmatic, to verify your EJB role-based security. We can complete the following actions to verify EJB role-based security:

    • Define a user to be used for authorization purposes.

    • Assign users to roles that are declared in the EJB.

    • Test the use of the EJBContext methods, isCallerInRole() and getCallerPrincipal(), in the EJB.

    Here is an example of how the application can use declarative and programmatic security:

    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 to use the WebSphere embeddable container:
          properties.put(EJBContainer.PROVIDER, 
              "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
          
          // Specify we 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();
       }
    }

    The preceding code enables security and then creates two roles, employee and manager, and three users, bob, mary, and fred. It then specifies that the fred user is used when running as the manager role. Before creating the embeddable container, it sets the invocation user as fred. This means that when EJB methods are started, they are started by fred, which means that if those methods require the role of employee or manager, fred is able to access those methods.

  6. Your application can specify Local Transaction Containment (LTC) behavior per bean. For an explanation of LTC, read about local transaction containment.

    Here is an example of how the application can specify the LTC resolver and unresolved action:

    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 to use the WebSphere embeddable container:
          properties.put(EJBContainer.PROVIDER, 
              "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
          
          // Specify we want the LTC resolver container-at-boundary:
          properties.put("Bean.myApp1#moduleA#bean101.LocalTransaction.Resolver", "ContainerAtBoundary");
          
          // Specify we 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();
       }
    }

    The preceding code sets the resolver action for the specified bean to its non-default value of container-at-boundary, and causes the unresolved action to be the non-default action that commits the transaction.

    If an application name is not specified when launching the embeddable container, the <application_name> must be omitted. However, use the # delimiter. For example:

      properties.put("Bean.#moduleA#bean101.LocalTransaction.UnresolvedAction", "Commit");


Subtopics

  • Local transaction containment