Dropwizard and Friends
On a Twelve-factor Quest
Sydney MicroServices Meetup April 2015
About Me
- Comp Science Bachelor UNSW
- Applied Finance PostGrad at Macquarie Uni
- ESB driver at Accenture, BGI/BlackRock, Macquarie Group
- Now Microservicing Trunk Platform

yunspace
yunzhilin

yunspace.com
- My opinions does not reflect the view of the company
- Shout out if you have questions, or answers

Why
Demo
Decisions
CD + Docker
Why Dropwizard?
Standalone App
public static void main(String[] args) throws Exception {
new LazyCatApplication().run(args);
}
java -jar build/awesome_api.jar server awesome_api.yml
No War Files, No App Servers
Builds and runs a Fat Jar
Start Application in a simple Main() method
Because:
and you should
Who Uses Dropwizard?
- Sky - Fault Tolerant Microservices
- Datasift - dropwizard extra, scala, zeromq
- HubSpot - dropwizard-guice
- Gilt - Production Ready Web Services with Dropwizard
- airbnb - Introducing Airpal
- Riot Games - How we built a Cloud Platform at Riot Games using NetflixOSS
- Bloom Health - Micro-services with Dropwizard
Surely Java without App Server is unstable?
Production Ready



- Ops Friend
- Health Checks
- Metrix
More so than most Enterprise Apps
Plays Well with Others
-
More Modules at http://modules.dropwizard.io/





Easy to do the Right Thing
Dropwizard makes it easy to do the right thing, allowing you to concentrate on the essential complexity of a problem rather than the plumbing
We agree
High
Performance
techempower.com/benchmarks/
Low
Latency
techempower.com/benchmarks/
Compared to Rails

Dropping Rails for Dropwizard? - Yammer, April 2014
Compared Spring Boot

Java BootStrap: Dropwizard vs SprintBoot - Takipi Blog
Compared to RatPack
public class FooBarFactory implements HandlerFactory {
@Override
public Handler create(LaunchConfig launchConfig) throws Exception {
return Guice.builder(launchConfig)
.bindings(bindingsSpec -> bindingsSpec.add(new MyModule()))
.build(chain -> chain
.handler("foo", context -> context.render("from the foo handler"))
.handler("bar", context -> context.render("from the bar handler")));
}
}
public class FooBarApplication extends Application<FooBarConfig> {
public static void main(String[] args) throws Exception {
new FooBarApplication().run(args);
}
@Override
public void run(final FooBarApplication configuration, final Environment environment) throws Exception {
environment.register(FooResource.class);
environment.register(BarResrouce.class);
}
}
@Path("/foo")
@Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON)
public class FooResource {
@GET
public String getFoo() {
return "from the foo handler";
}
}
- Dropwizard is more opinionated and explicit
Right Tool for the Right Job
- Not a silver bullet
- We also use Rails to leverage neat Gems
- And AngularJs on HarpJs for Static Sites
Build another "Hello World" App?

Demo
Let's build a Dropwizard Turbo app using LazyBones!

12 Factors

Design Decisions
Iron Fisted
Gradle
Declare and isolate Dependencies (II)
Portable "gradlew" is great for CI & locks gradle version
More than just Dependency Management:
- builds shadow
Configuration
java \
-Ddw.dataSource.driverClass=$DATABASE_DRIVER -Ddw.dataSource.url=$DATABASE_URL \
-Ddw.dataSource.user=$DATABASE_USER -Ddw.dataSource.password=$DATABASE_PASSWORD \
-jar build/application.jar server config.yml
1. Replace config.yml variables in run command (messy):
- Configuration using Environment Variables (III)
- Attach Backing Services (IV) with no code change
dataSource:
driverClass: ${env.HIBERNATE_DRIVER!'org.h2.Driver'}
user: ${env.HIBERNATE_USER!'sa'}
password: ${env.HIBERNATE_PASSWORD!'sa'}
url: ${env.HIBERNATE_URL!'jdbc:h2:./build/h2db'}
2. Use Dropwizard-Template-Config to add ${env} in config.yml:
java -jar build/application.jar server config.yml
Modules
- Dropwizard version 0.8.0: Jersey2 major update.
- github.com/dropwizard/dropwizard-java8
- github.com/hubspot/dropwizard-guice
- We are active contributors, get in contact if you have any issues
Used by lazybones-dropwizard-turbo

Swagger.IO
Integration using our own code
New Relic
- Gist: NewRelicTimedApplicationListener
- Register above listener, add newrelic.jar

Dockerfile
FROM errordeveloper/oracle-jre
ENV HOME /root/
WORKDIR /app/
# newrelic
RUN curl -L --silent --retry 3 \
https://download.newrelic.com/newrelic/java-agent/newrelic-agent/current/newrelic-java.zip -o newrelic-java.zip
RUN unzip newrelic-java.zip && \
rm newrelic/*.xml newrelic/*.xsd newrelic/*.yml newrelic/newrelic-api*.jar
ADD newrelic/newrelic.yml /app/newrelic/newrelic.yml
# plamasphere
ADD platmasphere-services.yml /app/
ENV PLATMA_VERSION latest
ADD build/platmasphere-services.jar /app/platmasphere-services.jar
# run
EXPOSE 9090
ENTRYPOINT [ "java" ]
CMD ["-javaagent:newrelic/newrelic.jar", "-jar", "platmasphere-services.jar", "server", "platmasphere-services.yml"]
Tips
- Joda DateTime is NOT equivalent to JSR-310 LocalDateTime. Use ZonedDateTime or OffsetDateTime
compile "org.jadira.usertype:usertype.extended:3.2.0.GA"
- Use Governator @LazySingleton if you have issue with Guice eager @Singleton
compile("com.netflix.governator:governator:${governatorVersion}") {
exclude group: 'com.google.guava', module: 'guava'
exclude group: 'commons-lang'
}
- Multiple Database Schema Support: have a look here
- Jadira UserType Extended for Hibernate JSR-310 support
Continuous Delivery
+
Docker
Snap-CI
Continuous Delivery enables:
- Strictly Separate Build, Release, Run (V)
- Reduced Dev/prod parity (X)
Pact Contract
{
"description": "request for getting property 80 CLARENCE ST",
"provider_state": "property 80 CLARENCE ST exists",
"request": {
"method": "get",
"path": "/properties/1",
"headers": {
"Tenant": "trunk",
"Authorization": "Bearer valid_token"
}
},
"response": {
"status": 200,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "origin, content-type, accept, authorization, tenant",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, HEAD",
"Access-Control-Max-Age": "43200"
},
"body": {
"id": 1,
"addressLine": "80 CLARENCE ST",
"postcode": "2000",
"state": "NSW",
"suburb": "SYDNEY",
"streamId": 1
}
}
}
BinTray and Quay.io


- Small Base Image = quicker build time
- Use errordeveloper/oracle-jre (busybox based)
- Only 159 mb
Build Docker Images

Database Migration
Prior to deploying to a Environment, we run DB Migration as Once off Admin Processes (XII)
./gradlew dbMigrate -Pdb_schema=
./gradlew dbTag -Pdb_schema=
Deploy Docker Container
- Isolation of Stateless Processes (VI) and Port binding (VII)
- Containers are Disposable(IX) and Concurrent(VIII)
- Stream Logs (XI) to LogSpout
Docker Containers takes care of:
Running Containers in Tutum

Questions
Like us on GitHub!
Dropwizard and Friends
By Yun Zhi Lin
Dropwizard and Friends
On a Twelve Factor Quest - Microservices MeetUp April 2015
- 7,725