Question

I am currently fighing quite a few issues with the creation of a database unit test environment using Arquillian. My project already works in a Glassfish 3.1.2 environment based on Seam 3, JSF and MySQL. However, when trying to set up a test environment using Arquillian, things get nasty.

My ultimate goal is an Arquillian-based unit test using a Glassfish embedded server and an embedded, in-memory h2database. I’m not picky when it comes to the embedded container, it’s just that the Arquillian JPA guide suggested that the minimal Weld container does not support JPA. That’s why I opted out towards Glassfish. Since I'm not getting even near the initialization of the persistence context, I'm not posting my persistence.xml file.

Here’s the POM I ended up with so far:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ch.diction</groupId>
    <artifactId>web-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Diction web portal</name>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jee.version>1.0.0.Final</jee.version>
        <seam.version>3.1.0.Final</seam.version>
        <primefaces.version>3.4</primefaces.version>
        <primefaces.theme.version>1.0.8</primefaces.theme.version>
        <drools.version>5.4.0.Final</drools.version>
        <arquillian.version>1.0.2.Final</arquillian.version>
        <arquillian.weld.version>1.0.0.CR3</arquillian.weld.version>
        <junit.version>4.8.1</junit.version>
        <h2.version>1.3.168</h2.version>
        <weldcore.version>1.1.10-SNAPSHOT</weldcore.version>
        <slf4j.version>1.6.6</slf4j.version>
    </properties>

    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <outputDirectory>target/main</outputDirectory>
        <testOutputDirectory>target/test</testOutputDirectory>
        <resources>
            <resource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <testResources>
            <testResource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/test/resources</directory>
            </testResource>
            <testResource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/main/resources</directory>
            </testResource>
        </testResources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>http://repository.jboss.org/nexus/content/groups/public</url>
        </repository>
        <repository>
            <id>Java.Net</id>
            <name>Java Maven Repository</name>
            <url>http://download.java.net/maven/2/</url>
        </repository>
        <repository>
            <id>prime-repo</id>
            <name>PrimeFaces Maven Repository</name>
            <url>http://repository.primefaces.org</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.seam</groupId>
                <artifactId>seam-bom</artifactId>
                <version>${seam.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>${arquillian.version}</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>${primefaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.themes</groupId>
            <artifactId>redmond</artifactId>
            <version>${primefaces.theme.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.security</groupId>
            <artifactId>seam-security</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>${drools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${drools.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.drools</groupId>
                    <artifactId>drools-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.persistence</groupId>
            <artifactId>seam-persistence</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.solder</groupId>
            <artifactId>solder-impl</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.transaction</groupId>
            <artifactId>seam-transaction</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.international</groupId>
            <artifactId>seam-international-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.international</groupId>
            <artifactId>seam-international</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.faces</groupId>
            <artifactId>seam-faces</artifactId>
        </dependency>
        <!-- Test dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
            <version>1.0.0.CR3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.main.extras</groupId>
            <artifactId>glassfish-embedded-all</artifactId>
            <version>3.1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>juli</artifactId>
            <version>6.0.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

I guess for this post, only the „Test dependencies“ are important (see comment marker), since the actual main deploy works flawlessly. Running the following unit test:

package ch.diction.webportal.test.glossary.model;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.seam.security.SecurityInterceptor;
import org.jboss.seam.transaction.TransactionInterceptor;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import ch.diction.webportal.glossary.entity.Glossary;
import ch.diction.webportal.glossary.model.IGlossaryDataAccessObject;
import ch.diction.webportal.glossary.model.JpaGlossaryDataAccessObject;
import ch.diction.webportal.security.seam.producer.EntityManagerProducer;

@RunWith(Arquillian.class)
public class JpaGlossaryDataAccessObjectTest {
    @Deployment
    public static Archive<?> createDeployment() {
        final Archive<?> ar = ShrinkWrap
                .create(WebArchive.class, "test.war")
                .addPackage(Glossary.class.getPackage())
                .addClass(SecurityInterceptor.class)
                .addClass(TransactionInterceptor.class)
                .addClass(EntityManagerProducer.class)
                .addClass(JpaGlossaryDataAccessObject.class)
                .addAsWebInfResource("ch/diction/webportal/resources/security/beans.xml", "beans.xml")
                .addAsResource("ch/diction/webportal/resources/persistence/persistence.xml", "META-INF/persistence.xml");
        return ar;
    }

    @Inject
    private IGlossaryDataAccessObject dao;
    @PersistenceContext
    private EntityManager entityManager;
    @Inject
    private UserTransaction userTransaction;

    private void clearData() throws Exception {
        userTransaction.begin();
        entityManager.joinTransaction();
        entityManager.createQuery("delete from Glossary").executeUpdate();
        userTransaction.commit();
    }

    @After
    public void commitTransaction() throws Exception {
        userTransaction.commit();
    }

    private void insertData() throws Exception {
        userTransaction.begin();
        entityManager.joinTransaction();
        // TODO: Insert records
        userTransaction.commit();
        entityManager.clear();
    }

    @Before
    public void preparePersistenceTest() throws Exception {
        clearData();
        insertData();
        startTransaction();
    }

    private void startTransaction() throws Exception {
        userTransaction.begin();
        entityManager.joinTransaction();
    }

    @Test
    public void testCreateEmptyGlossary() {
        final Glossary glossary = new Glossary("empty");
        dao.store(glossary);
    }
}

Now provides me with the following exception:

Caused by: java.lang.VerifyError: class com.sun.enterprise.web.WebModule overrides final method stop.()V
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2404)
    at java.lang.Class.getConstructor0(Class.java:2714)
    at java.lang.Class.newInstance0(Class.java:343)
    at java.lang.Class.newInstance(Class.java:325)
    at com.sun.hk2.component.ConstructorCreator.create(ConstructorCreator.java:65)
    ... 79 more

As to that, I am completely clueless. I didn’t even know these kinds of exceptions existed in java o.O ...

Thanks in advance for any suggestions here! Any help is appreciated!

Best regards Pascal

Was it helpful?

Solution

Well, I ended up ignoring the h2database part and instead used a MySQL test database provided by a fully-fledged Glassfish 3.1.2 container. The Arquillian's embedded container proved quite a hassle and wasn't worth the trouble, when Arquillian can work with actual remote Glassfish containers instead.

This is the POM I ended up with:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ch.diction</groupId>
    <artifactId>web-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Diction web portal</name>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jee.version>1.0.0.Final</jee.version>
        <seam.version>3.1.0.Final</seam.version>
        <primefaces.version>3.4</primefaces.version>
        <primefaces.theme.version>1.0.8</primefaces.theme.version>
        <drools.version>5.4.0.Final</drools.version>
        <arquillian.version>1.0.2.Final</arquillian.version>
        <arquillian.persistence.version>1.0.0.Alpha5</arquillian.persistence.version>
        <junit.version>4.8.1</junit.version>
        <slf4j.version>1.6.6</slf4j.version>
    </properties>

    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <outputDirectory>target/main</outputDirectory>
        <testOutputDirectory>target/test</testOutputDirectory>
        <resources>
            <resource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <testResources>
            <testResource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/test/resources</directory>
            </testResource>
            <testResource>
                <directory>src/test/resources/container</directory>
            </testResource>
            <testResource>
                <targetPath>ch/diction/webportal/resources</targetPath>
                <directory>src/main/resources</directory>
            </testResource>
        </testResources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>http://repository.jboss.org/nexus/content/groups/public</url>
        </repository>
        <repository>
            <id>Java.Net</id>
            <name>Java Maven Repository</name>
            <url>http://download.java.net/maven/2/</url>
        </repository>
        <repository>
            <id>prime-repo</id>
            <name>PrimeFaces Maven Repository</name>
            <url>http://repository.primefaces.org</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.seam</groupId>
                <artifactId>seam-bom</artifactId>
                <version>${seam.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>${arquillian.version}</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>${primefaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.themes</groupId>
            <artifactId>redmond</artifactId>
            <version>${primefaces.theme.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.security</groupId>
            <artifactId>seam-security</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>${drools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${drools.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.drools</groupId>
                    <artifactId>drools-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.persistence</groupId>
            <artifactId>seam-persistence</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.solder</groupId>
            <artifactId>solder-impl</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.transaction</groupId>
            <artifactId>seam-transaction</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.international</groupId>
            <artifactId>seam-international-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.international</groupId>
            <artifactId>seam-international</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.seam.faces</groupId>
            <artifactId>seam-faces</artifactId>
        </dependency>
        <!-- Test dependencies -->
        <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-6.0</artifactId>
            <version>${jee.version}</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-remote-3.1</artifactId>
            <version>1.0.0.CR3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-persistence-impl</artifactId>
            <version>${arquillian.persistence.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.shrinkwrap.resolver</groupId>
            <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

And my test-persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="web-portal-test" transaction-type="JTA">
        <jta-data-source>jdbc/web-portal-test</jta-data-source>
        <properties>
            <property name="eclipselink.logging.level" value="FINE" />
        </properties>
    </persistence-unit>
</persistence>

The lesson I get from this is that Arquillian is too bleeding edge to provoke unnecessary configuration issues. From now on, I'll always start out with a full remote container.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top