12 Factor
App
Best Practices for Java
Deployment
You might not like what I have to say
Modern Java
Deployment
.war
Traditional Java Deployment
.jar
Modern Java Deployment
Make JAR
Not WAR
2005 2015
WAR files JAR files
App Servers Microservices
Hot Deploy Continuous Deploy
Server in a closet Heroku/AWS/etc
Joe Kutner
@codefinger
JVM Platform Owner
12 Factor App
a methodology
Scalability
Maintainability
Portability
Immutable
Ephemeral
Declarative
Automated
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Use version
control
BAD
BAD
App #1 App #2
pom.xml
<project>
...
<modules>
<module>my-app</module>
<module>my-other-app</module>
</modules>
<project>
Submodules
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Never rely on implicit
existence of system-wide
packages
Explicitly declare
and isolate
dependencies
Don’t check
JAR files
into Git
https://bintray.com/
Agent JARs
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-new-relic</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>com.newrelic.agent.java</includeGroupIds>
<includeArtifactIds>newrelic-agent</includeArtifactIds>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
build.gradle
task copyToLib(type: Copy) {
into "$buildDir/server"
from(configurations.compile) {
include "jetty-runner*"
}
}
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
• Resource handles to the database,
memcached, and other backing services
• Credentials to external services such as
Amazon S3 or Twitter
• Per-deploy values such as the canonical
hostname for the deploy
Anything that changes between
deployment environments:
(does not include things like conf/routes)
Configuration is…
Configuration should
be strictly separated
from code
Don’t check
passwords
into Git
Configuration belongs
in the environment,
not in the application
applicationContext.xml
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
id=“dataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value=“${JDBC_DATABASE_URL}"/>
// ...
application.conf
db.default.url=${DATABASE_URL}
Can you make your app open source at
any moment, without compromising
any credentials?
Litmus Test
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
application.conf
db.default.url=${DATABASE_URL}
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
build, release, run
$ mvn clean install
$ sbt stage
$ ./gradlew build
build
$ heroku deploy:jar -j myapp.war
$ mvn heroku:deploy
$ docker push ...
release
$ java -jar myapp.war
$ build/install/myapp/bin/myapp.bat
run
$ mvn jetty:run
$ service tomcat start
$ cp myapp.war TOMCAT_HOME/webapps/
$ git push heroku master
build,
release,
& run
DemoTime
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Processes
should be
stateless
sticky sessions
😞
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
The twelve-factor app
is completely self-contained
The web app exports HTTP
as a service by binding to a port
.war
Traditional Deployment
.jar
Modern Deployment
Dropwizard
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Relax bro, I got this…
java.util.concurrent
RxJava
java.util.stream
Scale Up
Scale Out
web.1
web.2
worker.1 clock.1
Workload Diversity
NumberofProcesses
worker.2
worker.3
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Graceful shutdown
Quick startup
Resilience to failure
Servers are not pets
Servers are cattle
Application Servers
are pets
Application Servers
are not
disposable
Microservices are
cattle
Microservices are
disposable
Easy to replace
Decoupled from
external infrastructure
Easy to modify
Microservices
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
dev stage prod= =
dev
sqlite
stage
mysql
prod
postgres
=
≠
=
≠
dev
sqlite
postgres
stage
mysql
postgres
prod
postgres
postgres
=
≠
=
=
≠
=
dev
tomcat
jetty
stage
tomcat
jetty
prod
jboss
jetty
=
≠
=
=
≠
=
.jar
disposability
reproducibility
parity
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
Admin tasks
should be run
in isolated processes
$ heroku run bash
Running `bash` attached to terminal... up, run.1594
~ $
web1
web2
web3
admin
• Codebase
• Dependencies
• Config
• Backing services
• Build, release, run
• Processes
• Port Binding
• Concurrency
• Disposability
• Dev/Prod Parity
• Logs
• Admin Processes
12 Factor App
http://12factor.net
http://jkutner.github.io
Create a bintray.com account1.
set JDBC_DATABASE_URL=jdbc:postgres://…2.
Measure your app’s boot time3.
Click a Heroku button4.
What next?
https://github.com/britter/spring-boot-heroku-demo
Joe Kutner
@codefinger
JVM Platform Owner
(http://www.slideshare.net/jkutner/javaone-2015-12-factor-app)
http://bit.ly/1PSRxcm

JavaOne 2015: 12 Factor App