Java EE 6 Testing Part I – EJB 3.1 Embeddable API

December 6th, 2011 by Samuel Santos Leave a reply »

One of the most common requests we hear from Enterprise JavaBeans developers is for improved unit/integration testing support.
EJB 3.1 Specification introduced the EJB 3.1 Embeddable API for executing EJB components within a Java SE environment.

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.
[…]
The embeddable EJB container provides a managed environment with support for the same basic services that exist within a Java EE runtime: injection, access to a component environment, container-managed transactions, etc. In general, enterprise bean components are unaware of the kind of managed environment in which they are running. This allows maximum reusability of enterprise components across a wide range of testing and deployment scenarios without significant rework.

Let’s look at an example.

Start by creating a Maven project and add the embeddable GlassFish dependency.
I chose to use TestNG testing framework, but JUnit should work just as well.

<dependencies>
    <dependency>
        <groupId>org.glassfish.main.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>3.1.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.4</version>
        <scope>test</scope>
    </dependency>
    <!--
        The javaee-api is stripped of any code and is just used to
        compile your application. The scope provided in Maven means
        that it is used for compiling, but is also available when
        testing. For this reason, the javaee-api needs to be below
        the embedded Glassfish dependency. The javaee-api can actually
        be omitted when the embedded Glassfish dependency is included,
        but to keep your project Java-EE 6 rather than GlassFish,
        specification is important.
    -->
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

Here’s a simple Stateless session bean:

@Stateless
public class HelloWorld {
    public String hello(String message) {
        return "Hello " + message;
    }
}

It exposes business methods through a no-interface view.
There is no special API it must use to be capable of embeddable execution.

Here is some test code to execute the bean in an embeddable container:

public class HelloWorldTest {
    private static EJBContainer ejbContainer;

    private static Context ctx;

    @BeforeClass
    public static void setUpClass() throws Exception {
        // Instantiate an embeddable EJB container and search the
        // JVM class path for eligible EJB modules or directories
        ejbContainer = EJBContainer.createEJBContainer();

        // Get a naming context for session bean lookups
        ctx = ejbContainer.getContext();
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
        // Shutdown the embeddable container
        ejbContainer.close();
    }

    @Test
    public void hello() throws NamingException {
        // Retrieve a reference to the session bean using a portable
        // global JNDI name
        HelloWorld helloWorld = (HelloWorld)
                ctx.lookup("java:global/classes/HelloWorld");

        // Do your tests
        assertNotNull(helloWorld);
        String expected = "World";
        String hello = helloWorld.hello(expected);
        assertNotNull(hello);
        assertTrue(hello.endsWith(expected));
    }
}

The source code is available on GitHub under the folder ejb31-embeddable.

For a step by step tutorial with a JPA example take a look at Using the Embedded EJB Container to Test Enterprise Applications from NetBeans docs.

While this new API is a step forward, I still have an issue with this approach: you are bringing the container to the test. This requires a specialized container which is different from your production environment.

In Java EE 6 Testing Part II, I will introduce Arquillian and ShrinkWrap.
Arquillian, a powerful container-oriented testing framework layered atop TestNG and JUnit, gives you the ability to create the production environment on the container of your choice and just execute tests in that environment (using the datasources, JMS destinations, and a whole lot of other configurations you expect to see in production environment). Instead of bringing your runtime to the test, Arquillian brings your test to the runtime.

Don't be shellfish...Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInPin on PinterestBuffer this pageEmail this to someone
Advertisement

7 comments

  1. Steve Schols says:

    Nice article about the embeddable EJB container. I forgot how simple it is nowadays to test enterprise applications using embeddable containers or Arquillian.

    One small detail. The shown filename of your HelloWorld class shouldn’t be PersonService.java, but of course HelloWorld.java. But that’s just a tiny detail.

    Can you just use @EJB or @Inject dependency injection in such an embeddable container within EJB’s, and can you also inject the EJB in your test class instead of using the JNDI name?

    • One small detail. The shown filename of your HelloWorld class shouldn’t be PersonService.java, but of course HelloWorld.java. But that’s just a tiny detail.

      Fixed. Thanks!

      Can you just use @EJB or @Inject dependency injection in such an embeddable container within EJB’s

      Yep.

      and can you also inject the EJB in your test class instead of using the JNDI name?

      No, you cannot. You need to enrich your test class to support @EJB or @Inject injection.
      However, you can use Arquillian which supports it.
      Take a look at the second part of this Java EE 6 Testing series.

  2. Indeed, a very good article. I would only replace @BeforeClass and @AfterClass with @BeforeSuit and @AfterSuit as a small improvement :).

  3. Peter Weston says:

    This is a good article and makes this part of testing EJBs in an embeddable container seem pretty straight forward.

    The problem I have is when I want to do something a bit more interesting like include a custom data-source.

    I see a few references as to how to create a cut-down version of a glassfish instance and installation root in the src/test/resources of a maven project.

    It is not clear at all ‘exactly’ what has to go into such a cut-down’ glassfish server.

    Does anyone have a complete example project they could share that makes this part clearer?

  4. Luciano says:

    Taken from https://community.jboss.org/wiki/WhereIsTheEmbeddedGlassFish312Jar

    This way works:

    <dependency>
        <groupId>org.glassfish.main.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>3.1.2</version>
        <scope>test</scope>
    </dependency>
    

Leave a Reply