Dropwizard-Hibernate Transaction handling for Integration Tests

1.7k Views Asked by At

my dropwizard application has a integration test where i use a hibernate h2 database for storing data. For the second part of the test i am using jersey-testframework to handle resources and rest calls.

In order to make these two parts work together i had to create a TestRule for each case.

Hibernate:

@ClassRule
public static final SessionFactoryRule sessionFactoryRule = new SessionFactoryRule(User.class, HibernateUtil.getHibernateClasses());
public static final ProgramDAO programDao =  new ProgramDAO(sessionFactoryRule.getSessionFactory());

Jersey:

@ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
        .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
        .addProvider(new AuthDynamicFeature(
                new OAuthCredentialAuthFilter.Builder<User>()
                        .setAuthenticator(new OAuthAuthenticator(userManagement))
                        .setAuthorizer(new OAuthAuthorizer())
                        .setPrefix(TOKEN_TYPE)
                        .buildAuthFilter()))
        .addProvider(new AuthValueFactoryProvider.Binder<>(User.class))
        .addProvider(RolesAllowedDynamicFeature.class)
        .addResource(new AdResource(urlMapperMock, programDao))
        .build();

The h2 hibernate db configuration

    Configuration configuration = new Configuration()
            .setInterceptor(new SoftDeleteInterceptor())
            .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
            .setProperty("hibernate.connection.driver_class", "org.h2.Driver")
            .setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
            .setProperty("hibernate.hbm2ddl.auto", "create")
            .setProperty("hibernate.default_batch_fetch_size", "200")
            .setProperty("hibernate.show_sql", "false")
            .setProperty("hibernate.current_session_context_class", "thread");

Now when i call a request on the resource ...

@Test
public void resourceCheck() {
    javax.ws.rs.core.Response response = resources.getJerseyTest().target(Ad.TABLE_NAME).request().header(HEADER_KEY_AUTHORIZATION, HEADER_VALUE_VALID_BEARER_TOKEN).get();
    assertThat(response.getStatus()).isEqualTo(200);
}

... the following error is thrown

ERROR [2016-01-26 11:23:21,594] org.glassfish.grizzly.servlet.ServletHandler: service exception:
! org.hibernate.HibernateException: getNamedQuery is not valid without active transaction
! at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
! at com.sun.proxy.$Proxy74.getNamedQuery(Unknown Source) ~[na:na]
! at io.dropwizard.hibernate.AbstractDAO.namedQuery(AbstractDAO.java:57) ~[dropwizard-hibernate-0.9.1.jar:0.9.1]
! at com.ad4mat.api.db.core.AdDAO.findAllByUser(AdDAO.java:36) ~[classes/:na]
! at com.ad4mat.api.resource.AdResource.getAll(AdResource.java:79) ~[classes/:na]

Apparently there is no transaction handling for the testcase but there should be one.

My normal dropwizard application is working fine. The transactions are handled by notating the resources with @UnitOfWork.

When i add a manuel transaction in the dao like ...

public List<Ad> findAllByUser(User user) {
    currentSession().beginTransaction();
    Query query = namedQuery("ad.findAllByUser")
                      .setParameter(User.FOREIGN_COLUMN_ID, user.getId());
    return query.list();

the integration test works, but my application will throw a nested transaction exception.

So my Question is:

How do make the @UnitOfWork annotation available for the integration test process. Clearly there is a transaction handling implementation missing. Do i have to jersey.register() a certain component of Dropwizard-Hibernate?

1

There are 1 best solutions below

0
On BEST ANSWER

As of dropwizard version 0.9.2 it is possible to use the @UnitOfWork annotation outside of Jersey contexts. Maybe a dropwizard update is what you are looking for; then you should be able to do database stuff from within any context (most important from a junit/testng context). http://www.dropwizard.io/0.9.2/docs/about/release-notes.html