Use this task to develop applications using the embeddable Enterprise JavaBeans (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.
If your 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 your system. Copy the app_server_root\runtimes\endorsed\endorsed_apis_8.0.0.jar file into a target directory of your choice. Use the java.endorsed.dirs property on the Java command to specify your directory that contains the copied JAR file.
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 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(); } }
In this sample code, you 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 you wanted to start using the EJBContainer.MODULES property. Use this property to specify a string or string array of module names that must exist in the JVM class path.
You 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.
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 that are configured in the server using the administrative console or wsadmin scripting tool. Since these tools do not exist in the embeddable container, you 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. You 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 your 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.jndiName", "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. You 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. You 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.jndiName=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.
Here is an example of how your 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 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(); } }
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.
Here is an example of how your 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 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(); } }
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.
properties.put("Bean.#moduleA#bean101.LocalTransaction.UnresolvedAction", "Commit");
In this information ...Subtopics
Related reference
| IBM Redbooks, demos, education, and more(Index) Use IBM Suggests to retrieve related content from ibm.com and beyond, identified for your convenience. This feature requires Internet access. Most of the following links will take you to information that is not part of the formal product documentation and is provided "as is." Some of these links go to non-IBM Web sites and are provided for your convenience only and do not in any manner serve as an endorsement by IBM of those Web sites, the material thereon, or the owner thereof. |