Using the EJBContainer API with or without Maven (but with GlassFish v3)
By alexismp on oct. 05, 2009
This blog has moved to alexismp.wordpress.com
Follow the link for the most up-to-date version of this blog entry.
This blog is still pretty accurate but do note that GlassFish v3 and NetBeans 6.8 have been released in final version
The typical way to start GlassFish is to use
$asadmin start-domain but you could also start it using
java -jar modules/glassfish.jar. Both start a standalone instance of GlassFish. The following paragraphs discuss GlassFish Embedded (i.e. start it using an API).
There are at least two ways to start GlassFish in embedded mode: using
org.glassfish.api.embedded.Server and associated classes but also using the (now standard in EJB 3.1)
EJBContainer.createEJBContainer() API. Let me describe here the latter one and reserve the more general embedded case for a later blog entry.
The goal is to write something like as simple as this to test your EJB :
EJBContainer c = EJBContainer.createEJBContainer(); // new in EJB 3.1!
Context ic = c.getContext();
SimpleEjb ejb = (SimpleEjb) ic.lookup("java:global/sample/SimpleEjb");
EJB's found in the classpath of the running code above will automatically be deployed and made available via lookups.
EJBContainer.createEJBContainer() are likely to be made from your tests. If you're making those calls by constructing yourself the execution classpath, then you simply need to add
glassfish/lib/embedded/glassfish-embedded-static-shell.jar, an empty jar with a
Class-Path: listing the required jars and that is part of the GlassFish distro. In fact, if you're using recent builds of NetBeans 6.8 (and the soon-to-be-released beta), the IDE does this for you when GlassFish is the target server. If you are using Maven, it's a bit trickier.
EJBContainer.createEJBContainer() from Maven tests, you'll need to add the following dependency to your POM (updated to final version of GlassFish v3):
You could restrict this to a smaller set of GlassFish artifacts but for non-trivial tests (if you use JPA for instance), you would start to have a fairly long list of dependencies so the above sounds like a reasonable thing to do. This will require Maven to download the GlassFish All-in-one JAR file (40MB or so). The reason I wrote it would be trickier with maven is that you need to pass a property during the
createEJBContainer() call indicating the location of a GlassFish v3 install. The above Java code would need to read something like this:
"/path/to/glassfish"); // include trailing "/glassfish"
ec = EJBContainer.createEJBContainer(p);
As of build 69 (maybe 70?), this is no longer needed - i.e. you can simply have
glassfish-embedded-all.jar as a dependency or simply in your classpath. A full install of GlassFish is no longer required (although it may be interesting if you want to use JDBC configurations). Read this blog by Thomas for another interesting approach: Nice follow-up blog here: http://ctpjava.blogspot.com/2009/10/unit-testing-ejbs-and-jpa-with.html
Starting the appserver this way (with or without Maven) exercises the actual GlassFish code, not another implementation or a customized fork. There are some limitations to what you can run and in particular port configuration is ignored (not listening on any) and only local EJB interfaces are available (the spec only requires EJB 3.1 lite support). On the other hand, JPA calls are very much possible.
This should all work with v3 promoted build 66 (I just tested this with promoted build 70, see above simplification). Adam Bien beat me to covering that topic, but I hope you get some additional info here. In my case the start-up, setup, deploy and shutdown of GlassFish Embedded are worth about 6 seconds. Note that there is no OSGi involved here.
Update: some people are facing classpath/maven issues that causes the test to fail to find any EJB to test. The above is meant to run with an existing install of GlassFish (sorry this wan't clear) and this great thread has more data on what the issues can be. Marina describes the expected behavior and Laird goes into details about the use of
maven-surefire-plugin and its
<forkMode> configuration parameter. Make sure you read this if you have similar issues.
Update 2: per the EJB 3.1 specification
EJBContainer is only required to support "EJB light" (no remote interfaces for instance).