package io.dropwizard.hibernate;
import com.codahale.metrics.MetricRegistry;
import com.google.common.collect.ImmutableList;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.jackson.Jackson;
import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.jersey.errors.ErrorMessage;
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import io.dropwizard.jersey.optional.EmptyOptionalExceptionMapper;
import io.dropwizard.lifecycle.setup.LifecycleEnvironment;
import io.dropwizard.logging.BootstrapLogging;
import io.dropwizard.setup.Environment;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.After;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JerseyIntegrationTest extends JerseyTest {
static {
BootstrapLogging.bootstrap();
}
public static class PersonDAO extends AbstractDAO<Person> {
public PersonDAO(SessionFactory sessionFactory) {
super(sessionFactory);
}
public Optional<Person> findByName(String name) {
return Optional.ofNullable(get(name));
}
@Override
public Person persist(Person entity) {
return super.persist(entity);
}
}
@Path("/people/{name}")
@Produces(MediaType.APPLICATION_JSON)
public static class PersonResource {
private final PersonDAO dao;
public PersonResource(PersonDAO dao) {
this.dao = dao;
}
@GET
@UnitOfWork(readOnly = true)
public Optional<Person> find(@PathParam("name") String name) {
return dao.findByName(name);
}
@PUT
@UnitOfWork
public void save(Person person) {
dao.persist(person);
}
}
private SessionFactory sessionFactory;
@Override
@After
public void tearDown() throws Exception {
super.tearDown();
if (sessionFactory != null) {
sessionFactory.close();
}
}
@Override
protected Application configure() {
forceSet(TestProperties.CONTAINER_PORT, "0");
final MetricRegistry metricRegistry = new MetricRegistry();
final SessionFactoryFactory factory = new SessionFactoryFactory();
final DataSourceFactory dbConfig = new DataSourceFactory();
final HibernateBundle<?> bundle = mock(HibernateBundle.class);
final Environment environment = mock(Environment.class);
final LifecycleEnvironment lifecycleEnvironment = mock(LifecycleEnvironment.class);
when(environment.lifecycle()).thenReturn(lifecycleEnvironment);
when(environment.metrics()).thenReturn(metricRegistry);
dbConfig.setUrl("jdbc:hsqldb:mem:DbTest-" + System.nanoTime() + "?hsqldb.translate_dti_types=false");
dbConfig.setUser("sa");
dbConfig.setDriverClass("org.hsqldb.jdbcDriver");
dbConfig.setValidationQuery("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS");
this.sessionFactory = factory.build(bundle,
environment,
dbConfig,
ImmutableList.of(Person.class));
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.createNativeQuery("DROP TABLE people IF EXISTS").executeUpdate();
session.createNativeQuery(
"CREATE TABLE people (name varchar(100) primary key, email varchar(16), birthday timestamp with time zone)")
.executeUpdate();
session.createNativeQuery(
"INSERT INTO people VALUES ('Coda', 'coda@example.com', '1979-01-02 00:22:00+0:00')")
.executeUpdate();
transaction.commit();
}
final DropwizardResourceConfig config = DropwizardResourceConfig.forTesting(new MetricRegistry());
config.register(new UnitOfWorkApplicationListener("hr-db", sessionFactory));
config.register(new PersonResource(new PersonDAO(sessionFactory)));
config.register(new JacksonMessageBodyProvider(Jackson.newObjectMapper()));
config.register(new PersistenceExceptionMapper());
config.register(new DataExceptionMapper());
config.register(new EmptyOptionalExceptionMapper());
return config;
}
@Override
protected void configureClient(ClientConfig config) {
config.register(new JacksonMessageBodyProvider(Jackson.newObjectMapper()));
}
@Test
public void findsExistingData() throws Exception {
final Person coda = target("/people/Coda").request(MediaType.APPLICATION_JSON).get(Person.class);
assertThat(coda.getName())
.isEqualTo("Coda");
assertThat(coda.getEmail())
.isEqualTo("coda@example.com");
assertThat(coda.getBirthday())
.isEqualTo(new DateTime(1979, 1, 2, 0, 22, DateTimeZone.UTC));
}
@Test
public void doesNotFindMissingData() throws Exception {
try {
target("/people/Poof").request(MediaType.APPLICATION_JSON)
.get(Person.class);
failBecauseExceptionWasNotThrown(WebApplicationException.class);
} catch (WebApplicationException e) {
assertThat(e.getResponse().getStatus())
.isEqualTo(404);
}
}
@Test
public void createsNewData() throws Exception {
final Person person = new Person();
person.setName("Hank");
person.setEmail("hank@example.com");
person.setBirthday(new DateTime(1971, 3, 14, 19, 12, DateTimeZone.UTC));
target("/people/Hank").request().put(Entity.entity(person, MediaType.APPLICATION_JSON));
final Person hank = target("/people/Hank")
.request(MediaType.APPLICATION_JSON)
.get(Person.class);
assertThat(hank.getName())
.isEqualTo("Hank");
assertThat(hank.getEmail())
.isEqualTo("hank@example.com");
assertThat(hank.getBirthday())
.isEqualTo(person.getBirthday());
}
@Test
public void testSqlExceptionIsHandled() throws Exception {
final Person person = new Person();
person.setName("Jeff");
person.setEmail("jeff.hammersmith@targetprocessinc.com");
person.setBirthday(new DateTime(1984, 2, 11, 0, 0, DateTimeZone.UTC));
final Response response = target("/people/Jeff").request().
put(Entity.entity(person, MediaType.APPLICATION_JSON));
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.BAD_REQUEST);
assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_JSON);
assertThat(response.readEntity(ErrorMessage.class).getMessage()).isEqualTo("Wrong email");
}
}