Enterprise Java

Arquillian with NetBeans, GlassFish embedded, JPA and a MySQL Datasource

This is an, let’s call it accidental post. I was looking into transactional CDI observers and playing around with GlassFish embedded to run some integration tests against it. But surprisingly this did not work too well and I am still figuring out, where exactly the problems are while using the plain embedded GlassFish for that.

In the meantime I switched to Arquillian. After I looked at the Arquillian 1.0.0.Alpha4 a bit more detailed last year, it was time to see, what the guys prepared for 1.0.0 final. Some stuff changed a bit and I was surprised to only find some basic examples on the net. That was the main reason I started writing this post. To have a more complete example of all the three technologies working together.

Getting Started
First of all, get yourself a fresh copy of latest NetBeans 7.1. It’s out since a few weeks and it really looks good. If you like, you can download a copy of the Java EE version, which comes with latest GlassFish OSS Edition 3.1.1 pre bundled. Install it and fire it up. Also grep a copy of MySQL Community Edition and install it. Back in NetBeans, setup a new Maven Webapplication via the new Project Wizard. Let’s call it “simpleweb” and we tell it to run on GF 3.1.1 (if you haven’t done so, you should create a Services>Server>GlassFish instance before or do it during the project setup).

Implement your Application
Even if this isn’t test-driven, I like to use this approach because I still believe, that this is the most common case you find out there in your projects. You have a lot of stuff ready to run and you are looking for some kind of automated integration tests. So, let’s assume you have a very basic entity, we call it “com.mycompany.simpleweb.entities.AuditLog”. You can create it with the NetBeans new Entity wizard. The third step during the Entity creation is the provider and database setup. Define a new Datasource and name it “jdbc/auditlog”. As a connection specification use MySQL J driver and I assume you have a database up and running (let’s assume this is called auditlog). Test the connection and finish the wizard.

If you are using the wizard, you get some free gifts. Beside the fact, that you now have your AuditLog entity in the source tree, you also find a META-INF/persistence.xml file in your src/main/resources and a glassfish-resources.xml in src/main/setup. This is needed later on, keep it in mind. Add some additional properties to your entity. For now I add “String account”. And don’t forget to define a Version field “Timestamp timestamp”. And it’s also nice to have a little named query to get a list of all AuditLogs

@NamedQuery(name = "findAllAuditLogs",
query = "SELECT OBJECT (e) FROM AuditLog e")
 
@Version
private Timestamp timestamp;

If you are using the wizard, make sure to check your pom.xml. The wizard is adding some eclipselink dependencies in scope provided, so this shouldn’t make a big difference here. Next is to add a com.mycompany.simpleweb.service.AuditRepositoryService EJB. This should be responsible for all CRUD operations on the AuditLog entity.
Add some code to it to insert an AuditLog:

@PersistenceContext
private EntityManager em;
 
  public void writeLog(String account) {
        AuditLog log = new AuditLog();
        log.setAccount(account);
        em.persist(log);
    }

And some more code to find out the total number of entries in your table:

public int findAll() {
        TypedQuery<AuditLog> query = em.createNamedQuery("AuditLog.findAllAuditLogs", AuditLog.class);
        return query.getResultList().size();
 
    }

That’s all for now.

Adding Basic Test Dependencies
Next we are going to add some very basic test dependencies. Open your projects pom.xml file and add the following sections for Arquillian to your project:

<repository>
        <id>JBoss</id>
        <name>JBoss Repository</name>
        <url>https://repository.jboss.org/nexus/content/groups/public/</url>
    </repository>
<dependencymanagement>     
      
    <dependencies>
        <dependency>
            <groupid>org.jboss.arquillian</groupid>
            <artifactid>arquillian-bom</artifactid>
            <version>1.0.0.Final-SNAPSHOT</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencymanagement>
<dependencies>
     
    <dependency>
        <groupid>org.jboss.arquillian.container</groupid>
        <artifactid>arquillian-glassfish-embedded-3.1</artifactid>
        <version>1.0.0.Final-SNAPSHOT</version>
        <scope>test</scope>
    </dependency>
    <dependency>
     
        <groupid>org.jboss.arquillian.junit</groupid>
        <artifactid>arquillian-junit-container</artifactid>
        <scope>test</scope>
    </dependency>
</dependencies>

