Building a Microservice Using Dropwizard and JanusGraph
Chris Pounds

In this blog post, I'll discuss the process of building a microservice that is backed by a graph database and the technologies leveraged to accomplish it.

Choosing the Technologies

When building a microservice, I recommend trying to follow the tenets of The Twelve-Factor App.

With those tenets in mind, I'll be building this microservice in Java using Maven for its declarative dependency management and build process and Dropwizard for its straightforward architecture and configuration. Dropwizard offers great facilities for being able to monitor your application as well as functionality to run one-off tasks where the source for those tasks can be bundled with your service application code.

Getting Started With Dropwizard

One of the selling points of Dropwizard is that it's not a heavyweight framework. Its a collection of some of the best Java libraries glued together to form an easy to use REST service. To get started, let's create a Maven pom file and the typical project directory structure.

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>      <groupId>com.experoinc</groupId>     <artifactId>graph-ms</artifactId>     <version>1.0.0-SNAPSHOT</version>      <properties>         <dropwizard.version>1.0.0</dropwizard.version>     </properties>      <dependencies>         <dependency>             <groupId>io.dropwizard</groupId>             <artifactId>dropwizard-core</artifactId>             <version>${dropwizard.version}</version>         </dependency>     </dependencies>   </project>

To run a Dropwizard application, we need to have an implementation of an io.dropwizard.Configuration that represents the single yml config file required by Dropwizard, an implementation of an io.dropwizard.Application, and a yml config file.

// GraphMsApplication.java package com.experoinc.blog;  import io.dropwizard.Application; import io.dropwizard.setup.Environment;  public class GraphMsApplication extends Application<GraphMsConfiguration> {      public static void main(String[] args) throws Exception {         new GraphMsApplication().run(args);     }      public void run(GraphMsConfiguration configuration, Environment environment)             throws Exception {     } } // GraphMsConfiguration.java package com.experoinc.blog;  import io.dropwizard.Configuration;  public class GraphMsConfiguration extends Configuration { } # app.yml logging:   level: INFO   loggers:     com.experoinc: DEBUG

By default, the base Dropwizard configuration class has all of the necessary defaults for us to be able to run the Dropwizard application. Now that we have all the required files necessary to run, let's include a Maven exec directive to launch the application.

<build>    <plugins>        <plugin>            <groupId>org.codehaus.mojo</groupId>            <artifactId>exec-maven-plugin</artifactId>            <version>1.6.0</version>            <configuration>                <mainClass>com.experoinc.blog.GraphMsApplication</mainClass>                <arguments>                    <argument>server</argument>                    <argument>app.yml</argument>                </arguments>            </configuration>        </plugin>    </plugins> </build>

Now, let's run the application: mvn exec:java.

At this point, the application should be up and running without much to show for it other than some default administrative resources that Dropwizard includes. Those resources should be available by navigating to http://localhost:8081/ in your browser. One of these operational resources is the application healthchecks. This resource can be utilized to monitor different components of your application and can be used to provide alerts when portions of your system are not functioning properly.

Connecting to the Graph Database

Now that we have our application up and running, let's get it hooked up to our JanusGraph database. To do this, we'll utilize Expero's dropwizard-tinkerpop library.

<dependency>     <groupId>com.experoinc</groupId>     <artifactId>dropwizard-tinkerpop</artifactId>     <version>1.0.0</version> </dependency>

This library provides all of the necessary configuration parameters required to connect a Dropwizard application to an Apache TinkerPop enabled graph database. Additionally, it includes a healthcheck to verify the application's ability to connect to the graph database as well as hooks into Dropwizard's lifecycle management to properly shut down connections when the application halts.

Let's update our applications configuration to support the connection.

public class GraphMsConfiguration extends Configuration {          @Valid @NotNull     private TinkerPopFactory tinkerPop = new TinkerPopFactory();      @JsonProperty     public TinkerPopFactory getTinkerPop() {         return tinkerPop;     }      @JsonProperty     public void setTinkerPop(TinkerPopFactory tinkerPop) {         this.tinkerPop = tinkerPop;     } }

Now let's update our yml file to include the configuration to connect to a locally running instance.

tinkerPop:   contactPoints:     - localhost   serializer:     type: gryoMessageSerializerV1d0     ioRegistries:       - org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry

As we're using JanusGraph and it has a custom format for edge serialization, we'll need to include the janusgraph-core dependency in our application as well.

<dependency>     <groupId>org.janusgraph</groupId>     <artifactId>janusgraph-core</artifactId>     <version>0.1.1</version> </dependency>

Now, in our application startup, let's build a Cluster connection using the TinkerPopFactory included in the configuration. Additionally, let's build a GraphTraversalSource to support executing gremlin traversals against the graph.

public void run(GraphMsConfiguration configuration, Environment environment)        throws Exception {    Cluster cluster = configuration.getTinkerPop().build(environment);     GraphTraversalSource traversalSource = EmptyGraph.instance()            .traversal().withRemote(DriverRemoteConnection.using(cluster)); }

If you startup the application now, and navigate to the healthcheck page, you'll notice there is now an entry for the tinker pop server connection.

At this point, we can begin creating API's that utilize the graph database. In part 2 of the series, we'll look into packaging our application into a docker image to simplify our deployments.

RECENT POSTS FROM
THIS AUTHOR