Skip to content

Instantly share code, notes, and snippets.

@andref
Last active July 7, 2022 18:19
Show Gist options
  • Select an option

  • Save andref/9869a3c483b57eb8bf1f145740fe5c71 to your computer and use it in GitHub Desktop.

Select an option

Save andref/9869a3c483b57eb8bf1f145740fe5c71 to your computer and use it in GitHub Desktop.
Minimal example. Run with java -cp someClassPath Minimal server config.yaml
server:
applicationConnectors:
- type: http
port: 3000
adminConnectors:
- type: http
port: 3001
db:
driverClass: org.h2.Driver
url: jdbc:h2:${DB_URL}/mem:${DB_SCHEMA}
user:
password:
maxWaitForConnection: 1 second
checkConnectionWhileIdle: true
validationInterval: 30 seconds
validationQuery: select 1
logValidationErrors: true
checkConnectionOnBorrow: true
checkConnectionOnConnect: true
checkConnectionOnReturn: true
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.core.Application;
import io.dropwizard.core.Configuration;
import io.dropwizard.core.setup.Bootstrap;
import io.dropwizard.core.setup.Environment;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.db.PooledDataSourceFactory;
import io.dropwizard.hibernate.HibernateBundle;
import io.dropwizard.hibernate.UnitOfWork;
import io.dropwizard.lifecycle.Managed;
import org.apache.commons.text.StringSubstitutor;
import org.h2.jdbc.JdbcSQLNonTransientConnectionException;
import org.h2.tools.Server;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.PersistenceException;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import java.sql.SQLException;
import java.util.Map;
import static java.util.Map.entry;
public class Minimal {
public static void main(String[] args) throws Exception {
new App().run(args);
}
public static class App extends Application<Config> {
private final Server databaseServer;
HibernateBundle<Config> hibernateBundle = new HibernateBundle<>(SomeEntity.class) {
@Override
public PooledDataSourceFactory getDataSourceFactory(Config minimalConfig) {
return minimalConfig.db;
}
};
public App() throws SQLException {
this.databaseServer = Server.createTcpServer("-ifNotExists");
databaseServer.start();
}
@Override
public void initialize(Bootstrap<Config> bootstrap) {
var properties = Map.ofEntries(
entry("DB_URL", databaseServer.getURL()),
entry("DB_SCHEMA", "example")
);
bootstrap.setConfigurationSourceProvider(new SubstitutingSourceProvider(bootstrap.getConfigurationSourceProvider(),
new StringSubstitutor(
properties)));
bootstrap.addBundle(hibernateBundle);
}
@Override
public void run(Config minimalConfig, Environment environment) {
var resource = new Resource(databaseServer);
environment.jersey().register(resource);
var persistenceExceptionMapper = new PersistenceExceptionMapper();
environment.jersey().register(persistenceExceptionMapper);
// turn off the database when we quit.
environment.lifecycle().manage(new Managed() {
@Override
public void stop() {
databaseServer.stop();
}
});
}
}
static class Config extends Configuration {
public DataSourceFactory db = new DataSourceFactory();
}
@Path("db")
@Produces(MediaType.TEXT_PLAIN)
public static class Resource {
private final Server server;
public Resource(Server server) {
this.server = server;
}
@UnitOfWork
@GET
public Response useHibernateSession() {
return Response.ok("hello, world").build();
}
@POST
@Path("start")
public void startDatabase() throws SQLException {
server.start();
}
@POST
@Path("stop")
public void stopDatabase() {
server.stop();
}
}
static class PersistenceExceptionMapper implements ExceptionMapper<PersistenceException> {
@Override
public Response toResponse(PersistenceException exception) {
// When the H2 database is offline, the JDBC driver throws a
// JdbcSQLNonTransientConnectionException that we can use to respond with a 503 status, for
// instance.
if (dbSeemsToBeOffline(exception)) {
return Response
.status(Response.Status.SERVICE_UNAVAILABLE)
.entity(exception.getMessage())
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
.build();
}
return Response
.serverError()
.entity(exception.getLocalizedMessage())
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
.build();
}
private static boolean dbSeemsToBeOffline(Throwable t) {
var e = t;
while (e != null) {
if (e instanceof JdbcSQLNonTransientConnectionException) {
return true;
}
e = e.getCause();
}
return false;
}
}
@Entity
static class SomeEntity {
@Id
public Long id;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>minimal-example</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-dependencies</artifactId>
<version>3.0.0-beta.3</version>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-db</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-hibernate</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment