Testing with the GlassFish Maven plugin and JavaDB Embedded

January 16, 2010 § 4 Comments

Having GlassFish v3 usable in embedded mode made it easy to create a maven plugin with multiple goals (see this previous entry). This in turn makes it easy to configure the plugin for maven-driven unit testing. Here’s an example :


<plugin>
    <groupId>org.glassfish</groupId>
    <artifactId>maven-embedded-glassfish-plugin</artifactId>
    <version>3.0</version>
    <configuration>
       <goalPrefix>embedded-glassfish</goalPrefix>
       <app>${basedir}/target/myapp.ear</app>
       <autoDelete>true</autoDelete>
       <port>8080</port>

    </configuration>

    <executions>
       <execution>
          <id>start-glassfish</id>
          <phase>pre-integration-test</phase>
          <goals>
             <goal>start</goal>
          </goals>
       </execution>
       <execution>
          <id>glassfish-deploy</id>
          <phase>pre-integration-test</phase>
          <goals>
             <goal>deploy</goal>
          </goals>
       </execution>
       <execution>
          <id>glassfish-undeploy</id>
          <phase>post-integration-test</phase>
          <goals>
             <goal>undeploy</goal>
          </goals>
       </execution>
       <execution>
          <id>stop-glassfish</id>
          <phase>post-integration-test</phase>
          <goals>
             <goal>stop</goal>
          </goals>
       </execution>
    </executions>
</plugin>

Now it’s certainly nice to be able to automate tests right from a single pom.xml and not have to deal with starting, deploying, stopping the app server. It’s even better when the runtime starts fast and uses only the required memory (as it is the case with GlassFish v3), but what about running tests involving a database? If a database server needs to be started using external tools (or worse, manually) it’s a bit back to square “one”.

This is where JavaDB embedded can come in handy. The trick with an application server like GlassFish is that it’s not enough to use the embedded driver (org.apache.derby.jdbc.EmbeddedDriver), you also need to reference an embedded JTA datasource. GlassFish v3 ships with one such datasource pre-configured: jdbc/__TimerPool so lazy as I am, I simply reused this in by setup – using the following JPA persistence-unit enables my test to fire up an embedded (in-process) instance of JavaDB (no separate startup, no port used). As the names implies, this pool isn’t really a general purpose one (it’s used for by the Timer Service) so this is a bit of a hack. A handy one, but a hack.


<persistence-unit name="tempdb">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/__TimerPool</jta-data-source>
    <properties>
       <property name="javax.persistence.jdbc.driver"
            value="org.apache.derby.jdbc.EmbeddedDriver"/>
       <property name="eclipselink.target-database" value="DERBY"/>
       <property name="eclipselink.ddl-generation"
            value="drop-and-create-tables"/>
    </properties>
</persistence-unit>

You see here that I use the drop-and-create-tables ddl generation strategy (create-tables would work too) and consider the database to be volatile. The next step would be to run all of this in-memory and no longer write files to disk (which shouldn’t be that hard).

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

October 5, 2009 § 8 Comments

2010 update: 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 :


// new in EJB 3.1!
    EJBContainer c = EJBContainer.createEJBContainer();
    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.

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).

Where Am I?

You are currently browsing entries tagged with maven at Bistro! 2.0.

Follow

Get every new post delivered to your Inbox.