Continuous Delivery of Microservices using Dropwizard, Developer Cloud and Application Container Cloud

I recently came across Dropwizard, which just reached their 1.0.0 release milestone (congratulations). Dropwizard has assembled popular Java libraries such as Jetty, Jersey and Jackson to create a framework for developing RESTful web services.

A Java framework like Dropwizard is ideally suited for a runtime environment like Oracle’s Application Container Cloud Service (ACCS). ACCS provisions Java SE (or Node.js) environments as required, on demand.

Additionally, we can use Oracle Developer Cloud Service, an integrated DevOps platform, to automate deployment.

In this tutorial I will cover the steps necessary to package and deploy a Dropwizard application to the Application Container Cloud Service. This will be achieved in an automated fashion using the Developer Cloud Service.

Since the focus isn’t on the application but on the process, I selected to use the Dropwizard Getting Started application.

Step 1: Create the Dropwizard Application

Follow the steps in the Getting Started guide to create the HelloWorld application. Or feel free to use your own Dropwizard application. I’ll review the high-level steps here.

Generate the application. My inputs are highlighted in bold:

C:\mvnProjects>mvn archetype:generate 
-DarchetypeGroupId=io.dropwizard.archetypes 
-DarchetypeArtifactId=java-simple -DarchetypeVersion=1.0.0
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository not defined. Using the one from [io.dropwizard.archetypes:java-simple:1.0.0] found in catalog remote
Define value for property 'groupId': : com.example.helloworld
Define value for property 'artifactId': : HelloWorld
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  com.example.helloworld: :
[INFO] Using property: description = null
Define value for property 'name': : HelloWorld
[INFO] Using property: shaded = true
Confirm properties configuration:
groupId: com.example.helloworld
artifactId: HelloWorld
version: 1.0-SNAPSHOT
package: com.example.helloworld
description: null
name: HelloWorld
shaded: true
 Y: : Y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: java-simple:1.0.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example.helloworld
[INFO] Parameter: artifactId, Value: HelloWorld
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example.helloworld
[INFO] Parameter: packageInPathFormat, Value: com/example/helloworld
[INFO] Parameter: package, Value: com.example.helloworld
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: name, Value: HelloWorld
[INFO] Parameter: groupId, Value: com.example.helloworld
[INFO] Parameter: description, Value: null
[INFO] Parameter: shaded, Value: true
[INFO] Parameter: artifactId, Value: HelloWorld
[INFO] project created from Archetype in dir: C:\mvnProjects\HelloWorld
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:25 min
[INFO] Finished at: 2016-08-04T11:09:23-04:00
[INFO] Final Memory: 14M/293M
[INFO] ------------------------------------------------------------------------
C:\mvnProjects>

Use Eclipse (or your favorite IDE) to import an existing Maven project.

Complete the steps as outlined in the Dropwizard Getting Started Guide.

If using Eclipse, right-click the project and select Run As > Maven Build…. Set the goal to package and click Run:

dw10-package

Test Locally

This is still part of the Dropwizard Getting Started exercise. This information we need here is the Java command to start the server. We will use this same exact command string later when we instruct the Application Container Cloud to run our server.

C:\mvnProjects\HelloWorld>java -jar target/HelloWorld-1.0-SNAPSHOT.jar server 
hello-world.yml
INFO  [2016-08-04 15:46:48,845] org.eclipse.jetty.util.log: Logging initialized @929ms
INFO  [2016-08-04 15:46:48,896] io.dropwizard.server.DefaultServerFactory: Registering jersey handler with root path prefix: /
INFO  [2016-08-04 15:46:48,896] io.dropwizard.server.DefaultServerFactory: Registering admin handler with root path prefix: /
INFO  [2016-08-04 15:46:48,899] io.dropwizard.server.DefaultServerFactory: Registering jersey handler with root path prefix: /
INFO  [2016-08-04 15:46:48,899] io.dropwizard.server.DefaultServerFactory: Registering admin handler with root path prefix: /
INFO  [2016-08-04 15:46:48,903] io.dropwizard.server.ServerFactory: Starting hello-world
================================================================================

                              HelloWorld

================================================================================


