From 2207a1e695ce23e79678c232cff2ceb84ebaa801 Mon Sep 17 00:00:00 2001
From: Erik Brakkee <erik@brakkee.org>
Date: Mon, 12 Apr 2010 20:45:03 +0000
Subject: [PATCH]

---
 pom.xml                                       |   1 +
 security/pom.xml                              |   2 +-
 system/general/pom.xml                        |   2 +-
 test/eclipselink/pom.xml                      |  58 +++
 .../eclipselink/EclipselinkJpaCustomizer.java |  30 ++
 .../eclipselink/EclipselinkTables.java        |  20 +
 .../eclipselink/JndiSessionCustomizer.java    |  59 +++
 ....wamblee.support.persistence.JpaCustomizer |   1 +
 .../eclipselink/DatabaseUtilsTest.java        |  23 ++
 .../eclipselink/MyEntityExampleTest.java      |  29 ++
 test/enterprise/pom.xml                       |  72 ++++
 .../support/jndi/StubInitialContext.java      |  31 ++
 .../jndi/StubInitialContextFactory.java       |  63 +++
 .../support/persistence/AbstractDatabase.java |  78 ++++
 .../persistence/AbstractDatabaseProvider.java |  18 +
 .../persistence/CompositeJpaCustomizer.java   |  33 ++
 .../persistence/CompositeJpaTables.java       |  31 ++
 .../wamblee/support/persistence/Database.java |  63 +++
 .../support/persistence/DatabaseBuilder.java  | 116 ++++++
 .../persistence/DatabaseDescription.java      |  41 ++
 .../support/persistence/DatabaseProvider.java |  42 ++
 .../support/persistence/DatabaseStarter.java  | 106 +++++
 .../support/persistence/DatabaseUtils.java    | 389 ++++++++++++++++++
 .../support/persistence/DerbyDatabase.java    | 314 ++++++++++++++
 .../persistence/DerbyDatabaseProvider.java    |  32 ++
 .../support/persistence/ExternalDatabase.java |  82 ++++
 .../persistence/ExternalDatabaseProvider.java |  35 ++
 .../support/persistence/JpaBuilder.java       | 136 ++++++
 .../support/persistence/JpaCustomizer.java    |  22 +
 .../persistence/JpaCustomizerBuilder.java     |  20 +
 .../support/persistence/JpaTester.java        | 113 +++++
 .../PersistenceUnitDescription.java           |  28 ++
 .../support/persistence/package-info.java     |  23 ++
 ...mblee.support.persistence.DatabaseProvider |   2 +
 .../jndi/StubInitiaContextFactoryTest.java    |  41 ++
 .../persistence/DatabaseBuilderTest.java      |  16 +
 .../persistence/DatabaseUtilsTestBase.java    |  89 ++++
 .../persistence/DerbyDatabaseTest.java        |  47 +++
 .../persistence/ExternalDatabaseTest.java     |  53 +++
 .../wamblee/support/persistence/MyEntity.java |  39 ++
 .../persistence/MyEntityExampleTestBase.java  |  87 ++++
 .../persistence/MyPersistenceUnit.java        |  15 +
 .../wamblee/support/persistence/MyTables.java |  25 ++
 .../test/resources/META-INF/persistence.xml   |  40 ++
 test/hibernate/pom.xml                        |  50 +++
 .../hibernate/HibernateJpaCustomizer.java     |  31 ++
 .../hibernate/HibernateTables.java            |  20 +
 ....wamblee.support.persistence.JpaCustomizer |   1 +
 .../hibernate/DatabaseUtilsTest.java          |  23 ++
 .../hibernate/MyEntityExampleTest.java        |  29 ++
 test/pom.xml                                  |  38 ++
 test/toplink-essentials/pom.xml               |  60 +++
 .../toplink/JndiSessionCustomizer.java        |  59 +++
 .../toplink/ToplinkJpaCustomizer.java         |  30 ++
 .../persistence/toplink/ToplinkTables.java    |  20 +
 ....wamblee.support.persistence.JpaCustomizer |   1 +
 .../toplink/DatabaseUtilsTest.java            |  23 ++
 .../toplink/MyEntityExampleTest.java          |  29 ++
 58 files changed, 2979 insertions(+), 2 deletions(-)
 create mode 100644 test/eclipselink/pom.xml
 create mode 100644 test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java
 create mode 100644 test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java
 create mode 100644 test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java
 create mode 100644 test/eclipselink/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
 create mode 100644 test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java
 create mode 100644 test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java
 create mode 100644 test/enterprise/pom.xml
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java
 create mode 100755 test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java
 create mode 100755 test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java
 create mode 100644 test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java
 create mode 100644 test/enterprise/src/main/resources/META-INF/services/org.wamblee.support.persistence.DatabaseProvider
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java
 create mode 100644 test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java
 create mode 100644 test/enterprise/src/test/resources/META-INF/persistence.xml
 create mode 100644 test/hibernate/pom.xml
 create mode 100644 test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java
 create mode 100644 test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java
 create mode 100644 test/hibernate/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
 create mode 100644 test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java
 create mode 100644 test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java
 create mode 100644 test/pom.xml
 create mode 100644 test/toplink-essentials/pom.xml
 create mode 100644 test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java
 create mode 100644 test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java
 create mode 100644 test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java
 create mode 100644 test/toplink-essentials/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
 create mode 100644 test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java
 create mode 100644 test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java

diff --git a/pom.xml b/pom.xml
index 30daf852..5ddaea11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
         <module>system</module>
         <module>hibernate-jpa</module>
         <module>security</module>
+        <module>test</module>
         <module>gps</module>
     </modules>
     <dependencies>
diff --git a/security/pom.xml b/security/pom.xml
index e878f674..ed4b721f 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -29,7 +29,7 @@
     </dependency>
     <dependency>
       <groupId>org.wamblee</groupId>
-      <artifactId>wamblee-support-test-enterprise</artifactId>
+      <artifactId>wamblee-test-enterprise</artifactId>
       <version>0.2-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
diff --git a/system/general/pom.xml b/system/general/pom.xml
index 615f4c4e..f20a4abe 100644
--- a/system/general/pom.xml
+++ b/system/general/pom.xml
@@ -33,7 +33,7 @@
     </dependency>
     <dependency>
       <groupId>org.wamblee</groupId>
-      <artifactId>wamblee-support-test-enterprise</artifactId>
+      <artifactId>wamblee-test-enterprise</artifactId>
       <version>0.2-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
