In this blog, we’ll explore how to employ the Embeddable EJB Container inside a Java SE application using WebSphere Application Server 8.x.
Embeddable EJB Container
One of the new features introduced in EJB 3.1 (part of Java EE 6) is the Embeddable EJB Container. The main two use cases for the Embeddable EJB Container are:
- Unit testing your EJBs without requiring a Java EE application server
- Embedding EJBs inside a Java SE application, which allows you to take advantage of their benefits (e.g., security and transactions)
The primary advantages of using the Embeddable EJB Container are:
- You don’t need to install the application server if all you need to do is unit test or employ your EJBs within a Java SE-based application. You just need access to the vendor’s Embeddable EJB Container JAR file.
- The Embeddable EJB Container starts almost instantaneously, unlike the server-based EJB container (which can take a minute or more to start up), since the Embeddable EJB Container initializes only EJB-related components.
- The Embeddable EJB Container has a much smaller memory footprint than the equivalent server-based EJB container.
Embeddable EJB Container Functionality
The Embeddable EJB Container is not required to support the full EJB 3.1 specification, but only EJB Lite, which is a subset of the specification. This includes support for:
- Stateless, stateful and singleton session beans
- Local and no-interface views only
- Synchronous method invocations only
- Transactions (both container-managed and bean-managed)
- Security (both declarative and programmatic)
- Support for annotations and XML deployment descriptor (ejb-jar.xml)
- Java Persistence API (JPA) 2.0
WebSphere’s Embeddable EJB Container supports all the above functionality and also provides extensions for:
- JDBC Datasources, including dependency injection using the @Resource annotation
- Bean validation (also new to Java EE 6)
Note that Contexts and Dependency Injection (CDI), which is also new to Java EE 6, is not required to be supported by an Embeddable EJB Container, nor does WebSphere’s implementation support it.
Instantiating the Embeddable EJB Container
The client application is responsible for loading the Embeddable EJB Container inside its JVM using the bootstrapping API provided by the EJB 3.1 specification. Specifically, the client creates an Embeddable EJB Container instance by calling the createEJBContainer static factory method on the javax.ejb.embeddable.EJBContainer class:
EJBContainer ejc = EJBContainer.createEJBContainer();
There is also an overloaded version of the createEJBContainer method that accepts a java.util.Properties object that contains standard properties and vendor-specific properties (more on this later).
During the bootstrapping step, the container performs the standard container initialization steps, like resource injection, initialization of singleton EJBs, etc. When the createEJBContainer method returns successfully, the container is ready to accept a client’s requests.
For looking up an EJB, your client first needs to gain access to the javax.naming.Context object, using the container’s getContext method. Then it looks up the EJB using the new portable “java:global/” JNDI naming syntax introduced in EJB 3.1. For example:
Context ctx = ejc.getContext(); GreetingLocal greetingBean = (GreetingLocal) ctx.lookup("java:global/SimpleEJBProject/Greeting"); String message = greetingBean.sayHello("Matt"); System.out.println("EJB said: " + message);
In the example above, the client application looks up a stateless session EJB called Greeting, invokes its sayHello method, and prints out the result.
|Note: Prior to EJB 3.1, JNDI names were vendor specific. Now, using the portable JNDI naming syntax, you can employ JNDI names that can be used across application server vendors.|
When you’re finished with the EJBContainer, it’s standard practice to shut it down using the close method:
Running the Embeddable EJB Container
Running the Java SE application that employs the Embeddable EJB Container requires that the class path be configured appropriately. It also requires usage of a vendor specific JAR file that contains the Embedded EJB Container. For example:
java -cp .;SimpleEJBProject.jar;SimpleEJBProjectClient.jar;com.ibm.ws.ejb.embeddableContainer_8.0.0.jar;EmbeddableContainerTest.jar com.mycom.test.EmbeddableContainerTest
In the example above, the classpath contains the EJB JAR file (SimpleEJBProject.jar), the EJB client JAR file (which contains the local interface) (SimpleEJBProjectClient.jar), the vendor specific JAR file that contains the Embedded EJB Container (com.ibm.ws.ejb.embeddableContainer_8.0.0.jar), and the client JAR file (EmbeddableContainerTest.jar). The name of the class that’s being tested is called com.mycom.test.EmbeddableContainerTest.
|Note: The com.ibm.ws.ejb.embeddableContainer_8.0.0.jar is located in the <WAS_HOME>/runtimes directory.|
Using JPA 2.0
If you want to employ JPA 2.0 from within an EJB-based application, which is typical if you want to access a database, you’ll need to perform a few extra steps.
1. Provide a java.util.Properties object that’s used when creating the EJB container. This is used to configure a JDBC datasource. For example:
Properties props = new Properties(); props.put("DataSource.ds1.name", "env/jdbc/ds1"); props.put("DataSource.ds1.className", "org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource"); props.put("DataSource.ds1.createDatabase", "create"); props.put("DataSource.ds1.databaseName", "bankdb"); props.put("DataSource.ds1.user", "wasadmin"); props.put("DataSource.ds1.password", "wasadmin"); EJBContainer ejc = EJBContainer.createEJBContainer(props);
2. Modify the persistence.xml file to use the new datasource. For example:
<persistence-unit name="BankAccountJPA" transaction-type="JTA"> <jta-data-source>env/jdbc/ds1</jta-data-source> … </persistence-unit>
|Note: Ordinarily you’d use the WAS administrative console to configure a datasource, or create an application-scoped datasource using the WebSphere Application Server Deployment descriptor editor (inside of RAD), but that’s not possible for the Embeddable EJB Container.|
3. Add the com.ibm.ws.jpa.thinclient_8.0.0.jar (contained inside the <WAS_HOME>/runtimes directory), derby.jar (contained inside the <WAS_HOME>/derby/lib directory), and JPA JAR files to the classpath.
|Note: Derby, which comes packaged with WebSphere, is the database being used here.|
4. Enhance the JPA.jar file, which I did dynamically using a Java Agent. Specifically, I added the following argument to my java command:
I used the following command to run my application. The items in bold are the additions. Note that I’m also using a different EJB JAR file and EJB Client JAR file than the previous example:
java -cp .;SimpleEJBProject.jar;SimpleEJBProjectClient.jar;BankAccountJPA.jar;com.ibm.ws.ejb.embeddableContainer_8.0.0.jar;com.ibm.ws.jpa.thinclient_8.0.0.jar;derby.jar;EmbeddableContainerTest.jar -javaagent:com.ibm.ws.jpa.thinclient_8.0.0.jar com.mycom.test.EmbeddableContainerTest
What About the Liberty Profile?
WebSphere Application Server 8.5 introduced the Liberty Profile which complies with the new Java EE 6 Web Profile. The Web Profile does not support all of the features of the Java EE specification (also referred to as the Full Profile), but the more commonly used ones. One of the nice things about the Liberty Profile is that it starts up extremely quickly (within 5 seconds). It’s also very configurable. Like the Embeddable EJB Container, it supports EJB Lite and JPA. However, unlike the Embeddable EJB Container, it also provides support for Message-Driven Beans (MDBs), CDI, JSPs, Servlets, JSF, JAX-WS, and JAX-RS.
You may be tempted to just use the Liberty Profile for unit testing and development. However, if haven’t upgraded to v8.5 yet and you’re still on v8.0, or you’re simply trying to test our your EJB layer (not your Web layer), or if you want to use EJBs inside a Java SE application, or if you want slightly faster startup times, you’re still better off using the Embeddable EJB Container provided by WebSphere.
In summary, the Embeddable EJB Container makes testing and using your EJBs within a Java SE application faster and easier. It eliminates having to do a full-blown server installation. It also provides quick startup times and a low memory footprint.
For more information on WebSphere’s Embeddable EJB Container, please refer to:
For more information on EJB 3.1 and JPA 2.0 development, check out our course (i.e., WA2093 EJB and JPA Programming with Java EE 6 – WebSphere 8.0 / RAD 8.0) :