This blog has been in my Drafts folder for quite some time now, needed some final tweaks, and finally pushing it out.

Chapter 22 of Enterprise JavaBeans 3.1 specification (released as part of Java EE 6) describes "Embeddable Usage" as:

Unlike traditional Java EE server-based execution, embeddable usage allows client code and its corresponding enterprise beans to run within the same JVM and class loader. This provides better support for testing, offline processing (e.g. batch), and the use of the EJB programming model in desktop applications.

Earlier blogs already described the steps in detail but I had to try this stuff myself :-) And moreover this Tip Of The Day (TOTD) shows, as always, complete detailed steps to get you going from scratch.

Lets see how such an embeddable EJB application can be easily created.
  1. Create a Maven project as:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.embedded.samples -DartifactId=ejb31
  2. Add the following fragments to "pom.xml" to ensure right set of JARs are pulled in: Maven Repository . . . org.glassfish.extras glassfish-embedded-all 3.0 compile. . . install org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.5 1.5
  3. Change the generated "src/main/java/org/glassfish/embedded/samples/" to: package org.glassfish.embedded.samples;import javax.ejb.Stateless;/** * Hello world! */@Statelesspublic class App { public static String sayHello(String name) { return "Hello " + name; }}
    This creates our trivial Enterprise JavaBean.
  4. Change the generated "src/test/java/org/glassfish/embedded/samples/" to (taking the code snippet from Adam's blog and slightly altering it):
    public void testEJB() throws NamingException { EJBContainer ejbC = EJBContainer.createEJBContainer(); Context ctx = ejbC.getContext(); App app = (App) ctx.lookup("java:global/classes/App"); assertNotNull(app); String NAME = "Duke"; String greeting = app.sayHello(NAME); assertNotNull(greeting); assertTrue(greeting.equals("Hello " + NAME)); ejbC.close(); }
    This is a simple test that looks up the bean using portable JNDI name, more explanation on JNDI name below.
  5. Run the tests by giving the following standard command in the Maven project:
    ~/samples/v3/embedded/ejb31 >mvn clean test[INFO] Scanning for projects...[INFO] ------------------------------------------------------------------------[INFO] Building ejb31[INFO] task-segment: [clean, test][INFO] ------------------------------------------------------------------------[INFO] [clean:clean {execution: default-clean}][INFO] Deleting directory /Users/arungupta/samples/v3/embedded/ejb31/target. . .------------------------------------------------------- T E S T S-------------------------------------------------------Running org.glassfish.embedded.samples.AppTestApr 9, 2010 3:48:16 PM org.glassfish.ejb.embedded.EJBContainerProviderImp l getValidFileSEVERE: ejb.embedded.location_not_existsApr 9, 2010 3:48:19 PM com.sun.enterprise.v3.server.AppServerStartup runINFO: GlassFish v3 (74.2) startup time : Embedded(1180ms) startup services(1523ms) total(2703ms)Apr 9, 2010 3:48:20 PM com.sun.enterprise.transaction.JavaEETransactionMa nagerSimplified initDelegatesINFO: Using com.sun.enterprise.transaction.jts.JavaEETransacti onManagerJTSDelegate as the delegateApr 9, 2010 3:48:21 PM org.glassfish.admin.mbeanserver.JMXStartupService$ JMXConnectorsStarterThread runINFO: JMXStartupService: JMXConnector system is disabled, skipping.Apr 9, 2010 3:48:21 PM AppServerStartup runINFO: [Thread[GlassFish Kernel Main Thread,5,main]] startedApr 9, 2010 3:48:30 PM INFO: security.secmgroffApr 9, 2010 3:48:31 PM checkCertificateDatesSEVERE: java_security.expired_certificateApr 9, 2010 3:48:31 PM onInitializationINFO: Security startup service calledApr 9, 2010 3:48:31 PM loadPolicyINFO: policy.loadingApr 9, 2010 3:48:32 PM doInstantiateINFO: Realm admin-realm of classtype alm successfully created.Apr 9, 2010 3:48:32 PM doInstantiateINFO: Realm file of classtype alm successfully created.Apr 9, 2010 3:48:32 PM doInstantiateINFO: Realm certificate of classtype .CertificateRealm successfully created.Apr 9, 2010 3:48:32 PM onInitializationINFO: Security service(s) started successfully....Apr 9, 2010 3:48:33 PM com.sun.ejb.containers.BaseContainer initializeHomeINFO: Portable JNDI names for EJB App : [java:global/classes/App!org.glassfish.embedded.samples.App, java:global/classes/App]Apr 9, 2010 3:48:34 PM org.glassfish.admin.mbeanserver.JMXStartupService shutdownINFO: JMXStartupService and JMXConnectors have been shut down.Apr 9, 2010 3:48:34 PM com.sun.enterprise.v3.server.AppServerStartup stopINFO: Shutdown procedure finishedApr 9, 2010 3:48:34 PM AppServerStartup runINFO: [Thread[GlassFish Kernel Main Thread,5,main]] exitingTests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 18.61 secResults :Tests run: 2, Failures: 0, Errors: 0, Skipped: 0The key log messages are highlighted in bold and are described:
    1. *"mvn clean test" builds the project and runs the test.
    2. The server started in under 3 seconds, 2703 ms to be precise.
    3. The portable JNDI name for the EJB is "java:global/classes/App" (convenience name for a bean with one view) and the fully-qualified notation is "java:global/classes/App!org.glassfish.embedded.samples.App". The convenience name is constructed in the "global" namespace + the unqualified name of the directory + bean name. The later is created by adding the fully-qualified name of the interface to the former.
    4. The server shuts down after the tests are run, shows that 2 tests (one default + one newly added) ran, and both passed.
So no explicit GlassFish downloading and/or configuring, just deployed a simple EJB, and ran the tests - everything within one VM.

A future blog will show how to add other Java EE functionality to this app.

Technorati: totd embedded ejb glassfish javaee v3

Read More about [TOTD #128: EJBContainer.createEJBContainer: Embedded EJB using GlassFish v3...