diff --git a/test/eclipselink/pom.xml b/test/eclipselink/pom.xml
new file mode 100644
index 00000000..6d707410
--- /dev/null
+++ b/test/eclipselink/pom.xml
@@ -0,0 +1,58 @@
+<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/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.wamblee</groupId>
+    <artifactId>wamblee-utils</artifactId>
+    <version>0.2-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.wamblee</groupId>
+  <artifactId>wamblee-test-eclipselink</artifactId>
+  <packaging>jar</packaging>
+  <name>/test/eclipselink</name>
+  <url>http://wamblee.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.dbunit</groupId>
+      <artifactId>dbunit</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.persistence</groupId>
+      <artifactId>eclipselink</artifactId>
+    </dependency>
+
+  </dependencies>
+
+   <repositories>
+        <repository>
+            <id>EclipseLink Repo</id>
+            <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
+        </repository>
+
+    </repositories>
+
+
+</project>
diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java
new file mode 100644
index 00000000..856b0519
--- /dev/null
+++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java
@@ -0,0 +1,30 @@
+package org.wamblee.support.persistence.eclipselink;
+
+import java.util.Map;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.wamblee.support.persistence.JpaCustomizer;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+
+public class EclipselinkJpaCustomizer implements JpaCustomizer {
+
+    public EclipselinkJpaCustomizer() { 
+        // Empty
+    }
+    
+    @Override
+    public void customize(PersistenceUnitDescription aPersistenceUnit, Map<String, String> aJpaProperties) {
+        // Hack to make JNDI lookup of the datasource work with toplink
+        aJpaProperties.put("eclipselink.session.customizer", JndiSessionCustomizer.class
+                .getName());
+        
+        // DDL generation for toplink
+        aJpaProperties.put("eclipselink.ddl-generation", "create-tables");   
+    }
+    
+    @Override
+    public ITableFilterSimple getJpaTables() {
+        return new EclipselinkTables();
+    }
+
+}
diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java
new file mode 100644
index 00000000..d4df0ddd
--- /dev/null
+++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java
@@ -0,0 +1,20 @@
+package org.wamblee.support.persistence.eclipselink;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+/**
+ * Toplink-specific tables. 
+ */
+public class EclipselinkTables implements ITableFilterSimple {
+
+	private static final List<String> TABLES = Arrays.asList(new String[] { "SEQUENCE" } );
+	
+	public boolean accept(String aTableName) throws DataSetException {
+		return TABLES.contains(aTableName);
+	}
+
+}
diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java
new file mode 100644
index 00000000..9b856f05
--- /dev/null
+++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java
@@ -0,0 +1,59 @@
+package org.wamblee.support.persistence.eclipselink;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.eclipse.persistence.config.SessionCustomizer;
+import org.eclipse.persistence.sessions.DatabaseLogin;
+import org.eclipse.persistence.sessions.JNDIConnector;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.sessions.server.ServerSession;
+ 
+/**
+ * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) Use for clients that would like to use a
+ * JTA SE pu instead of a RESOURCE_LOCAL SE pu.
+ * 
+ * This utility also makes sure that using a persistence.xml with a JTA datasource works in a standalone Java SE 
+ * environment together with our JNDI stub. 
+ */
+public class JndiSessionCustomizer
+    implements SessionCustomizer {
+	
+	public JndiSessionCustomizer() {
+		// Empty.
+	}
+ 
+  /**
+   * Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP
+   */
+  public void customize(Session session) throws Exception {
+    JNDIConnector connector = null;
+    Context context = null;
+    try {
+      context = new InitialContext();
+      if(null != context) {
+        connector = (JNDIConnector)session.getLogin().getConnector(); // possible CCE
+        // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP
+        // Note: if both jta and non-jta elements exist this will only change the first one - and may still result in
+        // the COMPOSITE_NAME_LOOKUP being set
+        // Make sure only jta-data-source is in persistence.xml with no non-jta-data-source property set
+        connector.setLookupType(JNDIConnector.STRING_LOOKUP);
+ 
+        // Or, if you are specifying both JTA and non-JTA in your persistence.xml then set both connectors to be safe
+        JNDIConnector writeConnector = (JNDIConnector)session.getLogin().getConnector();
+        writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP);
+        JNDIConnector readConnector =
+            (JNDIConnector)((DatabaseLogin)((ServerSession)session).getReadConnectionPool().getLogin()).getConnector();
+        readConnector.setLookupType(JNDIConnector.STRING_LOOKUP);
+ 
+        System.out.println("JndiSessionCustomizer: configured " + connector.getName());
+      }
+      else {
+        throw new Exception("JndiSessionCustomizer: Context is null");
+      }
+    }
+    catch(Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/eclipselink/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer b/test/eclipselink/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
new file mode 100644
index 00000000..35638de1
--- /dev/null
+++ b/test/eclipselink/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
@@ -0,0 +1 @@
+org.wamblee.support.persistence.eclipselink.EclipselinkJpaCustomizer
diff --git a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java
new file mode 100644
index 00000000..870e20a2
--- /dev/null
+++ b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java
@@ -0,0 +1,23 @@
+package org.wamblee.support.persistence.eclipselink;
+
+import static junit.framework.Assert.assertEquals;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.DatabaseUtilsTestBase;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+public class DatabaseUtilsTest extends DatabaseUtilsTestBase {
+   // Empty, all tests inherited
+}
diff --git a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java
new file mode 100644
index 00000000..84c3fff5
--- /dev/null
+++ b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java
@@ -0,0 +1,29 @@
+package org.wamblee.support.persistence.eclipselink;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.DatabaseTestCase;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.JpaTester;
+import org.wamblee.support.persistence.MyEntityExampleTestBase;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+import static junit.framework.Assert.*;
+
+
+/**
+ * This class shows an example of how to test an entity  using jpa. 
+ */
+public class MyEntityExampleTest extends MyEntityExampleTestBase {
+    // Empty, all tests are inherited
+}
diff --git a/test/enterprise/pom.xml b/test/enterprise/pom.xml
new file mode 100644
index 00000000..1d6f8625
--- /dev/null
+++ b/test/enterprise/pom.xml
@@ -0,0 +1,72 @@
+<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/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.wamblee</groupId>
+    <artifactId>wamblee-utils</artifactId>
+    <version>0.2-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.wamblee</groupId>
+  <artifactId>wamblee-test-enterprise</artifactId>
+  <packaging>jar</packaging>
+  <name>/test/enterprise</name>
+  <url>http://wamblee.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-support-general</artifactId>
+      <version>0.2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>javax.transaction</groupId>
+      <artifactId>transaction-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derby</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derbyclient</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derbynet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.dbunit</groupId>
+      <artifactId>dbunit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-jdk14</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java
new file mode 100644
index 00000000..a7e4c965
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java
@@ -0,0 +1,31 @@
+package org.wamblee.support.jndi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+public class StubInitialContext extends InitialContext {
+	private Map<String, Object> bindings = new HashMap<String, Object>();
+
+	public StubInitialContext() throws NamingException { 
+		super(true);
+	}
+	
+	@Override
+	public void bind(String name, Object obj) throws NamingException {
+		bindings.put(name, obj);
+	}
+
+	@Override
+	public Object lookup(String name) throws NamingException {
+		return bindings.get(name);
+	}
+	
+	@Override
+	public Object lookup(Name name) throws NamingException {
+		return super.lookup(name.toString());
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java
new file mode 100644
index 00000000..c7e4e2fd
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java
@@ -0,0 +1,63 @@
+package org.wamblee.support.jndi;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * Test initial context factory used for testing software in a Java SE
+ * environnment that uses JNDI to retrieve objects.
+ * 
+ * See {@link #bind(String, Object)} to resp. register the initial context.
+ * 
+ * To bind objects in the JNDI tree simply use the standard JNDI api: <code>
+ *   InitialContext context = new InitialContext();
+ *   MyClass myObj = ...; 
+ *   context.bind("a/b", myObj); 
+ * </code>
+ */
+public class StubInitialContextFactory implements InitialContextFactory {
+
+	private static Context context;
+
+	private static void initialize() {
+		try {
+			context = new StubInitialContext();
+		} catch (NamingException e) { // can't happen.
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * This method must be called to register this initial context factory as
+	 * the default implementation for JNDI.
+	 * 
+	 * @throws Exception
+	 */
+	public static void register() {
+		// sets up the InitialContextFactoryForTest as default factory.
+		System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+				StubInitialContextFactory.class.getName());
+		if (context == null) {
+			initialize();
+		}
+	}
+	
+	/**
+	 * Unregisters the initial context factory 
+	 */
+	public static void unregister() { 
+		System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "");
+		context = null; 
+	}
+
+	public Context getInitialContext(Hashtable<?, ?> environment)
+			throws NamingException {
+		return context;
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java
new file mode 100644
index 00000000..59f3d776
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java
@@ -0,0 +1,78 @@
+package org.wamblee.support.persistence;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+public abstract class AbstractDatabase implements Database {
+	private static final int CONNECTION_POOL_SIZE = 16;
+
+    private DataSource itsDataSource; 
+	
+	private boolean started; 
+	
+	protected AbstractDatabase() { 
+		started = false; 
+	}
+	
+	protected abstract void doStart();
+	
+	protected abstract void doStop();
+	
+	/**
+	 * This method must be called from the start method. 
+	 */
+	protected final void createDataSource() { 
+		GenericObjectPool connectionPool = new GenericObjectPool(null);
+		connectionPool.setMaxActive(CONNECTION_POOL_SIZE);
+		ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(getJdbcUrl(), getUsername(), getPassword());
+		// The following line must be kept in although it does not appear to be used, the constructor regsiters the
+		// constructed object at the connection pool. 
+		PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,connectionPool,null,null,false,true);
+		itsDataSource = new PoolingDataSource(connectionPool);
+	}
+	
+	
+	/// BELOW THIS LINE IS NOT OF INTEREST TO SUBCLASSES.
+	
+	public final DataSource start() {
+		if ( started ) { 
+			throw new RuntimeException("Database already started"); 
+		}
+		started = true; 
+		doStart();
+		return getDatasource();
+	}
+	
+	public final void stop() { 
+		if ( ! started ) { 
+			return; // nothing to do. 
+		}
+		started = false;
+		doStop(); 
+	}
+
+	private final DataSource getDatasource() {
+		if ( !started) { 
+			throw new RuntimeException("Database is not started!");
+		}
+		return itsDataSource;
+	}
+	
+	protected String getProperty(String aName) { 
+		String value = System.getProperty(aName); 
+		if ( value != null ) { 
+			return value;
+		}
+		value = System.getenv(aName); 
+		if ( value != null ) { 
+			return value; 
+		}
+		throw new RuntimeException("This class expects the '" + aName + "' property to be set");
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java
new file mode 100644
index 00000000..6ed9d6cb
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java
@@ -0,0 +1,18 @@
+package org.wamblee.support.persistence;
+
+import java.util.List;
+
+public abstract class AbstractDatabaseProvider implements DatabaseProvider {
+
+	protected abstract List<String> getCapabilities(); 
+
+	public final boolean supportsCapabilities(String[] aCapabilities) {
+		for (String capability: aCapabilities) { 
+			if ( !getCapabilities().contains(capability)) { 
+				return false;
+			}
+		}
+		return true; 
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java
new file mode 100644
index 00000000..fc6ecc7c
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java
@@ -0,0 +1,33 @@
+package org.wamblee.support.persistence;
+
+import java.util.List;
+import java.util.Map;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+public class CompositeJpaCustomizer implements JpaCustomizer {
+    
+    private List<JpaCustomizer> _customizers;
+    private CompositeJpaTables _tables; 
+    
+    public CompositeJpaCustomizer(List<JpaCustomizer> aCustomizers) { 
+        _customizers = aCustomizers;
+        _tables = new CompositeJpaTables();
+        for (JpaCustomizer customizer: _customizers) { 
+            _tables.add(customizer.getJpaTables());
+        }    
+    }
+    
+    @Override
+    public void customize(PersistenceUnitDescription aPersistenceUnit, Map<String, String> aJpaProperties) {
+        for (JpaCustomizer customizer: _customizers) { 
+            customizer.customize(aPersistenceUnit, aJpaProperties); 
+        }
+    }
+
+    @Override
+    public ITableFilterSimple getJpaTables() {
+        return _tables; 
+    }
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java
new file mode 100644
index 00000000..7a7e8de6
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java
@@ -0,0 +1,31 @@
+package org.wamblee.support.persistence;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+public class CompositeJpaTables implements ITableFilterSimple {
+    
+    private List<ITableFilterSimple> _tables; 
+    
+    public CompositeJpaTables() { 
+        _tables = new ArrayList<ITableFilterSimple>();
+    }
+    
+    public void add(ITableFilterSimple aFilter) { 
+        _tables.add(aFilter);
+    }
+
+    @Override
+    public boolean accept(String aTableName) throws DataSetException {
+        for (ITableFilterSimple filter: _tables) { 
+            if (filter.accept(aTableName)) { 
+                return true; 
+            }
+        }
+        return false; 
+    }
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java
new file mode 100755
index 00000000..f37474ea
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.support.persistence;
+
+import javax.sql.DataSource;
+
+/**
+ * Represents a database.
+ * 
+ * @author Erik Brakkee
+ */
+public interface Database {
+	
+    /**
+     * Starts a database. This call should not block and return as soon as the
+     * database has been started.
+     */
+    DataSource start();
+    
+    /**
+     * Gets the Jdbc Url to connect to this database.
+     * 
+     * @return Jdbc Url.
+     */
+    String getJdbcUrl();
+
+    /**
+     * Gets the external Jdbc URL to connect to this database from other JVMs.
+     */
+    String getExternalJdbcUrl();
+
+    /**
+     * Gets the username to connect to the database.
+     * 
+     * @return username.
+     */
+    String getUsername();
+
+    /**
+     * Gets the password to connect to the database.
+     * 
+     * @return password.
+     */
+    String getPassword();
+
+    /**
+     * Stops a database.
+     */
+    void stop();
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java
new file mode 100644
index 00000000..9c599a0a
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java
@@ -0,0 +1,116 @@
+package org.wamblee.support.persistence;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.logging.Logger;
+
+/**
+ * DatabaseBuilder is used from unit test to obtain a reference to a database
+ * from unit test. This database is either an inmemory database or represents an
+ * external database. Purpose of this utility is to make test code independent of the 
+ * particular database used and specifically to be able to run database tests without 
+ * any configuration at all (using an inmemory database).  
+ * 
+ * The type of database to use can be overridden by specifying either a system
+ * property or an environment variable ({@link #DB_CAPABILITIES_PROP}) that
+ * contains the comma-separated capabilities of the database. Each database type
+ * provides its own capabilities (see {@link DatabaseProvider} implementations}.
+ * 
+ * 
+ * There are currently two database types available: 
+ * <ul>
+ *   <li> Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This is the default. 
+ *   </li>
+ *   <li> External: An arbitrary external database configured using system properties or environment variables
+ *     in the usual way using a JDBC URL, username, and password. 
+ *   </li>
+ * </ul>
+ * 
+ * The <code>DatabaseBuilder</code> uses the {@link ServiceLoader} mechanism to find implementations
+ * of {@link DatabaseProvider} on the classpath. In the {@link #getDatabase(String...)} method a number of 
+ * capabilities are passed. The database providers are then searched in (arbitrary) order and the first one that
+ * has all required capabilities is returned. 
+ * 
+ * {@link #getSupportedDatabases()} gives a list of all available databases. 
+ */
+public class DatabaseBuilder {
+
+	private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class
+			.getName());
+
+	/**
+	 * Environmment variable by which capabilities of the requested database can
+	 * be defined
+	 */
+	private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES";
+
+	private static ServiceLoader<DatabaseProvider> LOADER = null;
+
+	private DatabaseBuilder() {
+		// Empty.
+	}
+
+	private static String[] parseCapabilities(String aValue) {
+		return aValue.split(",");
+	}
+
+	/**
+	 * Gets the first database that has all required capabilities. 
+	 * @param aCapabilities Capabilities. 
+	 * @return Database to use. 
+	 */
+	public static Database getDatabase(String... aCapabilities) {
+		if (aCapabilities.length == 0) {
+			LOGGER.info("Examining database capabilities");
+			LOGGER.info("  Checking system property " + DB_CAPABILITIES_PROP);
+			String capabilities = System.getProperty(DB_CAPABILITIES_PROP);
+			if (capabilities != null) {
+				aCapabilities = parseCapabilities(capabilities);
+			} else {
+				LOGGER.info("  Checking environment variable "
+						+ DB_CAPABILITIES_PROP);
+				capabilities = System.getenv(DB_CAPABILITIES_PROP);
+				if (capabilities != null) {
+					aCapabilities = parseCapabilities(capabilities);
+				} else {
+					LOGGER.info("  Using default capabilities");
+					aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY };
+				}
+			}
+			LOGGER.info("Using capabilities: " + aCapabilities);
+		}
+		synchronized (DatabaseBuilder.class) {
+			initLoader();
+			for (DatabaseProvider db : LOADER) {
+				if (db.supportsCapabilities(aCapabilities)) {
+					return db.create();
+				}
+			}
+		}
+		throw new RuntimeException(
+				"No database found that satisfies capabilities: "
+						+ Arrays.asList(aCapabilities));
+	}
+
+	/**
+	 * Gets a list of available databases. 
+	 * @return List of databases. 
+	 */
+	public static List<DatabaseDescription> getSupportedDatabases() {
+		initLoader();
+		List<DatabaseDescription> descriptions = new ArrayList<DatabaseDescription>();
+		for (DatabaseProvider db : LOADER) {
+			descriptions.add(db.getDescription());
+		}
+		return descriptions;
+	}
+
+	private static void initLoader() {
+		if (LOADER == null) {
+			LOADER = ServiceLoader.load(DatabaseProvider.class);
+		}
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java
new file mode 100644
index 00000000..c31427bc
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java
@@ -0,0 +1,41 @@
+package org.wamblee.support.persistence;
+
+/**
+ * Description of a specific database. 
+ */
+public class DatabaseDescription {
+
+	private String[] itsCapabilities; 
+	private String itsDatabase; 
+	private String itsOther;
+	
+	/**
+	 * Constructs the description. 
+	 * @param aCapabilities List of all capabilities. 
+	 * @param aDatabase Database. 
+	 * @param aOther Other information. 
+	 */
+	public DatabaseDescription(String[] aCapabilities, String aDatabase, String aOther) {
+		itsCapabilities = aCapabilities; 
+		itsDatabase = aDatabase; 
+		itsOther = aOther;
+	}
+	
+	@Override
+	public String toString() {
+		return "\n  Database " + itsDatabase + 
+				"\n    Capabilities: "  + printCapabilities() + 
+				"\n    Other info:   " + itsOther; 
+	}
+	
+	private String printCapabilities() {
+		String res = "";
+		for (int i = 0; i < itsCapabilities.length; i++) { 
+			res += "" + itsCapabilities[i]; 
+			if ( i < itsCapabilities.length -1 ) { 
+				res += ", ";
+			}
+		}
+		return res; 
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java
new file mode 100644
index 00000000..f6736aa1
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java
@@ -0,0 +1,42 @@
+package org.wamblee.support.persistence;
+
+/**
+ * Database provider. This database provider represents a particular type of
+ * database such as its capabilities and the ability to create an instance
+ * representing a running database.
+ * 
+ * Since the {@link DatabaseBuilder} uses a first match algorithm and the order
+ * of databaseproviders is not guaranteed, it is recommended for each database
+ * provider to also provide a unique capability that no other database has.
+ */
+public interface DatabaseProvider {
+
+	/**
+	 * Capability that all databases that run inmemory have.
+	 */
+	String CAPABILITY_IN_MEMORY = "INMEMORY";
+
+	/**
+	 * Capability that all databases that are external have.
+	 */
+	String CAPABILITY_EXTERNAL = "EXTERNAL";
+
+	/**
+	 * Determines if the database has all capabilities that are requested.
+	 * @param aCapabilities Capabilities it must ahve
+	 * @return True if it has all capabilities. 
+	 */
+	boolean supportsCapabilities(String[] aCapabilities);
+
+	/**
+	 * Gets the description for the database. 
+	 * @return Description.
+	 */
+	DatabaseDescription getDescription();
+
+	/**
+	 * Creates a database instance that represents a running instance of that database. 
+	 * @return Database. 
+	 */
+	Database create();
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java
new file mode 100644
index 00000000..44294e35
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+package org.wamblee.support.persistence;
+
+
+/**
+ * This class is used for starting the database from ant.
+ */
+public class DatabaseStarter {
+
+    /**
+     * Database class which encapsulates management of the database.
+     */
+    private Class _databaseClass;
+
+    /**
+     * Execution as a main program. Commandline
+     * 
+     * <pre>
+     * 
+     *    DatabaseStarter &lt;databaseClassName&gt;
+     *  
+     * </pre>
+     * 
+     * where the database class name must be the name of a concrete subclass of
+     * {@link Database}.
+     * 
+     * @param args
+     */
+    public static void main( String[] args ) throws Exception {
+        String clazz = args[0];
+        try {
+            new DatabaseStarter( Class.forName( clazz ) ).start( );
+        } catch ( Exception e ) {
+            e.printStackTrace( );
+            System.out
+                    .println( "\nUsage: ant dbClass ");
+        }
+    }
+
+    /**
+     * Constructs the database starter.
+     * 
+     * @param aClassName
+     *            Classname of the database class to use.
+     * @throws Exception
+     */
+    public DatabaseStarter( Class aClass ) throws Exception {
+        if ( !Database.class.isAssignableFrom( aClass ) ) {
+            throw new IllegalArgumentException( "Class '"
+                    + aClass.getName( )
+                    + "' is not a subclass of Database" );
+        }
+        _databaseClass = aClass;
+    }
+
+    /**
+     * Constructs a database starter with the derby database.
+     * 
+     * @throws Exception
+     */
+    public DatabaseStarter( ) throws Exception {
+        this( DerbyDatabase.class );
+    }
+
+    /**
+     * Starts the database.
+     * 
+     * @throws Exception
+     */
+    public void start( ) throws Exception {
+        Database lDatabase = (Database) _databaseClass.newInstance( );
+        lDatabase.start( );
+        System.out.println( "Database has been started. " );
+        System.out.println( );
+        System.out.println("=======================================================");
+        System.out.println( "Connection details:" );
+       // System.out.println( "  Driver class: "
+       //         + lDatabase.getDriverClassName( ) );
+        System.out.println( "  JDBC URL:     "
+                + lDatabase.getExternalJdbcUrl( ) );
+        System.out.println( "  username:     '" + lDatabase.getUsername( )
+                + "'" );
+        System.out.println( "  password:     '" + lDatabase.getPassword( )
+                + "'" );
+        System.out.println( "Interrupt the program to stop the database." );
+        System.out.println("=======================================================");
+        System.out.println("You must now populate the database with a schema. Use 'ant help' for information.");
+        for ( ;; ) {
+            Thread.sleep( 1000 );
+        }
+    }
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java
new file mode 100644
index 00000000..312e38a0
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java
@@ -0,0 +1,389 @@
+package org.wamblee.support.persistence;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.database.DatabaseConnection;
+import org.dbunit.database.DatabaseSequenceFilter;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.FilteredDataSet;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.filter.ITableFilter;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.dbunit.operation.DatabaseOperation;
+
+/**
+ * Database utilities is a simple support class for common tasks in working with
+ * databases.
+ */
+public class DatabaseUtils {
+
+	public static interface TableSet {
+		boolean contains(String aTableName);
+	}
+
+	public static interface JdbcUnitOfWork<T> {
+		T execute(Connection aConnection) throws Exception;
+	}
+
+	public static interface TableSetOperation {
+		void execute(String aTable) throws Exception;
+	}
+
+	private static final Logger LOG = Logger.getLogger(DatabaseUtils.class
+			.getName());
+
+	/**
+	 * Schema pattern.
+	 */
+	private static final String SCHEMA_PATTERN = "%";
+	private DataSource dataSource;
+	private ITableFilterSimple tables;
+	
+
+	public DatabaseUtils(DataSource aDataSource, ITableFilterSimple aTables) {
+		dataSource = aDataSource;
+		tables = aTables;
+	}
+
+	public IDatabaseTester createDbTester() throws Exception {
+		return createDbTester(getTableNames(tables));
+	}
+
+	public IDatabaseTester createDbTester(String[] aTables) throws Exception {
+		IDatabaseTester dbtester = new DataSourceDatabaseTester(dataSource);
+		dbtester.setDataSet(dbtester.getConnection().createDataSet(aTables));
+		return dbtester;
+	}
+
+	public void cleanDatabase() throws Exception {
+		cleanDatabase(tables);
+	}
+
+	public void executeOnTables(ITableFilterSimple aTables,
+			final TableSetOperation aOperation) throws Exception {
+		final String[] tables = getTableNames(aTables);
+		executeInTransaction(new JdbcUnitOfWork<Void>() {
+			public Void execute(Connection aConnection) throws Exception {
+				for (int i = tables.length - 1; i >= 0; i--) {
+					aOperation.execute(tables[i]);
+				}
+				return null;
+			}
+		});
+		for (String table : tables) {
+
+		}
+	}
+
+	public void cleanDatabase(ITableFilterSimple aSelection) throws Exception {
+
+		final String[] tables = getTableNames(aSelection);
+		executeInTransaction(new JdbcUnitOfWork<Void>() {
+
+			public Void execute(Connection aConnection) throws Exception {
+				IDatabaseConnection connection = new DatabaseConnection(
+						aConnection);
+				ITableFilter filter = new DatabaseSequenceFilter(connection,
+						tables);
+				IDataSet dataset = new FilteredDataSet(filter, connection
+						.createDataSet(tables));
+				DatabaseOperation.DELETE_ALL.execute(connection, dataset);
+				return null;
+			}
+		});
+
+	}
+
+	public <T> T executeInTransaction(JdbcUnitOfWork<T> aCallback)
+			throws Exception {
+		Connection connection = dataSource.getConnection();
+		try {
+			T value = aCallback.execute(connection);
+			connection.commit();
+			return value;
+		} finally {
+			connection.close();
+		}
+	}
+
+	public String[] getTableNames() throws Exception {
+		return getTableNames(tables);
+	}
+
+	/**
+	 * @throws SQLException
+	 */
+	public String[] getTableNames(ITableFilterSimple aSelection)
+			throws Exception {
+
+		List<String> result = new ArrayList<String>();
+		LOG.fine("Getting database table names to clean (schema: '"
+				+ SCHEMA_PATTERN + "'");
+
+		ResultSet tables = dataSource.getConnection().getMetaData().getTables(
+				null, SCHEMA_PATTERN, "%", new String[] { "TABLE" });
+		while (tables.next()) {
+			String table = tables.getString("TABLE_NAME");
+			if (aSelection.accept(table)) {
+				result.add(table);
+			}
+		}
+		return (String[]) result.toArray(new String[0]);
+	}
+
+	public void emptyTables() throws Exception {
+		executeOnTables(tables, new TableSetOperation() {
+			public void execute(String aTable) throws Exception {
+				emptyTable(aTable);
+			}
+		});
+	}
+
+	/**
+	 * @return
+	 * @throws SQLException
+	 */
+	public void emptyTables(final ITableFilterSimple aSelection)
+			throws Exception {
+		executeOnTables(aSelection, new TableSetOperation() {
+			public void execute(String aTable) throws Exception {
+				emptyTable(aTable);
+			}
+		});
+	}
+
+	/**
+	 * @return
+	 * @throws SQLException
+	 */
+	public void emptyTable(String aTable) throws Exception {
+		executeSql("delete from " + aTable);
+	}
+	
+	public void dropTables() throws Exception {
+		executeOnTables(tables, new TableSetOperation() {
+			
+			public void execute(String aTable) throws Exception {
+				dropTable(aTable);	
+			}
+		});
+	}
+
+	
+	public void dropTables(ITableFilterSimple aTables) throws Exception {
+		executeOnTables(aTables, new TableSetOperation() {
+			
+			public void execute(String aTable) throws Exception {
+				dropTable(aTable);	
+			}
+		});
+	}
+
+	/**
+	 * @return
+	 * @throws SQLException
+	 */
+	public void dropTable(final String aTable) throws Exception {
+		executeInTransaction(new JdbcUnitOfWork<Void>() {
+			public Void execute(Connection aConnection) throws Exception {
+				executeUpdate(aConnection, "drop table " + aTable);
+				return null;
+			}
+		});
+
+	}
+
+	/**
+	 * Executes an SQL statement within a transaction.
+	 * 
+	 * @param aSql
+	 *            SQL statement.
+	 * @return Return code of the corresponding JDBC call.
+	 */
+	public int executeSql(final String aSql) throws Exception {
+		return executeSql(aSql, new Object[0]);
+	}
+
+	/**
+	 * Executes an SQL statement within a transaction. See
+	 * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on
+	 * supported argument types.
+	 * 
+	 * @param aSql
+	 *            SQL statement.
+	 * @param aArg
+	 *            Argument of the sql statement.
+	 * @return Return code of the corresponding JDBC call.
+	 */
+	public int executeSql(final String aSql, final Object aArg)
+			throws Exception {
+		return executeSql(aSql, new Object[] { aArg });
+	}
+
+	/**
+	 * Executes an sql statement. See
+	 * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on
+	 * supported argument types.
+	 * 
+	 * @param aSql
+	 *            SQL query to execute.
+	 * @param aArgs
+	 *            Arguments.
+	 * @return Number of rows updated.
+	 */
+	public int executeSql(final String aSql, final Object[] aArgs)
+			throws Exception {
+		return executeInTransaction(new JdbcUnitOfWork<Integer>() {
+			public Integer execute(Connection aConnection) throws Exception {
+				PreparedStatement stmt = aConnection.prepareStatement(aSql);
+				setPreparedParams(aArgs, stmt);
+				return stmt.executeUpdate();
+			}
+		});
+	}
+
+	/**
+	 * Executes an SQL query.
+	 * 
+	 * @param aSql
+	 *            Query to execute.
+	 * @return Result set.
+	 */
+	public ResultSet executeQuery(Connection aConnection, String aSql) {
+		return executeQuery(aConnection, aSql, new Object[0]);
+	}
+
+	/**
+	 * Executes a query with a single argument. See
+	 * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on
+	 * supported argument types.
+	 * 
+	 * @param aSql
+	 *            Query.
+	 * @param aArg
+	 *            Argument.
+	 * @return Result set.
+	 */
+	public ResultSet executeQuery(Connection aConnection, String aSql,
+			Object aArg) {
+		return executeQuery(aConnection, aSql, new Object[] { aArg });
+	}
+
+	/**
+	 * Executes a query. See
+	 * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on
+	 * supported argument types.
+	 * 
+	 * @param aSql
+	 *            Sql query.
+	 * @param aArgs
+	 *            Arguments to the query.
+	 * @return Result set.
+	 */
+	public ResultSet executeQuery(Connection aConnection, final String aSql,
+			final Object[] aArgs) {
+		try {
+			PreparedStatement statement = aConnection.prepareStatement(aSql);
+			setPreparedParams(aArgs, statement);
+
+			return statement.executeQuery();
+		} catch (SQLException e) {
+			throw new RuntimeException(e);
+		}
+	}
+	
+	public int executeUpdate(Connection aConnection, final String aSql,
+			final Object... aArgs) {
+		try {
+			PreparedStatement statement = aConnection.prepareStatement(aSql);
+			setPreparedParams(aArgs, statement);
+
+			return statement.executeUpdate();
+		} catch (SQLException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Sets the values of a prepared statement. See
+	 * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on
+	 * supported argument types.
+	 * 
+	 * @param aArgs
+	 *            Arguments to the prepared statement.
+	 * @param aStatement
+	 *            Prepared statement
+	 * @throws SQLException
+	 */
+	private void setPreparedParams(final Object[] aArgs,
+			PreparedStatement aStatement) throws SQLException {
+		for (int i = 1; i <= aArgs.length; i++) {
+			setPreparedParam(i, aStatement, aArgs[i - 1]);
+		}
+	}
+
+	/**
+	 * Sets a prepared statement parameter.
+	 * 
+	 * @param aIndex
+	 *            Index of the parameter.
+	 * @param aStatement
+	 *            Prepared statement.
+	 * @param aObject
+	 *            Value Must be of type Integer, Long, or String.
+	 * @throws SQLException
+	 */
+	private void setPreparedParam(int aIndex, PreparedStatement aStatement,
+			Object aObject) throws SQLException {
+		if (aObject instanceof Integer) {
+			aStatement.setInt(aIndex, ((Integer) aObject).intValue());
+		} else if (aObject instanceof Long) {
+			aStatement.setLong(aIndex, ((Integer) aObject).longValue());
+		} else if (aObject instanceof String) {
+			aStatement.setString(aIndex, (String) aObject);
+		} else {
+			TestCase.fail("Unsupported object type for prepared statement: "
+					+ aObject.getClass() + " value: " + aObject
+					+ " statement: " + aStatement);
+		}
+	}
+
+	/**
+	 * @return
+	 * @throws SQLException
+	 */
+	public int getTableSize(final String aTable) throws Exception {
+		return executeInTransaction(new JdbcUnitOfWork<Integer>() {
+			public Integer execute(Connection aConnection) throws Exception {
+				ResultSet resultSet = executeQuery(aConnection,
+						"select count(*) from " + aTable);
+				resultSet.next();
+				return resultSet.getInt(1);
+			}
+		});
+
+	}
+
+	public int countResultSet(ResultSet aResultSet) throws SQLException {
+		int count = 0;
+
+		while (aResultSet.next()) {
+			count++;
+		}
+
+		return count;
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java
new file mode 100755
index 00000000..646931c5
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.support.persistence;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+
+import org.apache.derby.drda.NetworkServerControl;
+import org.wamblee.io.FileSystemUtils;
+
+/**
+ * Derby database setup. The external JDBC url used to connect to a running
+ * instance is
+ * 
+ * <pre>
+ *     jdbc:derby:net://localhost:1527/testdb
+ * </pre>
+ * 
+ * and the driver class is
+ * 
+ * <pre>
+ * com.ibm.db2.jcc.DB2Driver
+ * </pre>
+ * 
+ * The following jars will have to be used <code>db2jcc.jar</code> and
+ * <code>db2jcc_license_c.jar</code>.
+ */
+public class DerbyDatabase extends AbstractDatabase {
+
+	/**
+	 * Logger.
+	 */
+	private static final Logger LOGGER = Logger.getLogger(DerbyDatabase.class
+			.getName());
+
+	/**
+	 * Database user name.
+	 */
+	private static final String USERNAME = "sa";
+
+	/**
+	 * Database password.
+	 */
+	private static final String PASSWORD = "123";
+	/**
+	 * Poll interval for the checking the server status.
+	 */
+	private static final int POLL_INTERVAL = 100;
+
+	/**
+	 * Maximum time to wait until the server has started or stopped.
+	 */
+	private static final int MAX_WAIT_TIME = 10000;
+
+	/**
+	 * Database name to use.
+	 */
+	private static final String DATABASE_NAME = "testdb";
+
+	/**
+	 * Path on the file system where derby files are stored.
+	 */
+	private static final String DATABASE_PATH = "target/db/persistence/derby";
+
+	/**
+	 * Derby property required to set the file system path
+	 * {@link #DATABASE_PATH}.
+	 */
+	private static final String SYSTEM_PATH_PROPERTY = "derby.system.home";
+	
+
+	private boolean inmemory;
+		
+	
+	/**
+	 * Constructs derby database class to allow creation of derby database
+	 * instances.
+	 */
+	public DerbyDatabase() {
+		inmemory = true;
+	}
+
+	public DerbyDatabase(boolean aInMemoryFlag) {
+		inmemory = aInMemoryFlag;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.wamblee.persistence.Database#start()
+	 */
+	public void doStart() {
+		try {
+			// just in case a previous run was killed without the
+			// cleanup
+			cleanPersistentStorage();
+
+			if (!inmemory) {
+				// set database path.
+				Properties lProperties = System.getProperties();
+				lProperties.put(SYSTEM_PATH_PROPERTY, DATABASE_PATH);
+			}
+
+			Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
+
+			runDatabase();
+
+			waitUntilStartedOrStopped(true);
+
+			// Force creation of the database.
+			Connection lConnection = createConnection();
+			lConnection.close();
+			
+			LOGGER.info("Database started: \n    URL = " + getExternalJdbcUrl() + "\n    user = " + getUsername() + "\n    password = " 
+					+ getPassword()); 
+
+			createDataSource();
+			
+			Runtime.getRuntime().addShutdownHook(new Thread() {
+				@Override
+				public void run() {
+					if (isStarted()) {
+						LOGGER.warning("Shutting down db");
+						DerbyDatabase.this.stop();
+					}
+				}
+			});
+		} catch (Exception e) {
+			throw new RuntimeException("Problem starting database", e);
+		}
+	}
+
+	/**
+	 * Waits until the database server has started or stopped.
+	 * 
+	 * @param aStarted
+	 *            If true, waits until the server is up, if false, waits until
+	 *            the server is down.
+	 * @throws InterruptedException
+	 */
+	private void waitUntilStartedOrStopped(boolean aStarted)
+			throws InterruptedException {
+		long lWaited = 0;
+
+		while (aStarted != isStarted()) {
+			Thread.sleep(POLL_INTERVAL);
+			lWaited += POLL_INTERVAL;
+
+			if (lWaited > MAX_WAIT_TIME) {
+				throw new RuntimeException(
+						"Derby database did not start within " + MAX_WAIT_TIME
+								+ "ms");
+			}
+		}
+	}
+
+	/**
+	 * Checks if the database server has started or not.
+	 * 
+	 * @return True if started, false otherwise.
+	 */
+	private boolean isStarted() {
+		try {
+			getControl().ping();
+
+			return true;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	/**
+	 * Gets the controller for the database server.
+	 * 
+	 * @return Controller.
+	 * @throws Exception
+	 */
+	private NetworkServerControl getControl() throws Exception {
+		return new NetworkServerControl();
+	}
+
+	/**
+	 * Runs the database.
+	 * 
+	 */
+	private void runDatabase() {
+		try {
+			getControl().start(new PrintWriter(System.out));
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.wamblee.persistence.Database#getJdbcUrl()
+	 */
+	public String getJdbcUrl() {
+		return getBaseJdbcUrl()
+				+ ";create=true;retrieveMessagesFromServerOnGetMessage=true;";
+	}
+
+	private String getBaseJdbcUrl() {
+		return (inmemory ? "jdbc:derby:memory:": "jdbc:derby:") + DATABASE_NAME;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.wamblee.persistence.Database#getExternalJdbcUrl()
+	 */
+	public String getExternalJdbcUrl() {
+		return "jdbc:derby://localhost:1527/" + (inmemory ? "memory:" : "") + DATABASE_NAME;
+	}
+
+	/**
+	 * Shuts down the derby database and cleans up all created files.
+	 * 
+	 */
+	private void shutdownDerby() {
+		try {
+			DriverManager.getConnection("jdbc:derby:;shutdown=true");
+			throw new RuntimeException("Derby did not shutdown, "
+					+ " should always throw exception at shutdown");
+		} catch (Exception e) {
+			LOGGER.info("Derby has been shut down.");
+		}
+	}
+
+	/**
+	 * Gets the user name.
+	 */
+	public String getUsername() {
+		return USERNAME;
+	}
+
+	/**
+	 * Gets the password.
+	 * 
+	 * @return
+	 */
+	public String getPassword() {
+		return PASSWORD;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.wamblee.persistence.Database#createConnection()
+	 */
+	public Connection createConnection() throws SQLException {
+		Connection c = DriverManager.getConnection(getJdbcUrl(), getUsername(),
+				getPassword());
+
+		return c;
+	}
+
+
+	/**
+	 * Stops the derby database and cleans up all derby files.
+	 */
+	public void doStop() {
+		try {
+			// shutdown network server.
+			getControl().shutdown();
+			waitUntilStartedOrStopped(false);
+
+			// shutdown inmemory access.
+			shutdownDerby();
+			cleanPersistentStorage();
+		} catch (Exception e) {
+			LOGGER.log(Level.WARNING, "Problem stopping database", e);
+		}
+	}
+
+	/**
+	 * Cleans up persistent storage of Derby.
+	 */
+	private void cleanPersistentStorage() {
+		File lFile = new File(DATABASE_PATH);
+
+		if (lFile.isFile()) {
+			TestCase.fail("A regular file by the name " + DATABASE_PATH
+					+ " exists, clean this up first");
+		}
+
+		if (!lFile.isDirectory()) {
+			return; // no-op already cleanup up.
+		}
+		FileSystemUtils.deleteDirRecursively(DATABASE_PATH);
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java
new file mode 100644
index 00000000..088202c3
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java
@@ -0,0 +1,32 @@
+package org.wamblee.support.persistence;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DerbyDatabaseProvider extends AbstractDatabaseProvider {
+	
+	/**
+	 * Capabilities of this type of database. 
+	 */
+	public static final List<String> CAPABILIITIES = 
+		Arrays.asList(DatabaseProvider.CAPABILITY_IN_MEMORY, "DERBY");
+
+
+	public DerbyDatabaseProvider() {
+		// Empty
+	}
+
+	public Database create() {
+		return new DerbyDatabase();
+	}
+
+	public DatabaseDescription getDescription() {
+		return new DatabaseDescription(CAPABILIITIES.toArray(new String[0]),
+				"Derby", "In-memory, volatile, set breakpoint to debug");
+	}
+
+    @Override
+    protected List<String> getCapabilities() {
+    	return CAPABILIITIES;
+    }
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java
new file mode 100644
index 00000000..2533df42
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java
@@ -0,0 +1,82 @@
+package org.wamblee.support.persistence;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * Database that encapsulates connection to an external database. 
+ * Database connection details can be configured through system properties
+ * and environment variables, see {@link #DB_URL_PROP}, {@link #DB_USER_PROP}, and 
+ * {@link #DB_PASSWORD_PROP|. 
+ * 
+ * This class assumes modern database drivers that work together with java.util.ServiceLoader
+ * so that explicitly doing a Class.forName() is not necessary to load the database driver. 
+ */
+public class ExternalDatabase extends AbstractDatabase {
+	
+	private static final Logger LOGGER = Logger.getLogger(ExternalDatabase.class.getName()); 
+	
+	/**
+	 * System property/environment variable that defines the database URL. 
+	 */
+	public static final String DB_URL_PROP = "TEST_DB_URL";
+	
+	/**
+	 * System property/environment variable that defines the database user. 
+	 */
+	public static final String DB_USER_PROP = "TEST_DB_USER";
+	
+	/**
+	 * System property/environment variable that defines the database password. 
+	 */
+	public static final String DB_PASSWORD_PROP = "TEST_DB_PASSWORD";
+
+
+	private String itsUrl; 
+	private String itsUser; 
+	private String itsPassword; 
+	
+	private DataSource itsDataSource; 
+	
+	public ExternalDatabase() { 
+		// Empty
+	}
+	
+	public String getExternalJdbcUrl() {
+		return itsUrl; 
+	}
+
+	public String getJdbcUrl() {
+		return itsUrl; 
+	}
+
+	public String getPassword() {
+		return itsPassword;
+	}
+
+	public String getUsername() {
+		return itsUser;
+	}
+
+	public void doStart() {
+		itsUrl = getProperty(DB_URL_PROP);
+		itsUser = getProperty(DB_USER_PROP);
+		itsPassword = getProperty(DB_PASSWORD_PROP);
+		
+		createDataSource();
+	}
+
+	public void doStop() {
+		// Empty. 
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java
new file mode 100644
index 00000000..871be11a
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java
@@ -0,0 +1,35 @@
+package org.wamblee.support.persistence;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ExternalDatabaseProvider extends AbstractDatabaseProvider {
+
+	/**
+	 * Capabilities of this type of database.
+	 */
+	public static final List<String> CAPABILIITIES = Arrays
+			.asList(CAPABILITY_EXTERNAL);
+
+	@Override
+	protected List<String> getCapabilities() {
+		return CAPABILIITIES;
+	}
+
+	public Database create() {
+		return new ExternalDatabase();
+	}
+
+	public DatabaseDescription getDescription() {
+		return new DatabaseDescription(
+				CAPABILIITIES.toArray(new String[0]),
+				"External Database",
+				"Any database as described by the JDBC URL: requires system properties or environment variables: "
+						+ ExternalDatabase.DB_URL_PROP
+						+ ", "
+						+ ExternalDatabase.DB_USER_PROP
+						+ ", and "
+						+ ExternalDatabase.DB_PASSWORD_PROP);
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java
new file mode 100644
index 00000000..8b6e3399
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java
@@ -0,0 +1,136 @@
+package org.wamblee.support.persistence;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.wamblee.support.jndi.StubInitialContextFactory;
+
+
+/**
+ * Utility for building an appropriately configured EntityManagerFactory. The
+ * idea is that a persistence.xml is used unchanged from the production version.
+ * This utility will then add the additional properties required for execution
+ * in a standalone environment.
+ * 
+ * The other purpose is to to shield dependencies of the test code on a
+ * particular JPA provider.
+ */
+public class JpaBuilder {
+
+	private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
+			.getName());
+
+	/**
+	 * Callback interface to execute some JPA code within a transaction with the
+	 * entitymanager to use provided as input.
+	 */
+	public static interface JpaUnitOfWork<T> {
+		/**
+		 * Executes the unit of work. A transaction has been started.  
+		 * @param em Entity manager. 
+		 * @return Result of the execute method. If you don't want to return anything use
+		 *  <code>Void</code> for the return type and return null from the implementation. 
+		 */
+		T execute(EntityManager em);
+	}
+
+	private PersistenceUnitDescription persistenceUnit;
+	private DataSource dataSource;
+	private EntityManagerFactory factory;
+
+	/**
+	 * Constructs the builder.
+	 * 
+	 * @param aDataSource
+	 *            Datasource of database.
+	 * @param aPersistenceUnit
+	 *            Persistence unit.
+	 */
+	public JpaBuilder(DataSource aDataSource,
+			PersistenceUnitDescription aPersistenceUnit) {
+		persistenceUnit = aPersistenceUnit;
+		dataSource = aDataSource;
+		StubInitialContextFactory.register();
+	}
+
+	/**
+	 * Starts the builder, which in particular, mocks JNDI, binds the datasource
+	 * the JNDI where the persistence unit expects it, creates the entity
+	 * manager factory, and forces creation of the database schema.
+	 */
+	public void start() throws Exception {
+		try {
+			InitialContext ctx = new InitialContext();
+			ctx.bind(persistenceUnit.getJndiName(), dataSource);
+		} catch (NamingException e) {
+			throw new RuntimeException("JNDI problem", e);
+		}
+		factory = createFactory();
+		execute(new JpaUnitOfWork<Void>() {
+			public Void execute(EntityManager em) {
+				// Empty, just to trigger database schema creation.
+				return null;
+			}
+		});
+	}
+
+	/**
+	 * Stops the entity manager factory and disables JNDI mocking. 
+	 */
+	public void stop() {
+		StubInitialContextFactory.unregister();
+		factory.close();
+	}
+
+	/**
+	 * Creates a new entity manager factory. Typically not used by test code. 
+	 * @return Entity manager factory. 
+	 */
+	public EntityManagerFactory createFactory() {
+		Map<String, String> jpaProps = new TreeMap<String, String>();
+	
+		JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit, jpaProps);
+		
+		//jpaProps.put("javax.persistence.provider", HibernatePersistence.class.getName());
+		EntityManagerFactory factory = Persistence.createEntityManagerFactory(persistenceUnit
+				.getUnitName(), jpaProps);
+		
+		LOGGER.info("Using " + factory.getClass());
+		return factory;
+	}
+
+	/**
+	 * Executes a unit of work. This creates an entitymanager and runs the 
+	 * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction, passing
+	 * it the entity manager. Use of this method saves a lot of typing for applications. 
+	 * 
+	 * @param aWork Work to execute. 
+	 * @return The return value of the execute method of the unit of work. 
+	 */
+	public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
+		EntityManager em = factory.createEntityManager();
+		EntityTransaction transaction = em.getTransaction();
+		transaction.begin();
+		try {
+			T value = aWork.execute(em);
+			transaction.commit();
+			return value; 
+		} catch (Exception e) {
+			LOGGER.log(Level.WARNING, "Exception occured", e);
+			transaction.rollback();
+			throw e; 
+		} finally {
+			em.close();
+		}
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java
new file mode 100644
index 00000000..79303012
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java
@@ -0,0 +1,22 @@
+package org.wamblee.support.persistence;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+/**
+ * JPA customizer is used to customize properties for a given JPA implementation.
+ * 
+ * Implementations of JpaCustomizer are found using {@link ServiceLoader}. In case
+ * of testing with a specific JPA provider, the customizer library for that JPA provider
+ * must be on the classpath as well. 
+ * 
+ * @author Erik Brakkee
+ */
+public interface JpaCustomizer {
+
+    void customize(PersistenceUnitDescription aPersistenceUnit, Map<String,String> aJpaProperties);
+    
+    ITableFilterSimple getJpaTables();
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java
new file mode 100644
index 00000000..a824bf6f
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java
@@ -0,0 +1,20 @@
+package org.wamblee.support.persistence;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+public class JpaCustomizerBuilder {
+
+    private static final ServiceLoader<JpaCustomizer> CUSTOMIZERS = 
+        ServiceLoader.load(JpaCustomizer.class);
+    
+    
+    public static JpaCustomizer getCustomizer() { 
+        List<JpaCustomizer> customizers = new ArrayList<JpaCustomizer>(); 
+        for (JpaCustomizer customizer: CUSTOMIZERS) { 
+            customizers.add(customizer);
+        }
+        return new CompositeJpaCustomizer(customizers);
+    }
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java
new file mode 100644
index 00000000..a6a512f1
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java
@@ -0,0 +1,113 @@
+package org.wamblee.support.persistence;
+
+import javax.sql.DataSource;
+
+import org.dbunit.IDatabaseTester;
+
+/**
+ * This class is the entry point for JPA tests. Test code should construct a JpaTester in the 
+ * <code>@Before</code> method and call {@link #start()} on it in that method. Also, test code should 
+ * call {@link #stop()} on it in the <code>@After</code> method.  
+ * 
+ * This class is constructed with a description of the persistence unit to be tested. The principle is that
+ * an existing <code>persistence.xml</code> can be tested without change in unit test code. 
+ *  
+ * It then takes care of the following: 
+ * <ul> 
+ *   <li>  Creating an inmemory database for testing (default) or connecting to an external database. 
+ *        See {@link DatabaseBuilder} for more information on how a databse is obtained. 
+ *   </li>
+ *   <li> Drop all database tables that are related to the persistence unit under test, including JPA provider
+ *      specific tables. 
+ *   </li>
+ *   <li>  Creating a datasource for the database and make the datasource available through JNDI. 
+ *   </li>
+ *   <li> Creating the entity manager factory for JPA and configuring it in such a way that schema creation 
+ *      happens. (Typically, schema creation will be disabled in the persistence.xml but this utility enables it 
+ *      for unit test). 
+ *   </li>
+ *   <li> Creating a DBUnit database tester which is appropriately configured for the persistence unit under test. 
+ *   </li>
+ * </ul>
+ * 
+ * The main entry point for all this functionality is the {@link PersistenceUnitDescription} which describes the 
+ * persistence unit and must be provided at construction of the <code>JpaTester</code>
+ * 
+ * NOTE: Persistence XML files should be explicitly configured with the classes that are part of the persistence unit
+ * since scanning of classes does not work correctly in a unit test environment. This is currently the only limitation.
+ */
+public class JpaTester {
+
+	private PersistenceUnitDescription persistenceUnit;
+	private Database db;
+	private DataSource dataSource;
+	private DatabaseUtils dbUtils;
+	private JpaBuilder jpaBuilder;
+	private IDatabaseTester dbTester;
+
+	/**
+	 * Constructs the tester.
+	 * @param aPersistenceUnit Persistence unit under test. 
+	 */
+	public JpaTester(PersistenceUnitDescription aPersistenceUnit) {
+		persistenceUnit = aPersistenceUnit;
+	}
+
+	/**
+	 * Starts the tester. This must be called prior to running the test. 
+	 * @throws Exception
+	 */
+	public void start() throws Exception {
+		db = DatabaseBuilder.getDatabase();
+		dataSource = db.start();
+
+		dbUtils = new DatabaseUtils(dataSource, persistenceUnit.getTables());
+		dbUtils.dropTables();
+		dbUtils.dropTables(JpaCustomizerBuilder.getCustomizer().getJpaTables());
+
+		jpaBuilder = new JpaBuilder(dataSource, persistenceUnit);
+		jpaBuilder.start();
+
+		// db tester should be created after Jpa builder because jpa builder
+		// creates the
+		// tables that the tester looks at when it is initialized.
+		dbTester = dbUtils.createDbTester();
+	}
+
+	/**
+	 * Stops the tester. This must be called after the test. 
+	 */
+	public void stop() {
+		if (jpaBuilder != null) {
+			jpaBuilder.stop();
+		}
+		if (db != null) {
+			db.stop();
+		}
+	}
+
+	public Database getDb() {
+		return db;
+	}
+
+	public DataSource getDataSource() {
+		return dataSource;
+	}
+
+	public IDatabaseTester getDbTester() {
+		return dbTester;
+	}
+
+	public DatabaseUtils getDbUtils() {
+		return dbUtils;
+	}
+
+	public JpaBuilder getJpaBuilder() {
+		return jpaBuilder;
+	}
+
+	public PersistenceUnitDescription getPersistenceUnit() {
+		return persistenceUnit;
+	}
+
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java
new file mode 100644
index 00000000..a2499b47
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java
@@ -0,0 +1,28 @@
+package org.wamblee.support.persistence;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+public class PersistenceUnitDescription {
+
+	private String jndiName; 
+	private String unitName; 
+	private ITableFilterSimple tables; 
+	
+	public PersistenceUnitDescription(String aJndiName, String aUnitName, ITableFilterSimple aTables) {
+		jndiName = aJndiName;
+		unitName = aUnitName;
+		tables = aTables; 
+	}
+	
+	public String getJndiName() {
+		return jndiName;
+	}
+	
+	public String getUnitName() {
+		return unitName;
+	}
+	
+	public ITableFilterSimple getTables() { 
+		return tables; 
+	}
+}
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java
new file mode 100644
index 00000000..1bd7050c
--- /dev/null
+++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * This package provide a number of utilities for database testing and in particular with 
+ * JPA. 
+ * 
+ * The following utilities are available: 
+ * <ul>
+ *   <li> {@link JpaTester}: The main entry point for all JPA tests. 
+ *   </li>
+ *   <li> {@link JpaBuilder}: A utility constructed by <code>JpaTester</code> that provides a callback based 
+ *      style of working with transaction-scoped entity managers. 
+ *   </li>
+ *   <li> {@link DatabaseUtils}: A utility constructed by <code>JpaTester</code> for working with databases in general. Test code will not use this 
+ *        utility often. 
+ *   </li>
+ *   <li> {@link org.dbunit.IDatabaseTester}: A DB unit database tester. The test code can use this database tester. 
+ *   It is also created by <code>JpaTester</code>
+ *   </li>
+ *   <li> {@link DatabaseBuilder}: A utility by which test code can transparently create an inmemory database or 
+ *      connect to an external database. This is also used by <code>JpaTester</code>
+ *   </li>
+ * </ul>
+ */
+package org.wamblee.support.persistence;
diff --git a/test/enterprise/src/main/resources/META-INF/services/org.wamblee.support.persistence.DatabaseProvider b/test/enterprise/src/main/resources/META-INF/services/org.wamblee.support.persistence.DatabaseProvider
new file mode 100644
index 00000000..62979fb3
--- /dev/null
+++ b/test/enterprise/src/main/resources/META-INF/services/org.wamblee.support.persistence.DatabaseProvider
@@ -0,0 +1,2 @@
+org.wamblee.support.persistence.DerbyDatabaseProvider
+org.wamblee.support.persistence.ExternalDatabaseProvider
diff --git a/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java b/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java
new file mode 100644
index 00000000..6016e2b3
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java
@@ -0,0 +1,41 @@
+package org.wamblee.support.jndi;
+
+import static junit.framework.Assert.assertEquals;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.jndi.StubInitialContextFactory;
+
+public class StubInitiaContextFactoryTest {
+
+	@Before
+	@After
+	public void setUp() { 
+		StubInitialContextFactory.unregister();
+	}
+
+	
+	@Test(expected = NamingException.class)
+	public void testLookupNotRegistered() throws Exception { 
+		InitialContext ctx = new InitialContext();
+		ctx.bind("a/b", "hallo");
+	}
+	
+	@Test
+	public void testLookup() throws Exception {
+	    StubInitialContextFactory.register();
+	    
+		InitialContext ctx = new InitialContext();
+		ctx.bind("a/b", "hallo");
+		
+		ctx = new InitialContext(); 
+		Object obj = ctx.lookup("a/b");
+		
+		assertEquals("hallo", obj);
+	}
+	
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java
new file mode 100644
index 00000000..51364876
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java
@@ -0,0 +1,16 @@
+package org.wamblee.support.persistence;
+
+import org.junit.Test;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseDescription;
+
+public class DatabaseBuilderTest {
+
+	
+	@Test
+	public void testListAvailableDatabases() {
+		for (DatabaseDescription description: DatabaseBuilder.getSupportedDatabases()) { 
+			System.out.println(description);
+		}
+	}
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java
new file mode 100644
index 00000000..e55f1341
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java
@@ -0,0 +1,89 @@
+package org.wamblee.support.persistence;
+
+import static junit.framework.Assert.assertEquals;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+public class DatabaseUtilsTestBase {
+    private Database db;
+    private DataSource dataSource;
+    private PersistenceUnitDescription persistenceUnit;
+    private JpaBuilder builder;
+    private DatabaseUtils dbutils;
+    private IDatabaseTester dbtester;
+
+    @Before
+    public void setUp() throws Exception {
+        db = DatabaseBuilder.getDatabase();
+        dataSource = db.start();
+
+        persistenceUnit = new MyPersistenceUnit();
+
+        dbutils = new DatabaseUtils(dataSource, persistenceUnit.getTables());
+        dbutils.dropTables();
+        dbutils.dropTables(JpaCustomizerBuilder.getCustomizer().getJpaTables());
+
+        builder = new JpaBuilder(dataSource, persistenceUnit);
+        builder.start();
+        
+        dbtester = dbutils.createDbTester();
+    }
+
+    @After
+    public void tearDown() {
+        builder.stop();
+        db.stop();
+    }
+
+    @Test
+    public void testTablesCorrect() throws Exception {
+        String[] tables = dbutils.getTableNames();
+        assertEquals(1, tables.length);
+        assertEquals("XYZ_MYENTITY", tables[0]);
+    }
+
+    @Test
+    public void testDeleteTables() throws Exception {
+        String[] tables = dbutils.getTableNames();
+        assertEquals(1, tables.length);
+        assertEquals("XYZ_MYENTITY", tables[0]);
+
+        // Put some data in the database.
+        builder.execute(new JpaUnitOfWork<Void>() {
+            public Void execute(EntityManager em) {
+                MyEntity entity = new MyEntity("a", "b");
+                em.persist(entity);
+                return null;
+            }
+        });
+
+        // Verify one row is written (using Db unit)
+        ITable table = dbtester.getDataSet().getTable("XYZ_MYENTITY");
+        assertEquals(1, table.getRowCount());
+
+        // Clean the database
+        dbutils.cleanDatabase();
+        table = dbtester.getDataSet().getTable("XYZ_MYENTITY");
+        assertEquals(0, table.getRowCount());
+
+        // Now drop the database
+        dbutils.dropTables();
+        dbutils.dropTables(JpaCustomizerBuilder.getCustomizer().getJpaTables());
+        tables = dbutils.getTableNames();
+        assertEquals(0, tables.length);
+    }
+
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java
new file mode 100644
index 00000000..ffc17aea
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java
@@ -0,0 +1,47 @@
+package org.wamblee.support.persistence;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+
+
+public class DerbyDatabaseTest {
+
+	private Database db; 
+	private DataSource ds; 
+	
+	@Before
+	public void setUp() { 
+		db = DatabaseBuilder.getDatabase();
+		ds = db.start();
+	}
+	
+	@After
+	public void tearDown() { 
+		db.stop(); 
+	}
+	
+	@Test
+	public void testConnect() throws Exception { 
+		Connection conn = ds.getConnection();
+		try { 
+			System.out.println("Database name: " + conn.getMetaData().getDatabaseProductName());  
+		} finally { 
+			conn.close();
+		}
+	}
+	
+	@Test
+	public void testUseASecondTimeInTheSameTestCase() throws Exception { 
+		testConnect(); 
+		tearDown();
+		setUp();
+		testConnect();
+	}
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java
new file mode 100644
index 00000000..dbe5800b
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java
@@ -0,0 +1,53 @@
+package org.wamblee.support.persistence;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseProvider;
+import org.wamblee.support.persistence.ExternalDatabase;
+
+import static junit.framework.TestCase.*;
+
+public class ExternalDatabaseTest {
+
+	@Test
+	public void testExternalDB() throws Exception {
+		// Connect to inmemory db using External database class.
+
+		Database inmemory = DatabaseBuilder
+				.getDatabase(DatabaseProvider.CAPABILITY_IN_MEMORY);
+		try {
+			inmemory.start();
+
+			System.setProperty(ExternalDatabase.DB_URL_PROP, inmemory
+					.getExternalJdbcUrl());
+			System.setProperty(ExternalDatabase.DB_USER_PROP, inmemory
+					.getUsername());
+			System.setProperty(ExternalDatabase.DB_PASSWORD_PROP, inmemory
+					.getPassword());
+
+			Database external = DatabaseBuilder
+					.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL);
+			assertTrue(external instanceof ExternalDatabase);
+			try {
+				DataSource ds = external.start();
+				Connection conn = ds.getConnection();
+				try {
+					System.out.println("Database name: "
+							+ conn.getMetaData().getDatabaseProductName());
+				} finally {
+					conn.close();
+				}
+			} finally {
+				external.stop();
+			}
+		} finally {
+			inmemory.stop();
+		}
+
+	}
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java
new file mode 100644
index 00000000..c2b47288
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java
@@ -0,0 +1,39 @@
+package org.wamblee.support.persistence;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "XYZ_MYENTITY")
+public class MyEntity {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	private Long id; 
+	
+	private String sleuteltje; 
+	private String value; 
+	
+	
+	public MyEntity() { 
+	   // Empty	
+	}
+	
+	public MyEntity(String aKey, String aValue) { 
+		sleuteltje = aKey; 
+		value = aValue; 
+	}
+	
+	public String getKey() {
+		return sleuteltje;
+	}
+	
+	public String getValue() {
+		return value;
+	}
+
+	
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java
new file mode 100644
index 00000000..77f6114a
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java
@@ -0,0 +1,87 @@
+package org.wamblee.support.persistence;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.DatabaseTestCase;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.JpaTester;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+import static junit.framework.Assert.*;
+
+
+/**
+ * This class shows an example of how to test an entity  using jpa. 
+ */
+public class MyEntityExampleTestBase {
+
+	// This is the magical object that does all the test setup. 
+    private JpaTester jpaTester; 
+    
+    // The jpa tester initializes a lot for us....
+    
+    // A JPA builder that provides a transaction scoped entity manager for us. 
+    private JpaBuilder builder; 
+    
+    // The database tester for dbunit which is appropriately configured for our persistence unit. 
+    private IDatabaseTester dbtester; 
+    
+    // Database utilities with some additional functionality for working with the databse
+    // such as dropping tables, cleaning tables, etc. 
+    private DatabaseUtils dbutils; 
+	
+	@Before
+	public void setUp() throws Exception {
+
+		// First we create the JpaTester by telling us which persistence unit we are going to test
+		jpaTester = new JpaTester(new MyPersistenceUnit());
+	    jpaTester.start();
+	    
+	    // Retrieve some useful objects fromt he jpa tester. It also provides direct access to the datasource
+	    // but we don't need it. We can use datbase utils if we want to execute straight JDBC calls. 
+	    builder = jpaTester.getJpaBuilder();
+	    dbtester = jpaTester.getDbTester();
+	    dbutils = jpaTester.getDbUtils(); 
+	}
+	
+	@After
+	public void tearDown() { 
+		jpaTester.stop();
+	}
+	
+	@Test
+	public void testEntityPersistence() throws Exception { 
+		
+		// Use the JPA builder to create a transaction scoped entity manager for as and execute the 
+		// unit of work. 
+		builder.execute(new JpaUnitOfWork<Void>() {
+			public Void execute(EntityManager em) {
+				MyEntity entity = new MyEntity("a", "b"); 
+				em.persist(entity);
+				return null; 
+			}
+		}); 
+		
+		// Verify one row is written (using Db unit)
+		ITable table = dbtester.getDataSet().getTable("XYZ_MYENTITY");
+		assertEquals(1, table.getRowCount());
+		
+	    assertEquals("a", table.getValue(0, "SLEUTELTJE")); 
+	    assertEquals("b", table.getValue(0, "VALUE"));
+		
+		// For this simple test, it can also be done through DatabaseUtils
+		assertEquals(1, dbutils.getTableSize("XYZ_MYENTITY"));
+	
+	}
+
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java
new file mode 100644
index 00000000..777dd882
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java
@@ -0,0 +1,15 @@
+package org.wamblee.support.persistence;
+
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+
+/**
+ * This class describes the persistence unit that we are testing. 
+ */
+public class MyPersistenceUnit extends PersistenceUnitDescription {
+	private static final String JNDI_NAME = "wamblee/support/test";
+	private static final String PERSISTENCE_UNIT_NAME = "org.wamblee.jee.support-test";
+	
+	public MyPersistenceUnit() { 
+		super(JNDI_NAME, PERSISTENCE_UNIT_NAME, new MyTables());
+	}
+}
diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java
new file mode 100644
index 00000000..1283a8ff
--- /dev/null
+++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java
@@ -0,0 +1,25 @@
+package org.wamblee.support.persistence;
+
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+/**
+ * This class describes the tables we are testing. 
+ * This implementation selects all tables with the "XYZ" prefix. 
+ */
+public class MyTables implements ITableFilterSimple {
+		
+	/**
+	 * 
+	 * @param aJpaTables Specific tables used by the JPA provider in addition to those for the 
+	 *   entities.  
+	 */
+	public MyTables() { 
+		// Empty.
+	}
+
+	public boolean accept(String tableName) throws DataSetException {
+		return tableName.startsWith("XYZ_");
+	}
+
+}
diff --git a/test/enterprise/src/test/resources/META-INF/persistence.xml b/test/enterprise/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 00000000..c2528813
--- /dev/null
+++ b/test/enterprise/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="1.0"
+	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_1_0.xsd">
+	<persistence-unit name="org.wamblee.jee.support-test"
+		transaction-type="JTA">
+		<jta-data-source>wamblee/support/test</jta-data-source>
+		<class>org.wamblee.support.persistence.MyEntity</class>
+		<properties>
+			<!--
+				<property name="toplink.ddl-generation"
+				value="drop-and-create-tables" />
+			-->
+			<!--  <property name="toplink.ddl-generation" value="none" /> -->
+			<property name="toplink.ddl-generation" value="create-tables" />
+
+			<!--
+				<property name="toplink.create-ddl-jdbc-file-name"
+				value="create_tm_ddl.jdbc" />
+			-->
+			<!--
+				<property name="toplink.drop-ddl-jdbc-file-name"
+				value="drop_tm_ddl.jdbc" />
+			-->
+
+			<property name="toplink.logging.level" value="INFO" />
+
+			<!--
+				Toplink 2nd level cache disable for JSROuteRule, this is required so
+				that changes made by one instance in a cluster become visible to the
+				cluster. See
+				http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html#TopLinkCaching
+				for information on these toplink caching properties.
+			-->
+			<property name="toplink.cache.shared.default" value="false" />
+
+		</properties>
+
+	</persistence-unit>
+</persistence>
diff --git a/test/hibernate/pom.xml b/test/hibernate/pom.xml
new file mode 100644
index 00000000..d1c7b3d5
--- /dev/null
+++ b/test/hibernate/pom.xml
@@ -0,0 +1,50 @@
+<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/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.wamblee</groupId>
+    <artifactId>wamblee-utils</artifactId>
+    <version>0.2-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.wamblee</groupId>
+  <artifactId>wamblee-test-hibernate</artifactId>
+  <packaging>jar</packaging>
+  <name>/test/hibernate</name>
+  <url>http://wamblee.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.dbunit</groupId>
+      <artifactId>dbunit</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-hibernate-jpa</artifactId>
+      <version>0.2-SNAPSHOT</version>
+    </dependency>
+
+  </dependencies>
+
+</project>
diff --git a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java
new file mode 100644
index 00000000..fa4def8f
--- /dev/null
+++ b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java
@@ -0,0 +1,31 @@
+package org.wamblee.support.persistence.hibernate;
+
+import java.util.Map;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.wamblee.support.persistence.JpaCustomizer;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+
+public class HibernateJpaCustomizer implements JpaCustomizer {
+
+    public HibernateJpaCustomizer() { 
+        // Empty
+    }
+    
+    @Override
+    public void customize(PersistenceUnitDescription aPersistenceUnit, Map<String, String> aJpaProperties) {
+        // Hibernate: Override transaction type and datasource
+        aJpaProperties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
+        aJpaProperties.put("javax.persistence.jtaDataSource", null);
+        aJpaProperties.put("javax.persistence.nonJtaDataSource", aPersistenceUnit.getJndiName());
+        
+        // Hibernate schema generation
+        aJpaProperties.put("hibernate.hbm2ddl.auto", "create");     
+    }
+    
+    @Override
+    public ITableFilterSimple getJpaTables() {
+        return new HibernateTables();
+    }
+
+}
diff --git a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java
new file mode 100644
index 00000000..4b2c8a09
--- /dev/null
+++ b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java
@@ -0,0 +1,20 @@
+package org.wamblee.support.persistence.hibernate;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+/**
+ * Toplink-specific tables. 
+ */
+public class HibernateTables implements ITableFilterSimple {
+
+	private static final List<String> TABLES = Arrays.asList(new String[] { "" } );
+	
+	public boolean accept(String aTableName) throws DataSetException {
+		return TABLES.contains(aTableName);
+	}
+
+}
diff --git a/test/hibernate/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer b/test/hibernate/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
new file mode 100644
index 00000000..d057634d
--- /dev/null
+++ b/test/hibernate/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
@@ -0,0 +1 @@
+org.wamblee.support.persistence.hibernate.HibernateJpaCustomizer
diff --git a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java
new file mode 100644
index 00000000..68edf22a
--- /dev/null
+++ b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java
@@ -0,0 +1,23 @@
+package org.wamblee.support.persistence.hibernate;
+
+import static junit.framework.Assert.assertEquals;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.DatabaseUtilsTestBase;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+public class DatabaseUtilsTest extends DatabaseUtilsTestBase {
+   // Empty, all tests inherited
+}
diff --git a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java
new file mode 100644
index 00000000..537cb549
--- /dev/null
+++ b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java
@@ -0,0 +1,29 @@
+package org.wamblee.support.persistence.hibernate;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.DatabaseTestCase;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.JpaTester;
+import org.wamblee.support.persistence.MyEntityExampleTestBase;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+import static junit.framework.Assert.*;
+
+
+/**
+ * This class shows an example of how to test an entity  using jpa. 
+ */
+public class MyEntityExampleTest extends MyEntityExampleTestBase {
+    // Empty, all tests are inherited
+}
diff --git a/test/pom.xml b/test/pom.xml
new file mode 100644
index 00000000..97234c79
--- /dev/null
+++ b/test/pom.xml
@@ -0,0 +1,38 @@
+<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/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.wamblee</groupId>
+    <artifactId>wamblee-utils</artifactId>
+    <version>0.2-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.wamblee</groupId>
+  <artifactId>wamblee-test</artifactId>
+  <packaging>pom</packaging>
+  <name>/test</name>
+  <url>http://wamblee.org</url>
+
+  <modules>
+    <module>enterprise</module>
+    <module>hibernate</module>
+  </modules>
+
+  <profiles>
+    <profile>
+      <id>all</id>
+      <activation>
+        <property>
+          <name>!wamblee.release</name>
+        </property>
+      </activation>
+      <modules>
+        <module>eclipselink</module>
+        <module>toplink-essentials</module>
+      </modules>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/test/toplink-essentials/pom.xml b/test/toplink-essentials/pom.xml
new file mode 100644
index 00000000..8500c86a
--- /dev/null
+++ b/test/toplink-essentials/pom.xml
@@ -0,0 +1,60 @@
+<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/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.wamblee</groupId>
+    <artifactId>wamblee-utils</artifactId>
+    <version>0.2-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.wamblee</groupId>
+  <artifactId>wamblee-test-toplink-essentials</artifactId>
+  <packaging>jar</packaging>
+  <name>/test/toplinkessentials</name>
+  <url>http://wamblee.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.wamblee</groupId>
+      <artifactId>wamblee-test-enterprise</artifactId>
+      <version>0.2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.dbunit</groupId>
+      <artifactId>dbunit</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>toplink.essentials</groupId>
+      <artifactId>toplink-essentials</artifactId>
+    </dependency>
+
+
+  </dependencies>
+
+    <repositories>
+        <repository>
+            <id>javaee</id>
+            <name>Java EE repo at SUN</name>
+            <url>http://download.java.net/maven/1</url>
+            <layout>legacy</layout>
+        </repository>
+
+    </repositories>
+
+</project>
diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java
new file mode 100644
index 00000000..814fe593
--- /dev/null
+++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java
@@ -0,0 +1,59 @@
+package org.wamblee.support.persistence.toplink;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import oracle.toplink.essentials.jndi.JNDIConnector;
+import oracle.toplink.essentials.sessions.DatabaseLogin;
+import oracle.toplink.essentials.sessions.Session;
+import oracle.toplink.essentials.threetier.ServerSession;
+import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer;
+ 
+/**
+ * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) Use for clients that would like to use a
+ * JTA SE pu instead of a RESOURCE_LOCAL SE pu.
+ * 
+ * This utility also makes sure that using a persistence.xml with a JTA datasource works in a standalone Java SE 
+ * environment together with our JNDI stub. 
+ */
+public class JndiSessionCustomizer
+    implements SessionCustomizer {
+	
+	public JndiSessionCustomizer() {
+		// Empty.
+	}
+ 
+  /**
+   * Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP
+   */
+  public void customize(Session session) throws Exception {
+    JNDIConnector connector = null;
+    Context context = null;
+    try {
+      context = new InitialContext();
+      if(null != context) {
+        connector = (JNDIConnector)session.getLogin().getConnector(); // possible CCE
+        // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP
+        // Note: if both jta and non-jta elements exist this will only change the first one - and may still result in
+        // the COMPOSITE_NAME_LOOKUP being set
+        // Make sure only jta-data-source is in persistence.xml with no non-jta-data-source property set
+        connector.setLookupType(JNDIConnector.STRING_LOOKUP);
+ 
+        // Or, if you are specifying both JTA and non-JTA in your persistence.xml then set both connectors to be safe
+        JNDIConnector writeConnector = (JNDIConnector)session.getLogin().getConnector();
+        writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP);
+        JNDIConnector readConnector =
+            (JNDIConnector)((DatabaseLogin)((ServerSession)session).getReadConnectionPool().getLogin()).getConnector();
+        readConnector.setLookupType(JNDIConnector.STRING_LOOKUP);
+ 
+        System.out.println("JndiSessionCustomizer: configured " + connector.getName());
+      }
+      else {
+        throw new Exception("JndiSessionCustomizer: Context is null");
+      }
+    }
+    catch(Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java
new file mode 100644
index 00000000..5ba15e84
--- /dev/null
+++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java
@@ -0,0 +1,30 @@
+package org.wamblee.support.persistence.toplink;
+
+import java.util.Map;
+
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.wamblee.support.persistence.JpaCustomizer;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+
+public class ToplinkJpaCustomizer implements JpaCustomizer {
+
+    public ToplinkJpaCustomizer() { 
+        // Empty
+    }
+    
+    @Override
+    public void customize(PersistenceUnitDescription aPersistenceUnit, Map<String, String> aJpaProperties) {
+        // Hack to make JNDI lookup of the datasource work with toplink
+        aJpaProperties.put("toplink.session.customizer", JndiSessionCustomizer.class
+                .getName());
+        
+        // DDL generation for toplink
+        aJpaProperties.put("toplink.ddl-generation", "create-tables");   
+    }
+    
+    @Override
+    public ITableFilterSimple getJpaTables() {
+        return new ToplinkTables();
+    }
+
+}
diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java
new file mode 100644
index 00000000..cd3a0562
--- /dev/null
+++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java
@@ -0,0 +1,20 @@
+package org.wamblee.support.persistence.toplink;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+
+/**
+ * Toplink-specific tables. 
+ */
+public class ToplinkTables implements ITableFilterSimple {
+
+	private static final List<String> TABLES = Arrays.asList(new String[] { "SEQUENCE" } );
+	
+	public boolean accept(String aTableName) throws DataSetException {
+		return TABLES.contains(aTableName);
+	}
+
+}
diff --git a/test/toplink-essentials/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer b/test/toplink-essentials/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
new file mode 100644
index 00000000..82d1265a
--- /dev/null
+++ b/test/toplink-essentials/src/main/resources/META-INF/services/org.wamblee.support.persistence.JpaCustomizer
@@ -0,0 +1 @@
+org.wamblee.support.persistence.toplink.ToplinkJpaCustomizer
diff --git a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java
new file mode 100644
index 00000000..095109d3
--- /dev/null
+++ b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java
@@ -0,0 +1,23 @@
+package org.wamblee.support.persistence.toplink;
+
+import static junit.framework.Assert.assertEquals;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.Database;
+import org.wamblee.support.persistence.DatabaseBuilder;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.DatabaseUtilsTestBase;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.PersistenceUnitDescription;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+public class DatabaseUtilsTest extends DatabaseUtilsTestBase {
+   // Empty, all tests inherited
+}
diff --git a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java
new file mode 100644
index 00000000..415ee70f
--- /dev/null
+++ b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java
@@ -0,0 +1,29 @@
+package org.wamblee.support.persistence.toplink;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.DatabaseTestCase;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.filter.ITableFilterSimple;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.wamblee.support.persistence.DatabaseUtils;
+import org.wamblee.support.persistence.JpaBuilder;
+import org.wamblee.support.persistence.JpaTester;
+import org.wamblee.support.persistence.MyEntityExampleTestBase;
+import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork;
+
+import static junit.framework.Assert.*;
+
+
+/**
+ * This class shows an example of how to test an entity  using jpa. 
+ */
+public class MyEntityExampleTest extends MyEntityExampleTestBase {
+    // Empty, all tests are inherited
+}
-- 
2.31.1