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.
Before you begin
To create an embeddable EJB container application, you must
set your development environment to use Version 6.0 of Java Development Kit (JDK) Version 1.6. Your
development environment must also include the WebSphere
® embeddable container Java archive (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 WebSphere Application
Server.
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: ![[Updated in January 2013]](../../delta.gif)
The com.ibm.ws.ejb.embeddableContainer_8.0.0.jar
file is limited to providing messages in English. If you 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 WebSphere Application Server.
![[Updated in January 2013]](../../deltaend.gif)
jan2013
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.
- 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. You can
package the EJB module as directories of classes or as EJB JAR files.
- 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 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.
- Customize the embeddable container. You 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.
- If you want your application to use resources like data
sources, then you 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 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.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. 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.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.
- Your application can use Java EE
role-based security, both declarative and programmatic, to verify
your EJB role-based security. You
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 your EJB.
- Test the use of the EJBContext methods, isCallerInRole() and getCallerPrincipal(),
in your EJB.
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.
- 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 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.
If an application
name is not specified when launching the embeddable container, the
<application_name> must
be omitted. However, you must use the # delimiter. For example:
properties.put("Bean.#moduleA#bean101.LocalTransaction.UnresolvedAction", "Commit");