Fork me on GitHub
Dropwizard EntityManager

An add-on module for the popular Dropwizard RESTful web service framework that provides managed access to Hibernate JPA, along with support for @UnitOfWork transactions.

This user guide is for version 0.9.2-1.   Javadoc is available, as are guides for other versions.


Getting Started

If you’re using Maven, simply add the dropwizard-entitymanager dependency to your POM:

<dependency>
  <groupId>com.scottescue</groupId>
  <artifactId>dropwizard-entitymanager</artifactId>
  <version>0.9.2-1</version>
</dependency>

Configuration

First, your configuration class needs a DataSourceFactory instance:

public class ExampleConfiguration extends Configuration {
    @Valid
    @NotNull
    private DataSourceFactory database = new DataSourceFactory();

    @JsonProperty("database")
    public DataSourceFactory getDataSourceFactory() {
        return database;
    }
}

Then, add an EntityManagerBundle instance to your application class, specifying your entity classes and how to get a DataSourceFactory from your configuration subclass:

private final EntityManagerBundle<ExampleConfiguration> entityManagerBundle = 
        new EntityManagerBundle<ExampleConfiguration>(Person.class) {
    @Override
    public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
        return configuration.getDataSourceFactory();
    }
};

@Override
public void initialize(Bootstrap<ExampleConfiguration> bootstrap) {
    bootstrap.addBundle(entityManagerBundle);
}

@Override
public void run(ExampleConfiguration config, Environment environment) {
    final EntityManager entityManager = entityManagerBundle.getSharedEntityManager();
    environment.jersey().register(new UserResource(entityManager));
}

If you don’t want to explicitly specify your entity classes, you can instead create a ScanningEntityManagerBundle instance specifying a package in your application to recursively scan for entity classes:

private final EntityManagerBundle<ExampleConfiguration> entityManagerBundle = 
        new ScanningEntityManagerBundle<ExampleConfiguration>("com.myapp") {
    @Override
    public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
        return configuration.getDataSourceFactory();
    }
};

Creating an instance of either type of bundle will create a new managed connection pool to the database, a health check for connectivity to the database, and a new EntityManagerFactory as well as a thread-safe EntityManager instance for you to use in your classes.

Usage

Container Managed Persistence for Resource Methods

The shared EntityManager obtained from your EntityManagerBundle works with the @UnitOfWork annotation.
The @UnitOfWork annotation may be applied to resource methods to create a container managed PersistenceContext. This gives you the ability to declaratively scope transaction boundaries.

@POST
@Timed
@UnitOfWork
public Response create(@Valid Person person) {
    entityManager.persist(checkNotNull(person));

    return Response.created(UriBuilder.fromResource(PersonResource.class)
            .build(person.getId()))
            .build();
}

This will automatically initialize the EntityManager, begin a transaction, call persist, commit the transaction, and finally close the EntityManager. If an exception is thrown, the transaction is rolled back.

Often you simply need to read data without requiring an actual transaction.

@GET
@Timed
@UnitOfWork(transactional = false)
public Person findPerson(@PathParam("id") LongParam id) {
    return entityManager.find(Person.class, id.get());
}

This will automatically initialize the EntityManager, call find, and finally close the EntityManager.

Container Managed Persistence Outside Jersey Resources

Currently creating transactions with the @UnitOfWork annotation works out-of-box only for resources managed by Jersey. If you want to use it outside Jersey resources, e.g. in services, you should instantiate your class with UnitOfWorkAwareProxyFactory. If you had a simple PersonService including a @UnitOfWork annotated method:

public class PersonService {
    private final EntityManager entityManager;
    
    public PersonService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    
    @UnitOfWork
    public void create(Person person) {
        entityManager.persist(person);
    }
}

You would create an instance of that service using a UnitOfWorkAwareProxyFactory:

UnitOfWorkAwareProxyFactory proxyFactory = new UnitOfWorkAwareProxyFactory(entityManagerBundle);

PersonService personService = proxyFactory.create(
        PersonService.class, 
        EntityManager.class, 
        entityManagerBundle.getSharedEntityManager());

This will create a proxy of your class, which will initialize the shared EntityManager around methods with the @UnitOfWork annotation. A transaction will also be created around annotated methods unless the annotation specifies otherwise.

Application Managed Persistence

There may be times when you need to have more control over the PersistenceContext or need to manage a new transaction. The EntityManagerFactory obtained from your EntityManagerBundle allows you to create and manage new EntityManager instances. Any EntityManager created from the factory will have a new PersistenceContext that must be managed by your application.

public void create(Person person) {
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = entityManager.getTransaction();
    try {
        transaction.begin();
        entityManager.persist(person);
        transaction.commit();
    } catch (RuntimeException e) {
        if (transaction.isActive()) {
            transaction.rollback();
        }
    } finally {
        entityManager.close();
    }
}

Prepended Comments

By default, dropwizard-entitymanager configures Hibernate JPA to prepend a comment describing the context of all queries:

/* load com.example.helloworld.core.Person */
select
    person0_.id as id0_0_,
    person0_.fullName as fullName0_0_,
    person0_.jobTitle as jobTitle0_0_
from people person0_
where person0_.id=?

This will allow you to quickly determine the origin of any slow or misbehaving queries. See the Database - autoCommentsEnabled attribute in the Dropwizard Configuration Reference

Support

Please file bug reports and feature requests in GitHub issues.

Credits

This module is heavily derived from Dropwizard Hibernate. Those who have contributed to Dropwizard Hibernate deserve much of the credit for this project. I’ve essentially adapted their work to create and expose the EntityManager and EntityManagerFactory objects.

Dropwizard is developed by Coda Hale; Yammer, Inc.; and the Dropwizard Team, licensed under the Apache 2.0 license.

License

Copyright 2015-2016 Scott Escue

This library is licensed under the Apache License, Version 2.0. See the project’s LICENSE file for the full license text.