Bistro!
Alexis Moussine-Pouchkine's Weblog
public enum Topic { Java, GlassFish, Tools, Sun, InFrenchInZeText, SDPY }

20091005 lundi octobre 05, 2009

Using the EJBContainer API with or without Maven (but with GlassFish v3)

Updated this blog on October 28th as you no longer need to have a full GlassFish install to test EJBs
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.sayHello();

EJB's found in the classpath of the running code above will automatically be deployed and made available via lookups.

Calls to 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.

To use EJBContainer.createEJBContainer() from Maven tests, you'll need to add the following dependency to your POM (updated to final version of GlassFish v3):

     <groupId>org.glassfish.extras</groupId>
     <artifactId>glassfish-embedded-all</artifactId>
     <version>3.0</version>
     <scope>test</scope>

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:

     Map p = new HashMap();
     p.put ("org.glassfish.ejb.embedded.glassfish.installation.root",
           "/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.

For a complete working example with JPA calls, check out this sample code.
The EJB 3.1 specification has a chapter (#22) on "Embeddable Usage". Check it out for further details about EJBContainer.

( oct. 05 2009, 05:40:10 PM CEST ) Permalink Comments [7]

Comments:

I've followed the instruction exactly using the glassfish3-b66, but I still get the following error in Maven test.

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ejb/embeddable/EJBContainer

at the line

EJBContainer ejbC = EJBContainer.createEJBContainer(p);

Posted by Sean on octobre 09, 2009 at 01:50 PM CEST #

Sean,
Can you start a discussion on the GlassFish forum (http://forums.java.net/jive/forum.jspa?forumID=56) or on the USERS mailing list? It'll be easier than using this comments thread (sharing your pom.xml and full test code might help).

Posted by Alexis MP on octobre 12, 2009 at 12:20 PM CEST #

Nice follow-up blog here: http://ctpjava.blogspot.com/2009/10/unit-testing-ejbs-and-jpa-with.html

Posted by Alexis MP on octobre 30, 2009 at 07:17 PM CET #

Hi,

Great article.It was of great help.I managed to run the testing for my EJB3.1 without maven . I would like to know how to configure a local database which is not my development database or inmemory database for my testing purpose.

Thanks

Posted by Alphy on novembre 12, 2009 at 07:06 AM CET #

Does Thomas' blog help out in using an existing domain.xml config (which can be configured to use any database) help at all : http://ctpjava.blogspot.com/2009/10/unit-testing-ejbs-and-jpa-with.html ?
Or maybe I'm mis-understanding the question.

Posted by Alexis MP on novembre 12, 2009 at 10:48 AM CET #

Hi. I'm having a terrible time getting this to work. Here's what I have in my JUnit test method right now:

Map p = new HashMap();
p.put ( "org.glassfish.ejb.embedded.glassfish.installation.root",
"C:\\Program Files\\sges-v3\\glassfish"); // add the (p)
EJBContainer ec = EJBContainer.createEJBContainer();

Here's what I have in my pom.xml

<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0-b70</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>embedded</groupId>
<artifactId>glassfish-embedded-static-shell</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>C:\Program Files\sges-v3\glassfish\lib\embedded\glassfish-embedded-static-shell.jar</systemPath>
</dependency>

Both depedancies are resolved properly. However, I get this error:

No EJBContainer provider available The following providers: org.glassfish.ejb.embedded.EJBContainerProviderImpl Returned null from createEJBContainer call.

*I can't copy paste from NetBeans Test Results window to give you the full stack.. grrr*

I've tried numerous incantations, with just the system jar, or the repository jar, with and without the Map parameters. All give the same results.

Posted by Robert Gass on décembre 18, 2009 at 08:40 PM CET #

@Robert, Can you try with the latest "3.0-b74b" version of 'glassfish-embedded-all' (this is v3 final).

Have you tried running your test straight with junit (no Maven) with glassfish-embedded-static-shell.jar in the classpath?

Could we move this discussion to USERS @ glassfish.dev.java.net? Easier for multiple reasons.

Posted by Alexis MP on décembre 18, 2009 at 08:46 PM CET #

Post a Comment:

Comments are closed for this entry.

GlassFish Podcast
Get GlassFish V3
Support GlassFish Enterprise

Today's Page Hits: 2812




bea conference glassfish ips java javaee javaee6 javafx javaone javazone jug metro mysql netbeans openesb openoffice opensource paris performance podcast presentation sdpy sun swing techdays tips updatecenter v3 webservices wsit
Links