Arquillian Persistence and Embedded container (OpenEJB/DBUnit/HSQLDB case)


Arquillian has a lot of extensions which can dramtically cut needed code. An interesting one is the persistence one which simplifies a lot the DBUnit usage.

The sad part is this extension is designed for not embedded containers….but with this tip you’ll be able to use it (so with OpenEJB, OpenWebBeans, Weld…).

The test

We suppose we have a standard JPA application (using JTA mode since we’ll use OpenEJB adapter).

Here is the entity:

@Entity
@NamedQuery(name = "findAll", query = "select p from Person p")
public class Person {
    @Id
    private long id;

    private String name;

    public void setId(final long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

We’ll use an EJB to get an EntityManager:

@Singleton
@Lock(LockType.READ)
public class PersonBean {
    @PersistenceContext
    private EntityManager em;

    public Collection<Person> people() {
        return em.createNamedQuery("findAll", Person.class).getResultList();
    }

    public Person findById(final long id) {
        return em.find(Person.class, id);
    }

    public long newPerson(final long id, final String dummy) {
        final Person p = new Person();
        p.setName(dummy);
        p.setId(id);
        em.persist(p);
        em.flush();
        return p.getId();
    }
}

And here is the 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="test" transaction-type="JTA">
    <jta-data-source>testDatabase</jta-data-source>
    <class>org.superbiz.Person</class>
    <properties>
      <property name="openejb.jpa.init-entitymanager" value="true" />
      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" />
    </properties>
  </persistence-unit>
</persistence>

We see we need a testDatabase datasource, we’ll just define it in arquillian.xml:

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/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">
  <container default="true" qualifier="openejb-embedded-4">
    <configuration>
      <property name="properties">
        testDatabase = new://Resource?type=DataSource
      </property>
    </configuration>
  </container>
</arquillian>

Now we just need a test:

@RunWith(Arquillian.class)
public class PersonTest {
    @Deployment
    public static Archive<?> createDeploymentPackage() {
        return ShrinkWrap.create(WebArchive.class, "test.war")
            .addPackage(Person.class.getPackage())
            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
            .addAsWebInfResource("META-INF/persistence.xml", "persistence.xml");
    }

    @Inject
    private PersonBean bean;

    @Test
    @Transactional(TransactionMode.COMMIT)
    @UsingDataSet("datasets/person.yml")
    @ShouldMatchDataSet("datasets/expected-person.yml")
    public void personBeanTest() throws Exception {
        final Person p = bean.findById(1);
        assertNotNull(p);
        p.setName("foo");
        bean.newPerson(2, "dummy");
    }
}

This test is pretty trivial and mainly done for this post: it populates the database with a person from a YAML DBUnit file, we update this entity, then we persist another person and check we have both people in the database.

Here is the init YAML file:

PERSON:
  - id: 1
    name: bar

And here is the result/expected YAML file:

PERSON:
  - id: 1
    name: foo
  - id: 2
    name: dummy

Normally that’s all. But in embedded case you need some more configuration to get it working.

The tip

Normally you configure completely the persistence extension in the arquillian.xml file. In our case we’ll simulate what does arquillian persistence extension to work and it will replace the arquillian.xml file (but you’ll quickly see you have almost all parameters you could set in arquillian.xml but somewhere else).

First we need to activate server side persistence extension. To do so just create a file META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension containing:

org.jboss.arquillian.persistence.core.container.RemotePersistenceExtension

Then we need to initialize the configuration for all parts of the extension (even if we use all defaults we need to create files since that’s what does arquillian persistence extension and it expects it to be done).

First create a arquillian.extension.persistence.properties file containing the persistence configuration. For instance:

defaultDataSeedStrategy = CLEAN_INSERT
defaultDataSource = openejb:Resource/testDatabase
dumpData = true

Then do the same for script part of the persistence extension using the file arquillian.extension.persistence.script.properties:

# can contain all script properties
sqlStatementDelimiter = NEW_LINE

Then for dbunit in arquillian.extension.persistence.dbunit.properties:

# can contain all dbunit properties
caseSensitiveTableNames = true
datatypeWarning = true
defaultDataSetFormat = YAML
datatypeFactory = org.dbunit.ext.hsqldb.HsqldbDataTypeFactory

And finally for JPA cache part of the extension in arquillian.extension.persistence.jpacacheeviction.properties (i used an empty one since i don’t use this part in the test).

Here we are, we simulate the server execution of the extension forcing it to be executed and we manually initialized the configuration used by the server side of the persistence extension. This way arquillian persistence extension will find all the data it needs to be executed.

Advertisements

2 thoughts on “Arquillian Persistence and Embedded container (OpenEJB/DBUnit/HSQLDB case)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s