AWS Developer Tools Blog

Deploying Java Applications on Elastic Beanstalk from Maven

The Beanstalker open source project now supports Java SE application development and deployment directly to AWS Elastic Beanstalk using the Maven archetype elasticbeanstalk-javase-archetype. With just a few commands in a terminal, you can create and deploy a Java SE application. This blog post provides step-by-step instructions for using this archetype.

First, in the terminal, type the mvn archetype:generate command. Use elasticbeanstalk as the filter, choose elasticbeanstalk-javase-archetype as the target archetype, and set the required properties when prompted. This screenshot shows the execution of this command.

$ mvn archetype:generate -Dfilter=elasticbeanstalk
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> maven-archetype-plugin:2.3:generate (default-cli) >
 generate-sources @ standalone-pom >>>
[INFO] 
[INFO] <<< maven-archetype-plugin:2.3:generate (default-cli) <
 generate-sources @ standalone-pom <<<
[INFO] 
[INFO] --- maven-archetype-plugin:2.3:generate (default-cli) @
 standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart
 (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> 
br.com.ingenieux:elasticbeanstalk-docker-dropwizard-webapp-archetype
 (A Maven Archetype for Publishing Dropwizard-based Services on AWS'
 Elastic Beanstalk Service)
2: remote -> 
br.com.ingenieux:elasticbeanstalk-javase-archetype
 (A Maven Archetype Encompassing Jetty for Publishing Java SE
 Services on AWS' Elastic Beanstalk Service)
3: remote -> 
br.com.ingenieux:elasticbeanstalk-service-webapp-archetype
 (A Maven Archetype Encompassing RestAssured, Jetty, Jackson, Guice
 and Jersey for Publishing JAX-RS-based Services on AWS' Elastic
 Beanstalk Service)
4: remote -> 
br.com.ingenieux:elasticbeanstalk-wrapper-webapp-archetype
 (A Maven Archetype Wrapping Existing war files on AWS' Elastic
 Beanstalk Service)
Choose a number or apply filter
 (format: [groupId:]artifactId, case sensitive contains): : 2
Choose br.com.ingenieux:elasticbeanstalk-javase-archetype version: 
1: 1.4.3-SNAPSHOT
2: 1.4.3-foralula
Choose a number: 2: 1
Define value for property 'groupId': : org.demo.foo
Define value for property 'artifactId': : jettyjavase
Define value for property 'version':  1.0-SNAPSHOT: : 
Define value for property 'package':  org.demo.foo: : 
Confirm properties configuration:
groupId: org.demo.foo
artifactId: jettyjavase
version: 1.0-SNAPSHOT
package: org.demo.foo
 Y: : 
[INFO] ------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype:
 elasticbeanstalk-javase-archetype:1.4.3-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.demo.foo
[INFO] Parameter: artifactId, Value: jettyjavase
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: org.demo.foo
[INFO] Parameter: packageInPathFormat, Value: org/demo/foo
[INFO] Parameter: package, Value: org.demo.foo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: org.demo.foo
[INFO] Parameter: artifactId, Value: jettyjavase
[INFO] project created from Archetype in dir: /current/directory/jettyjavase
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24:07 min
[INFO] Finished at: 2016-02-19T09:53:54+08:00
[INFO] Final Memory: 14M/211M
[INFO] ------------------------------------------------------------------------

A new folder, jettyjavase, will be created under your current working directory. If you go to this folder and use the tree command to explore the structure, you will see the following:

$ tree
.
├── Procfile
├── pom.xml
└── src
    └── main
        ├── assembly
        │   └── zip.xml
        ├── java
        │   └── org
        │       └── demo
        │           └── foo
        │               └── Application.java
        └── resources
            └── index.html

8 directories, 5 files

The archetype uses java-se-jetty-maven, the sample project provisioned by AWS Elastic Beanstalk, as the template. This sample project generates a single executable jar file. Instructions that tell the server how to run the jar file are included in the Procfile.

As described here, there are basically three ways to deploy a Java SE application to AWS Elastic Beanstalk:

  • deploying a single executable jar.
  • deploying a single zip source bundle file that contains multiple jars and a Procfile.
  • deploying a single zip source bundle file that contains the source code, as-is, and a Buildfile.

This archetype supports the second option only. Before you deploy this sample project to Elastic Beanstalk, you might want to check the default configurations are what you want. You’ll find the default configurations in the <properties> section of the pom.xml file. 

  • beanstalk.s3Bucket and beanstalk.s3Key properties. The default Amazon S3 bucket used to store the zip source bundle file is configured as ${project.groupId}(in this case, for example, org.demo.foo). If you don’t have this bucket available in your S3 account, use the AWS CLI to create one, as shown here. You can also replace the default setting of beanstalk.s3Bucket to your preferred bucket. You must have permission to upload to the specified bucket.

    $ aws s3 mb s3://org.demo.foo
    make_bucket: s3://org.demo.foo/
    
  • mainApplication property. This is the application entry used to generate the executable jar file.
  • beanstalk.mainJar property. This is the main application compiled from your project and configured in the Procfile on the first row.
  • beanstalk.sourceBundle property. This is the final zip source bundle file. This property should not be changed because it is derived from the mavan-assembly-plugin file-naming logic.
  • beanstalk.artifactFile property. This is the target artifact file to be uploaded to S3 bucket.
  • beanstalk.solutionStack property. This is the solution stack used by the Java SE platform. You can change the default value, but make sure it is one of the supported solution stacks.
  • beanstalk.environmentName property. This is the name of the environment to which your application will be deployed. The default value is the artifact ID.
  • beanstalk.cnamePrefix property. The default value for the CNAME prefix is the artifact ID. Reconfigure it if the default value is already in use.

This archetype uses the maven-assembly-plugin to create the uber jar file and the zip source bundle file. Go to src/main/assembly/zip.xml and make changes, as necessary, for files you want to include or exclude from the zip source bundle file. Update the Procfile if you want to run multiple applications on the server. Make sure the first line in the file starts with “web: “.

After you have finished the configuration, you are ready to deploy the sample project to AWS Elastic Beanstalk. One single command, mvn -Ps3-deploy package deploy, will do the rest of work. If the sample project is deployed successfully, you will be able to access the http://jettyjavase.us-east-1.elasticbeanstalk.com/ endpoint and should see the Congratulations page. The following are the excerpts from the command output.

$ mvn -Ps3-deploy package deploy
[INFO] Scanning for projects...
...
[INFO] --- maven-assembly-plugin:2.2-beta-5:single (package-jar) @
 jettyjavase ---
...
[WARNING] Replacing pre-existing project main-artifact file:
 /current/directory/jettyjavase/target/jettyjavase-1.0-SNAPSHOT.jar
with assembly file:
 /current/directory/jettyjavase/target/jettyjavase-1.0-SNAPSHOT.jar
...
[INFO] --- maven-assembly-plugin:2.2-beta-5:single (package-zip) @
 jettyjavase ---
[INFO] Reading assembly descriptor: src/main/assembly/zip.xml
[INFO] Building zip:
 /current/directory/jettyjavase/target/jettyjavase-1.0-SNAPSHOT.zip
...
[INFO] --- beanstalk-maven-plugin:1.4.2:upload-source-bundle (deploy) @
 jettyjavase ---
[INFO] Target Path:
 s3://org.demo.foo/jettyjavase-1.0-SNAPSHOT-20160219040404.zip
[INFO] Uploading artifact file:
 /current/directory/jettyjavase/target/jettyjavase-1.0-SNAPSHOT.zip
  100.00% 945 KiB/945 KiB                        Done
[INFO] Artifact Uploaded
[INFO] SUCCESS
[INFO] null/void result
[INFO] 
[INFO] --- beanstalk-maven-plugin:1.4.2:create-application-version (deploy) @
 jettyjavase ---
[INFO] SUCCESS
[INFO] {
[INFO]   "applicationName" : "jettyjavase",
[INFO]   "description" : "Update from beanstalk-maven-plugin",
[INFO]   "versionLabel" : "20160219040404",
[INFO]   "sourceBundle" : {
[INFO]     "s3Bucket" : "org.demo.foo",
[INFO]     "s3Key" : "jettyjavase-1.0-SNAPSHOT-20160219040404.zip"
[INFO]   },
[INFO]   "dateCreated" : 1455854658750,
[INFO]   "dateUpdated" : 1455854658750
[INFO] }
[INFO] 
[INFO] --- beanstalk-maven-plugin:1.4.2:put-environment (deploy) @
 jettyjavase ---
[INFO] ... with cname set to 'jettyjavase.elasticbeanstalk.com'
[INFO] ... with status *NOT* set to 'Terminated'
[INFO] Environment Lookup
[INFO] ... with environmentId equal to 'e-pa2mn9iqkw'
[INFO] ... with status   set to 'Ready'
[INFO] ... with health equal to 'Green'
...
[INFO] SUCCESS
[INFO] {
[INFO]   "environmentName" : "jettyjavase",
[INFO]   "environmentId" : "e-pa2mn9iqkw",
[INFO]   "applicationName" : "jettyjavase",
[INFO]   "versionLabel" : "20160219040404",
[INFO]   "solutionStackName" : "64bit Amazon Linux 2015.09 v2.0.4 running Java 7",
[INFO]   "description" : "Java Sample Jetty App",
[INFO]   "dateCreated" : 1455854662359,
[INFO]   "dateUpdated" : 1455854662359,
[INFO]   "status" : "Launching",
[INFO]   "health" : "Grey",
[INFO]   "tier" : {
[INFO]     "name" : "WebServer",
[INFO]     "type" : "Standard",
[INFO]     "version" : " "
[INFO]   },
[INFO]   "cname" : "jettyjavase.us-east-1.elasticbeanstalk.com"
[INFO] }
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 05:14 min
[INFO] Finished at: 2016-02-19T12:09:19+08:00
[INFO] Final Memory: 26M/229M
[INFO] ------------------------------------------------------------------------

As you can see from the output and the pom.xml file, the s3-deploy profile consecutively executs three mojo commands, upload-source-bundle, create-application-version, and put-environment.

We welcome your feedback on the use of this Maven archetype. We want to add more features and continuously improve the user experience.