INFO  [2016-08-04 15:46:48,974] org.eclipse.jetty.setuid.SetUIDListener: Opened application@470a696f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
INFO  [2016-08-04 15:46:48,977] org.eclipse.jetty.setuid.SetUIDListener: Opened admin@1bc715b8{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
INFO  [2016-08-04 15:46:48,978] org.eclipse.jetty.server.Server: jetty-9.3.z-SNAPSHOT
INFO  [2016-08-04 15:46:49,400] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:

    GET     /hello-world (com.example.helloworld.resources.HelloWorldResource)

INFO  [2016-08-04 15:46:49,401] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@f72203{/,null,AVAILABLE}
INFO  [2016-08-04 15:46:49,404] io.dropwizard.setup.AdminEnvironment: tasks =

    POST    /tasks/log-level (io.dropwizard.servlets.tasks.LogConfigurationTask)
    POST    /tasks/gc (io.dropwizard.servlets.tasks.GarbageCollectionTask)

INFO  [2016-08-04 15:46:49,409] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@4a5905d9{/,null,AVAILABLE}
INFO  [2016-08-04 15:46:49,440] org.eclipse.jetty.server.AbstractConnector: Started application@470a696f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
INFO  [2016-08-04 15:46:49,453] org.eclipse.jetty.server.AbstractConnector: Started admin@1bc715b8{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
INFO  [2016-08-04 15:46:49,453] org.eclipse.jetty.server.Server: Started @1538ms

Configure for Deployment to ACCS

manifest.json

At a minimum, we need to inform ACCS how to start the service, as well as the version of Java we want to use. This is specified in a metadata file called manifest.json. For other optional settings, see Creating Metadata Files.

Create a new manifest.json with the following contents. The command is exactly as when we ran it from the command line when testing the service locally:

{
 "runtime": {
 "majorVersion": "8"
 },
 "command": "java -jar target/HelloWorld-1.0-SNAPSHOT.jar server hello-world.yml"
}

Deployment Archive

The application JAR file, the hello-world.yml configuration file and the manifest.json file need to be packaged into a zip file for deployment to ACCS. We will use the Maven Assembly Plugin to accomplish this task. See the Guide to creating assemblies for more details.

Create a new folder named assembly in the src folder.

Create a new file named accs.xml in assembly folder. The name of this file is arbitrary as it will be referenced later when we configure the assembly plugin:

<?xml version="1.0" encoding="UTF-8"?>
<assembly>
    <id>ACCS</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <files>
        <file>
            <source>manifest.json</source>
            <outputDirectory>/</outputDirectory>
        </file>
        <file>
            <source>hello-world.yml</source>
            <outputDirectory>/</outputDirectory>
        </file>
    </files>
    <fileSets>
        <fileSet>
            <directory>target</directory>
            <outputDirectory>target</outputDirectory>
            <includes>
                <include>HelloWorld-*-SNAPSHOT.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

Add the Maven Assembly build plugin to pom.xml:

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                  <descriptor>src/assembly/accs.xml</descriptor>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>                
            </plugin>

Run the build package again and you should now have a HelloWorld-1.0-SNAPSHOT-ACCS.zip file. This artifact can be deployed to ACCS.

Configure for Continuous Delivery

We could use the ACCS Service Console to manually deploy the application, however this would violate “Continuous Delivery” notion in the title of my tutorial. Instead, we’ll use the Oracle Developer Cloud Service to support continuous delivery of our application changes.

Step 1: Initialize a local Git repository

If using Eclipse, right-click the project and select New > Other. The select Git > Git Repository:

dw20-git

Then set the Repository Directory as your project directory:

dw-21-git2

Step 2: Create a Developer Cloud Service Project

Alternatively, you can add a new repository to an existing project. This is the approach I’m going to take. I’ve created a new repository named Dropwizard-HelloWorld:

dw51-new_repository

Copy the HTTP URL. We need this when we push our local changes to this repository:

dw51-http_url

Step 3: Push the local project to the Developer Cloud

Right-click the HelloWorld Eclipse project and select Team > Add to Index. Right-click the project again and select Team > Commit…, which will open the Git Staging window. Add a Commit message, such as Initial push and click Commit and Push…:

dw32-git_staging

Set the URI (that you copied from Developer Cloud) and click Next:

dw33-git3

Select Force overwrite branch in remote if it exists and has diverged:

dw34-git_force

Click Next and Finish on the Push Confirmation page:

dw35-push_confim

And you’ll see the Push Results:

dw36-push_confirm

Step 4: Create a Build Job

Create a new free-style Build Job named something like Dropwizard-HelloWorld:

dw52-new_build_job

Set the JDK to JDK 8:

dw53-JDK

Switch to the Source Control tab and select the Dropwizard_HelloWorld.git repository:

dw54-Git

Switch to the Triggers tab and and select Based on SCM Polling schedule:

dw55-triggers

Switch to the Build Steps tab and add a Maven 3 build step. Set the Goals to package. Everything else can remain as is:

dw56-build_step

Switch to the Post Build tab select Archive the Artifacts. Set the Files to Archive to **/target/*.zip:

dw56-post_build

Save the configuration and click Build Now. Wait while the build is queued and picked up by the build server:

dw57-build_now

Once the build build begins you can monitor the console output. It should take about 1 minute to complete:

dw58_console

Step 5: Create a Deploy Configuration

Switch to the Deploy tab and create a New Configuration:

dw60_new_config

For the Deployment Target, create a New Application Container Cloud. Note, this is all that’s required to establish your deployment runtime!

dw64-new_deployment_target

Set the remaining values as follows:

Configuration Name: DropwizardHelloWorld
Application Name: HelloWorld

Verify the Runtime is Java.

Be sure to set the Type to  Automatic and select Deploy stable builds only.

Select target/HelloWorld-1.0-SNAPSHOT-ACCS.zip as the artifact.

dw65-new_deployment_config

Click Save and Deploy. Wait for the deployment to complete, which should only take a couple of minutes:

dw66-deployment_complete

Use

Switch to the Application Contain Cloud Service to see your deployed application:

dw70-accs

Click the link to open your application is a new browser tab. Don’t forget to append the hello-world resource:

dw71-run

Continuous Delivery

Now let’s make a change to our application and watch it propagate through to deployment.

Return to Eclipse and edit hello-world.yml file. Change the defaultName from Stranger to Stranger Danger (Yes, technically I’m just making a configuration change, but code changes would propagate just the same):

dw80-stranger_danger

Stage and Commit and Push the change as we did before.

If you return to Developer Cloud Service, the home page will indicate a new build has been triggered:

dw90-home

Likewise, when the build completes, the Deploy will trigger.

After a few minutes, you’re updated application will be running

https://helloworld-gse00001975.apaas.em2.oraclecloud.com/hello-world

dw91_run

Certainly, your process might not be as streamlined. Ideally a branch would be created before making a change. A code review would occur before the branch is merged. Tests would run before the build is deemed a success. All of those options are possible using this same set of tools.

 

Advertisements

One thought on “Continuous Delivery of Microservices using Dropwizard, Developer Cloud and Application Container Cloud

  1. Pingback: Continuous Deployment of Spring Boot Applications using Developer Cloud and Application Container Cloud | W Brian Leonard

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s