Dropwizard is fast becoming the weapon of choice for deploying performant RESTful web services on the JVM platform. Snap makes it a breeze to fast track your Dropwizard services to Heroku with complete deployment pipelines.
For the purpose of this blog I have created a sample dropwizard service, appropriately titled dropwizard-snapci-sample. It's a simple microblogging service API with two resources, User and MicroBlog. It speaks to Postgresql using the light jdbi library with Liquibase database migrations. The sample service is covered by unit tests and one end to end integration test. To get started, fork this sample service to your GitHub account.
When you setup this repository in Snap for the first time, it will detect that it's a Maven project and create a single stage pipeline for you with an empty mvn
command. Simply replace mvn
with mvn package
to run the unit tests and create our deployable microblog jar.
We're almost done with our first stage. Only exporting the build artifacts remain. Propagating build artifacts through the pipeline is an essential component of a deployment pipeline. It ensures that the deployable artifact remains unchanged throughout the pipeline. Essentially we ensure that what we test and build against is what we deploy.
Exporting an artifact is easy. Simply click on the artifacts tab and add a new artifact with the target
directory. Snap will ensure that the target
directory is available in all subsequent stages.
Ensuring that the service works with a real database and web server is vital to a reliable deployment pipeline. Up until now, our unit tests were mocking out database calls and we had no need to connect to a database server. However our integration tests require a database. Thus we need to tweak our Dropwizard service to connect to a Snap's Postgresql server.
Snap follows Heroku's convention of injecting a DATABASE_URL
environment variable into each stage's execution environment. If you've not read it already it's highly recommended to check out the Heroku dev center article, Connecting to Relational Databases on Heroku with Java. Briefly the DATABASE_URL
is formatted like this [database type]://[username]:[password]@[host]:[port]/[database name]
.
Our sample service is already setup to leverage the DATABASE_URL
environment variable. The code to do this is located in MicroBlogDatabaseConfiguration.java. Here's the meat of it:
public class MicroBlogDatabaseConfiguration {
final static Logger logger = LoggerFactory.getLogger(MicroBlogDatabaseConfiguration.class);
public static DatabaseConfiguration create(String databaseUrl) {
if (databaseUrl == null) {
throw new IllegalArgumentException("The DATABASE_URL environment variable must be set before running the app " +
"example: DATABASE_URL=\"postgres://sahilm:sahilm@localhost:5432/microblog\"");
}
DatabaseConfiguration databaseConfiguration = null;
try {
URI dbUri = new URI(databaseUrl);
String user = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String url = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath();
databaseConfiguration = new DatabaseConfiguration();
databaseConfiguration.setUser(user);
databaseConfiguration.setPassword(password);
databaseConfiguration.setUrl(url);
databaseConfiguration.setDriverClass("org.postgresql.Driver");
} catch (URISyntaxException e) {
logger.info(e.getMessage());
}
return databaseConfiguration;
}
}
Next, setting up the actual stage is easy. Here's what you do:
- Select Postgresql from the database dropdown.
- Create a new stage by clicking on Add new stage.
- Select custom stage.
java -jar target/microblog-0.0.1-SNAPSHOT.jar db migrate microblog.yml
runs the database migrations.java -jar target/microblog-0.0.1-SNAPSHOT.jar server microblog.yml &>log &
starts Jetty.mvn failsafe:integration-test failsafe:verify
runs our integration tests.
The target
directory already contains our build artifact which was propagated by Snap from the previous stage.
Deploying to Heroku is the easiest part. All we need to ensure is that the web
task in our Procfile runs our database migrations and starts up Jetty. Here's how it looks:
web: java $JAVA_OPTS -jar target/microblog*.jar db migrate microblog.yml && java $JAVA_OPTS -Ddw.http.port=$PORT -Ddw.http.adminPort=$PORT -jar target/microblog*.jar server microblog.yml
To setup the stage:
- Create a new stage by click on Add new stage.
- Select Heroku deployment. If this your first time deploying to Heroku using Snap you will be asked to login via Heroku.
- Fill in your desired app name.
- Select auto deploy if you wish to deploy each commit to Heroku.
- And you're done!
That's all there's to it. We've setup a complete deployment pipeline for our Dropwizard service. Snap will track all subsequent commits to this repository and deploy all green builds to Heroku.
)