Beside that, you also need the embedded Glassfish dependency.

<dependency>
    <groupid>org.glassfish.extras</groupid>
    <artifactid>glassfish-embedded-all</artifactid>
    <version>3.1</version>
    <scope>test</scope>
</dependency>

We also need the MySQL J driver:

<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <version>5.1.18</version>
    <scope>test</scope>
</dependency>

Configuring Arquillian
After we have all the needed dependencies in place, we need to further configure Arquillian. This is done via the arquillian.xml which has to be placed in the src/test/resources folder (you might need to create it outside NetBeans before) and should look like this:

<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd">
    <engine>
        <property name="deploymentExportPath">target/arquillian</property>
    </engine>
 
    <container default="true" qualifier="glassfish">
        <configuration>
            <property name="sunResourcesXml">src/main/setup/glassfish-resources.xml</property> 
        </configuration>
    </container>
</arquillian>

The engine parameter tells Arquillian to place a packaged version of your test archive to a target/arquillian folder. This is quite useful for hunting down problems. The container qualifier points the testrunner to the glassfish-resources.xml which was created by the entity creation wizard. All done. One single thing I would like to suggest is to make a copy of your persistence.xml and place it to the test/resources folder renamed to something like test-persistence.xml. I consider it a best practice to have an option to configure your test JPA a bit different than the productive one. To make a simple example, we would like to see some more logging output during the tests, so the copied version should additionally contain the needed parameters. I also like to change the table generation strategy for testing to drop-and-create-tables:

<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.logging.level.sql" value="FINEST" />
<property name="eclipselink.logging.parameters" value="true" />

Let’s take a look at the the tests.

Add a Testcase
Lets add a test. This is easy with NetBeans: Right click on your EJB and select “Tools>Create JUnit Tests”. Select JUnit 4.x and accept the name proposal “com.mycompany.simpleweb.service.AuditRepositoryServiceTest”. Now your project has a new “Test Packages” folder. As you can see, the test is in error. NetBeans assumes, that you want to do a test based on embedded EJBContainer. Nice guess, but we would like to add some Arquillian here. Remove the EJBContainer import and strip the class down to this:

@RunWith(Arquillian.class)
public class AuditRepositoryServiceTest {
}

Now it’s time to define the deployment archive for the test using ShrinkWrap. The deployment archive for the test is defined using a static method annotated with Arquillian’s @Deployment annotation.

@Deployment
    public static JavaArchive createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class, "test.jar").addPackage(AuditLog.class.getPackage()).addPackage(AuditRepositoryService.class.getPackage()).addAsManifestResource(
                new ByteArrayAsset("<beans>".getBytes()),
                ArchivePaths.create("beans.xml")).addAsManifestResource(
                "test-persistence.xml",
                ArchivePaths.create("persistence.xml"));
    }

After the packages which should be contained are added, an empty beans.xml (which should be enough for now) is added and the test-persistence.xml is added as a manifest resource named persistence.xml. Great. One last thing is to define the test itself.

@EJB
AuditRepositoryService repository;
 
 @Test
    public void insertLog() throws Exception {
        repository.writeLog("Markus");
        int numberOfLogs = repository.findAll();
        Assert.assertEquals(1, numberOfLogs);
 
    }

