Spring Clean Close Saving HSQL in a memory database

I have an In-Memory database to run some unit tests. I am using Spring ORM 3.2.1 to run this In-Memory database. Spring context is part of a web application accessible through some REST interface implemented using Jersey 1.10. My tests are implemented as a JerseyTest criterion, and thus the context of the Spring application is hidden from the real leisure runner. My problem now is that we carefully close the database between tests so that one test does not see the data saved by the previous test.

My old implementation using only JPA and HSQL is called:

if (factory != null && factory.isOpen()) {
        EntityManager manager = factory.createEntityManager();
        manager.getTransaction().begin();
        manager.createNativeQuery("SHUTDOWN").executeUpdate();
        manager.getTransaction().commit();
}

in the database to make sure everything is deleted.

If I do the same in my created Spring database, I get an error:

Internal Exception: java.sql.SQLNonTransientConnectionException: connection exception:  closed
Error Code: -1353
Call: SHUTDOWN
Query: DataModifyQuery(sql="SHUTDOWN")
at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:308)
at de.tudresden.inf.rn.intellix.tudix.HsqldbShutdownListener.contextDestroyed(HsqldbShutdownListener.java:45)
at org.glassfish.grizzly.servlet.ServletContextImpl.destroyListeners(ServletContextImpl.java:186)
at org.glassfish.grizzly.servlet.ServletHandler.destroy(ServletHandler.java:768)
at org.glassfish.grizzly.http.server.HttpHandlerChain.destroy(HttpHandlerChain.java:317)
at org.glassfish.grizzly.http.server.HttpServer.tearDownHttpHandler(HttpServer.java:303)
at org.glassfish.grizzly.http.server.HttpServer.stop(HttpServer.java:366)
at com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory$GrizzlyWebTestContainer.stop(GrizzlyWebTestContainerFactory.java:154)
at com.sun.jersey.test.framework.JerseyTest.tearDown(JerseyTest.java:316)
at de.tudresden.inf.rn.intellix.tudix.TudixInterfaceTest.tearDown(TudixInterfaceTest.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:622)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLNonTransientConnectionException: connection exception: closed
Error Code: -1353
Call: SHUTDOWN
Query: DataModifyQuery(sql="SHUTDOWN")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1611)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:674)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:271)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:251)
at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:298)
... 32 more
Caused by: java.sql.SQLNonTransientConnectionException: connection exception: closed
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:281)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1556)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1505)
at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:778)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:619)
... 47 more
Caused by: org.hsqldb.HsqlException: connection exception: closed
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
... 55 more

It seems that the database is already closed. But this is definitely not the case, as I see the data from the previous test in the next.

The database is defined as a Spring bean in application-context.xml as follows:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver">
    </property>
    <property name="url" value="jdbc:hsqldb:mem:db;sql.enforce_size=false;sql.enforce_strict_size=false"></property>
    <property name="username" value="sa"></property>
    <property name="password" value=""></property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="persistenceUnitName" value="PU" />
    <property name="jpaVendorAdapter">
        <bean
            class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="eclipselink.weaving" value="false" />
            <entry key="eclipselink.ddl-generation" value="create-tables" />
            <entry key="eclipselink.ddl-generation.output-mode" value="database" />
            <entry key="eclipselink.logging.level.sql" value="SEVERE" />
            <entry key="eclipselink.logging.parameters" value="false" />
        </map>
    </property>
</bean>

Here is a minimal example of one test case:

public final class TudixInterfaceTest extends JerseyTest {

@Override
protected AppDescriptor configure() {
    Map<String, String> initParams = new HashMap<String, String>();
    initParams.put("com.sun.jersey.config.property.packages", "my.resource.package");

    Builder builder = new WebAppDescriptor.Builder(initParams);
    return builder.initParam("application-context", "application-context.xml").contextPath("/").build();
}


@Test
public void test() {
    // Access REST interface, saving some stuff to the in memory database on server side.
    // Assert the result on client side.
}

Can someone tell me how to properly close the In-Memory HSQL database in such a scenario?

+3
source share

All Articles