We are inserting a simple test entity and are getting the count back from the database which is checked via assertEquals. That’s all. Fire up your tests. (Right click on the AuditRepositoryServiceTest class and select “Test File (Strg+F6).

Examining what’s happening
The output window shows the Std.out of a starting GlassFish. If you examine the output further you see, that the JDBC connection pool and the JDBC resource are created:
INFO: command add-resources result: PlainTextActionReporterSUCCESSDescription: add-resources AdminCommandnull
JDBC connection pool mysql_auditlog_rootPool created successfully.
JDBC resource jdbc/auditlog created successfully.
and the “test” application was deployed:
INFO: WEB0671: Loading application [test] at [/test]
17.01.2012 10:12:39 org.glassfish.deployment.admin.DeployCommand execute
INFO: test was successfully deployed in 6.461 milliseconds.

Scanning through the output does point you to some EclipseLink stuff, but the additional sql logging doesn’t seem to be in effect. This is because EclipseLink needs to know to which logger to point the output to. Normally the log output is redirected to the server logger which is auto-discovered. We didn’t do any logging configuration until now and simply rely on what is default for Java Logging. So, let’s add a little logging configuration. Put an empty logging.properties file to src/test/resources and add some simple lines to it:

handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level=FINEST
add the maven sure-fire plugin to the build section of your pom.xml:

<plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-surefire-plugin</artifactid>
                <version>2.11</version>
                <configuration>
                    <includes>
                        <include>com/mycompany/simpleweb/service/*</include>
                    </includes>
                    <systempropertyvariables>
                        <java.util.logging.config.file>${basedir}/src/test/resources/logging.properties</java.util.logging.config.file>
                    </systempropertyvariables>
                </configuration>
            </plugin>

If you now issue a clean and build, you see, that the desired log output is shown in the NetBeans build output.
FEIN: INSERT INTO AUDITLOG (ID, ACCOUNT, TIMESTAMP) VALUES (?, ?, ?)
bind => [1, Markus, 2012-01-17 11:02:54.0]
In fact, if you use Strg+F6 you still only see INFO level messages. To fix this, you need to change your NetBeans run action settings. Right click your project and select “Properties”. Select “Actions” and “Test file”. Add the following as a new line within “Set Properties” area:

java.util.logging.config.file=src/test/resources/logging.properties

Now you also see the desired log-level output with a single test-run. That was it. You can download the complete sample maven project (as ZIP-File) with the mentioned classes and play around a bit. Have fun!

Even if the above post was intended to be a more complex demo it turns out, that I missed a big issue with the setup. Everything works fine up to the point when you start introducing enhanced features to your entities. To name but a few: lazy loading, change tracking, fetch groups and so on. JPA providers like to call this “enhancing” and it is most often referred to as “weaving”. Weaving is a technique of manipulating the byte-code of compiled Java classes. The EclipseLink JPA persistence provider uses weaving to enhance JPA entities for the mentioned things and to do internal optimizations. Weaving can be performed either dynamically at runtime, when Entities are loaded, or statically at compile time by post-processing the Entity .class files. Dynamic weaving is mostly recommended as it is easy to configure and does not require any changes to a project’s build process. You may have seen some finer log output from EclipseLink like the following:

[…]–Begin weaver class transformer processing class [com/mycompany/simpleweb/entities/AuditLog].
[…]–Weaved persistence (PersistenceEntity) [com/mycompany/simpleweb/entities/AuditLog].
[…]–Weaved change tracking (ChangeTracker) [com/mycompany/simpleweb/entities/AuditLog].
[…]–Weaved lazy (ValueHolder indirection) [com/mycompany/simpleweb/entities/AuditLog].
[…]–Weaved fetch groups (FetchGroupTracker) [com/mycompany/simpleweb/entities/AuditLog].
[…]–End weaver class transformer processing class [com/mycompany/simpleweb/entities/AuditLog].

The problem with Arquillian and Embedded GlassFish
Imagine you take the example from yesterday’s blog post and change the simple String account property to something like this:

@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
   private Person person;

That’s exactly one of the mentioned cases where your JPA provider would need to do some enhancements to your class files before executing. Without modifying the project it would lead to some very nasty exceptions:

Exception Description: A NullPointerException would have occurred accessing a non-existent weaved _vh_ method [_persistence_get_person_vh]. The class was not weaved properly – for EE deployments, check the module order in the application.xml deployment descriptor and verify that the module containing the persistence unit is ahead of any other module that uses it.
[…]
Internal Exception: java.lang.NoSuchMethodException: com.mycompany.simpleweb.entities.AuditLog._persistence_get_person_vh()
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[person]
Descriptor: RelationalDescriptor(com.mycompany.simpleweb.entities.AuditLog –> [DatabaseTable(AUDITLOG)])
at org.eclipse.persistence.exceptions.DescriptorException.noSuchMethodWhileInitializingAttributesInMethodAccessor(DescriptorException.java:1170)
at org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor.initializeAttributes(MethodAttributeAccessor.java:200)
[…]

indicating that something is missing. And that missing method is introduced by the weaving process. If you decompile a weaved entity you can see what the JPA provider is complaining about. This is how your enhanced entity class should look like. And this is only one of the enhanced methods a weaving process is introducing into your code.

public WeavedAttributeValueHolderInterface _persistence_get_person_vh()
  {
      _persistence_initialize_person_vh();
      if(_persistence_person_vh.isCoordinatedWithProperty() || _persistence_person_vh.isNewlyWeavedValueHolder())
      {
          Person person1 = _persistence_get_person();
          if(person1 != _persistence_person_vh.getValue())
              _persistence_set_person(person1);
      }
      return _persistence_person_vh;
  }

Dynamic vs. Static Weaving
Obviously the default dynamic weaving doesn’t work with the described setup. Why? Weaving is a spoiled child. It only works when the entity classes to be weaved do exist only in the application classloader. The combination of embedded GlassFish, Arquillian and the maven sure-fire-plugin mix this up a bit and the end of the story is, that exactly none of your entities are enhanced at all. Compare this nice discussion for a more detailed explanation. If dynamic waving doesn’t work, we have to use the fallback called static weaving. Static means: post processing the entities during the build. Having the maven project at hand, this sounds like a fairly easy job. Let’s look for something like this. The first thing you probably find is the StaticWeaveAntTask. The second thing may be Craig’s eclipselink-staticweave-maven-plugin.

Let’s start with the StaticWeaveAntTask. You would have to use maven-antrunner-plugin to get this introduced. Copy classes from left to right and do an amazing lot of wrangling to get your classpath rigth. Laird Nelson did a great job to archetype-ize an example configuration for all 3 big JPA providers (EclipseLink, OpenJPA, Hibernate) and your could give this a try. A detailed explanation about what is happening can be found on his blog. Thanks Laird for the pointers! Don’t get me wrong: This is a valid approach, but I simply don’t like it. Mainly because it introduces a massive complexity to the build and having seen far too many projects without the right skills for managing even normal maven projects, this simply isn’t a solution for me. I tried the static weaving plugin done by Craig Day.

Adding static weaving to simpleweb
So, let’s open the pom.xml from yesterdays project and introduce the new plugin:

<plugin>
    <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
    <groupId>au.com.alderaan</groupId>
    <version>1.0.1</version>
         <executions>
            <execution>
                 <goals>
                   <goal>weave</goal>
                 </goals>
                 <phase>process-classes</phase>
            </execution>
          </executions>
     </plugin>

Done. Now your classes are weaved and if you introduce some logging via the plugin configuration you can actually see, what happens to your entity classes. The plugin is available via repo1.maven.org. The only issue I came across is, that the introduced dependency towards EclipseLink 2.2.0 isn’t (or course) not available via the same repo, so you probably would need to build it for yourself with the right repositories and dependencies. You can get the source code via the plugin’s google code page.

Don’t forget to add the weaving property to your test-persistance.xml:

<property name="eclipselink.weaving" value="static" />

[UPDATE: 19.01.2012]
Craig released a new 1.0.2 version of the plugin which solves the issues with the EclipseLink dependency. You now can simply include the needed EclipseLink version as a dependency to the plugin. Also needed is the correct EclipseLink maven repository. A complete example with a configured log level looks like this:

<repository>
            <id>eclipselink</id>
            <name>Repository hosting the eclipselink artifacts</name>
            <url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo/</url>
        </repository>
 
[...]
  <plugin>
                <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
                <groupId>au.com.alderaan</groupId>
                <version>1.0.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>weave</goal>
                        </goals>
                        <phase>process-classes</phase>
                        <configuration>
                            <logLevel>ALL</logLevel>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.eclipse.persistence</groupId>
                        <artifactId>eclipselink</artifactId>
                        <version>2.3.1</version>
                    </dependency>
                </dependencies>
            </plugin>

References:  Arquillian with NetBeans, GlassFish embedded, JPA and a MySQL Datasource & Arquillian with NetBeans, GlassFish embedded, JPA and a MySQL Datasource – Part II from our JCG partner Markus Eisele at the Enterprise Software Development with Java blog.

Markus Eisele

Markus is a Developer Advocate at Red Hat and focuses on JBoss Middleware. He is working with Java EE servers from different vendors since more than 14 years and talks about his favorite topics around Java EE on conferences all over the world. He has been a principle consultant and worked with different customers on all kinds of Java EE related applications and solutions. Beside that he has always been a prolific blogger, writer and tech editor for different Java EE related books. He is an active member of the German DOAG e.V. and it's representative on the iJUG e.V. As a Java Champion and former ACE Director he is well known in the community. Follow him on Twitter @myfear.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button