Home Web Development Microservices Deployment Cookbook

Microservices Deployment Cookbook

By Vikram Murugesan
books-svg-icon Book
eBook $43.99 $29.99
Print $54.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $43.99 $29.99
Print $54.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Building Microservices with Java
About this book
This book will help any team or organization understand, deploy, and manage microservices at scale. It is driven by a sample application, helping you gradually build a complete microservice-based ecosystem. Rather than just focusing on writing a microservice, this book addresses various other microservice-related solutions: deployments, clustering, load balancing, logging, streaming, and monitoring. The initial chapters offer insights into how web and enterprise apps can be migrated to scalable microservices. Moving on, you’ll see how to Dockerize your application so that it is ready to be shipped and deployed. We will look at how to deploy microservices on Mesos and Marathon and will also deploy microservices on Kubernetes. Next, you will implement service discovery and load balancing for your microservices. We’ll also show you how to build asynchronous streaming systems using Kafka Streams and Apache Spark. Finally, we wind up by aggregating your logs in Kafka, creating your own metrics, and monitoring the metrics for the microservice.
Publication date:
January 2017
Publisher
Packt
Pages
378
ISBN
9781786469434

 

Chapter 1. Building Microservices with Java

In this chapter, we will cover the following recipes:

  • Creating a project template using STS and Maven

  • Writing microservices with Spring Boot

  • Writing REST APIs with Spring MVC

  • Writing microservices with WildFly Swarm

  • Writing microservices with Dropwizard

  • Writing REST APIs with SparkJava

Microservices have gained a lot of traction recently. A microservice-based architecture is one way of designing your software. In such an architecture, applications are broken down into smaller services so that they can be deployed and managed separately. This takes away a lot of pain points that occur in traditional monolithic applications. With that being said, microservices can be built using any programming language. In fact, there are many libraries and frameworks that help programmers build microservices using Java, Scala, C#, JavaScript, Python, Ruby, and so on. In this book, we will focus more on building and deploying microservices with Java.

 

Introduction


In a traditional microservice-based design, monolithic applications will be broken down into smaller services that can talk to other services either in a synchronous or asynchronous model, based on the need and use case. The first question that anyone would have when breaking down monolithic applications is "what are the potential services that my application can be broken down into?" There is no rule of thumb or straight-forward answer to this. But usually, one looks for independent functionalities. Each and every functionality can be considered to be built as its own service.

To illustrate this, let's take a look at an example application and see how it could be broken down into smaller, manageable and deployable microservices. The sample application we will be looking at is a biker tracking application. This application will have the following functionalities:

  • Web interface to monitor the user's progress on a map

  • REST API to consume the user's geolocation data constantly

  • Analytics code to perform calculations for biking route suggestions, weather predictions, biking gear suggestions, calories burnt, water intake, and so on

Let's take a look at how this application might have been designed as a monolithic application:

As you can see, the whole application is bundled as one artifact and therefore promotes a single point of failure (SPOF). If for some reason the analytics code crashes your JVM, we will lose the web interface, REST APIs, and analytics as a whole. Now, let's take a look at how this might be broken down into manageable microservices:

In this architecture diagram, you can see that each and every functionality is deployed as its own microservice. The service implementations have been broken down into a Notification Service, which will take care of sending notifications to the users, and the Geo Location Tracker Service, which keeps track of the geolocation (latitude and longitude) information of all the users. The Analytics code has been broken down into its own microservices. So if one type of analytics microservice goes down, the other microservices will keep functioning properly. You might have noticed that the REST APIs are missing. They are actually not missing, but integrated into their respective microservices.

Now let's not waste any more time and jump directly into building one part of this application. To be able to illustrate the extensive concepts that this book offers, I have chosen the geolocation tracker service as our example microservice. This service will be responsible for collecting the geolocation of all users of this application and then storing them in a data store.

 

Creating a project template using STS and Maven


Creating a project for your microservice is no different than creating a simple Java project. We will use Maven as our build framework as it is considered to be one of the most popular build frameworks. If you are comfortable using other frameworks, such as Gradle, SBT, or Ivy, feel free to use them. But keep in mind that the recipes throughout this book will use Maven extensively. Unless you are an expert in your preferred framework, I strongly recommend using Maven.

Getting ready

In order to create your microservice project, you will need the following software. Follow the instructions on their respective websites to install them:

  • JDK 1.8+

  • Maven 3.3.9+

  • Spring Tool Suite (STS) 3.8.0+

Make sure both Java and Maven are in your PATH variable so that you can use the java and mvn commands on every terminal shell without having to set PATH each time. Spring Tool Suite is a sophisticated version of Eclipse that has lot of Spring plugins and extensions. If you are familiar with other IDEs, feel free to use them. But for familiarity, this book will use STS for all recipes.

How to do it...

After you have installed the above-mentioned software, open Spring Tool Suite. The first time you open it, you will be requested to choose a workspace. Go ahead and enter your workspace location. In this recipe, we will learn how to create a template Maven project using STS and Maven. STS comes with Maven Integration out of the box. So we don't have to configure it any further. After your STS IDE has completed startup, follow the below instructions to create a new Maven project:

  1. In your STS window, right-click anywhere on the Package Explorer, select New, and then select Maven Project, as shown in the following screenshot:

  2. This will open a popup that will let you chose the type of Maven project you would like to create. We will skip the archetype selection by checking the box that says Create a simple project (skip archetype selection) and then hit Next:

  3. In the next window, enter the following details to create your project:

    • Group Id: com.packt.microservices

    • Artifact Id: geolocation

    • Name: geolocation

  4. After you have entered the details, hit Finish:

  5. This will create a simple Maven JAR module with all the required directories in place. Depending on your IDE settings, STS configures your new project with the default Java version. If you have not set any defaults, it will configure your project with Java 1.5. You can verify this by checking your project structure in STS. The following screenshot shows that STS uses Java 1.5 for your project:

  6. We will use Java 8's lambda expressions in other chapters. So let's change the Java version from 1.5 to 1.8. In order to change the Java version, we will configure the maven-compiler-plugin in the pom.xmlfile. Add the following section of code to your pom.xml file's project section:

            <build> 
              <plugins> 
               <plugin> 
                  <groupId>org.apache.maven.plugins</groupId> 
                  <artifactId>maven-compiler-plugin</artifactId> 
                <version>3.5.1</version> 
                <configuration> 
                  <source>1.8</source> 
                  <target>1.8</target> 
                </configuration> 
               </plugin> 
             </plugins> 
            </build> 
    
  7. Save your pom.xml file, right-click on your project, choose Maven, and then hit Update Project... or use the keyboard shortcut Alt + F5. This will automatically change your project's Java version to 1.8.

  8. Our microservice project is now ready to play with.

There's more...

If you are more comfortable using the command line to create Maven projects, issue the following command in your terminal to create the new project:

mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=com.packt.microservices -DartifactId=geolocation \ 
-Dname=geolocation

After Maven creates the project, you should be able to import your project into your IDE. As this is something out of the scope of this book, we will not be looking at how to import an existing Maven project into your IDE.

 

Writing microservices with Spring Boot


Now that our project is ready, let's look at how to write our microservice. There are several Java-based frameworks that let you create microservices. One of the most popular frameworks from the Spring ecosystem is the Spring Boot framework. In this recipe, we will look at how to create a simple microservice application using Spring Boot.

Getting ready

Any application requires an entry point to start the application. For Java-based applications, you can write a class that has the main method and run that class as a Java application. Similarly, Spring Boot requires a simple Java class with the main method to run it as a Spring Boot application (microservice). Before you start writing your Spring Boot microservice, you will also require some Maven dependencies in your pom.xml file.

How to do it...

  1. Create a Java class called com.packt.microservices.geolocation.GeoLocationApplication.java and give it an empty main method:

            package com.packt.microservices.geolocation;  
              public class GeoLocationApplication {  
                public static void main(String[] args) { 
                // left empty intentionally 
               } 
              } 
    
  2. Now that we have our basic template project, let's make our project a child project of Spring Boot's spring-boot-starter-parent pom module. This module has a lot of prerequisite configurations in its pom.xml file, thereby reducing the amount of boilerplate code in our pom.xml file. At the time of writing this, 1.3.6.RELEASE was the most recent version:

            <parent> 
              <groupId>org.springframework.boot</groupId> 
              <artifactId>spring-boot-starter-parent</artifactId> 
              <version>1.3.6.RELEASE</version> 
            </parent> 
    
  3. After this step, you might want to run a Maven update on your project as you have added a new parent module. If you see any warnings about the version of the maven-compiler  plugin, you can either ignore it or just remove the <version>3.5.1</version> element. If you remove the version element, please perform a Maven update afterward.

  4. Spring Boot has the ability to enable or disable Spring modules such as Spring MVC, Spring Data, and Spring Caching. In our use case, we will be creating some REST APIs to consume the geolocation information of the users. So we will need Spring MVC. Add the following dependencies to your pom.xml file:

            <dependencies> 
              <dependency> 
                <groupId>org.springframework.boot</groupId> 
                <artifactId>spring-boot-starter-web</artifactId> 
              </dependency> 
            </dependencies> 
    
  5. We also need to expose the APIs using web servers such as Tomcat, Jetty, or Undertow. Spring Boot has an in-memory Tomcat server that starts up as soon as you start your Spring Boot application. So we already have an in-memory Tomcat server that we could utilize.

  6. Now let's modify the GeoLocationApplication.java class to make it a Spring Boot application:

            package com.packt.microservices.geolocation; 
            import org.springframework.boot.SpringApplication; 
            import org.springframework.boot.autoconfigure
             .SpringBootApplication; 
              @SpringBootApplication 
              public class GeoLocationApplication { 
                public static void main(String[] args) {
                SpringApplication.run(GeoLocationApplication.class, args); 
               } 
              } 
    

As you can see, we have added an annotation, @SpringBootApplication, to our class. The @SpringBootApplication annotation reduces the number of lines of code written by adding the following three annotations implicitly:

  • @Configuration

  • @ComponentScan

  • @EnableAutoConfiguration

If you are familiar with Spring, you will already know what the first two annotations do. @EnableAutoConfiguration is the only annotation that is part of Spring Boot. The AutoConfiguration package has an intelligent mechanism that guesses the configuration of your application and automatically configures the beans that you will likely need in your code.

You can also see that we have added one more line to the main method, which actually tells Spring Boot the class that will be used to start this application. In our case, it is GeoLocationApplication.class. If you would like to add more initialization logic to your application, such as setting up the database or setting up your cache, feel free to add it here.

  1. Now that our Spring Boot application is all set to run, let's see how to run our microservice. Right-click on GeoLocationApplication.java from Package Explorer, select Run As, and then select Spring Boot App. You can also choose Java Application instead of Spring Boot App. Both the options ultimately do the same thing. You should see something like this on your STS console:

  2. If you look closely at the console logs, you will notice that Tomcat is being started on port number 8080. In order to make sure our Tomcat server is listening, let's run a simple curl command. cURL is a command-line utility available on most Unix and Mac systems. For Windows, use tools such as Cygwin or even Postman. Postman is a Google Chrome extension that gives you the ability to send and receive HTTP requests. For simplicity, we will use cURL. Execute the following command on your terminal:

          curl http://localhost:8080
    
  3. This should give us an output like this:

          {"timestamp":1467420963000,"status":404,"error":"Not
          Found","message":"No message available","path":"/"}
    
    

This error message is being produced by Spring. This verifies that our Spring Boot microservice is ready to start building on with more features. There are more configurations that are needed for Spring Boot, which we will perform later in this chapter along with Spring MVC.

 

Writing REST APIs with Spring MVC


There are two types of communication models. One of them is synchronous, where the client waits for the server to respond to its request. The other is asynchronous, where the client fires a request and forgets. Though Servlet 3.0 and above let you create asynchronous servlets, in our recipes, we will focus on traditional servlet-based HTTP APIs for simplicity. We will also be looking at asynchronous communication in later chapters.

Getting ready

When it comes to building REST APIs, there are several frameworks to choose from. As we already set up the Spring ecosystem in our previous recipe, it would make more sense and be much easier to use Spring MVC to expose REST APIs.

How to do it...

The true advantage of Spring Boot is that you do not have to add any new dependencies to enable web support for your application. Spring Boot's parent pom file (spring-boot-starter-parent) takes care of that for you. Now let's take a look at how to write our first API. If you are familiar with Spring MVC, this should be really straight-forward for you:

  1. Create a Controller class called com.packt.microservices.geolocation.GeoLocationController.java, which will be responsible for basic CRUD operations for the geolocation of all users:

            package com.packt.microservices.geolocation; 
     
            import org.springframework.web.bind.annotation.RequestMapping; 
            import org.springframework.web.bind.annotation.RestController; 
     
            @RestController 
            @RequestMapping("/geolocation") 
            public class GeoLocationController { 
     
            } 
    

    There are two things to note here. The @RestController annotation indicates that we are going to use this controller to expose our REST APIs. It implicitly adds the @ResponseBody annotation to all controller methods as that is something you would want to do when exposing your REST APIs using Spring MVC. The @RequestMapping annotation specifies where your HTTP resource is located. We are setting @RequestMapping on the controller level to apply it to all controller methods.

    Note

    Using @RequestMapping on the Controller class level to define a root resource path is considered to be one of the best practices. Instead of having to create API paths such as /getGeolocation or /createGeolocation, it is always a better practice to use the same path, /geolocation, with the GET method to get geolocation data and the POST method to create geolocation data.

  2. Before we jump into creating our APIs, we will need some classes for the domain object and service. Let's start with creating our domain object. Assume that our GeoLocation consists latitude and longitude. We will be defining both latitude and longitude as double to provide better precision. Now we will have to say which user's geolocation it is. So we might want to add a userId. We also need to say at what time the user was at the geolocation. So we might want to add a timestamp in EPOCH time format. The timestamp will be of type long. This is how your plain old java object (POJO) class will look:

            package com.packt.microservices.geolocation; 
    
            import java.io.Serializable; 
            import java.util.UUID; 
     
              public class GeoLocation implements Serializable { 
     
                private static final long serialVersionUID = 1L; 
       
               private double latitude; 
               private double longitude; 
               private UUID userId; 
               private long timestamp; 
       
              public double getLatitude() { 
                return latitude; 
              } 
       
              public void setLatitude(double latitude) { 
                this.latitude = latitude; 
              } 
       
              public double getLongitude() { 
               return longitude; 
              } 
       
              public void setLongitude(double longitude) { 
                this.longitude = longitude; 
              } 
       
              public UUID getUserId() { 
               return userId; 
              } 
       
              public void setUserId(UUID userId) { 
               this.userId = userId; 
              } 
       
             public long getTimestamp() { 
              return timestamp; 
             } 
       
             public void setTimestamp(long timestamp) { 
              this.timestamp = timestamp; 
             } 
            } 
    

    As you can see, we have used the java.util.UUID class to represent the userId, assuming that this UUID uniquely identifies a user. We will not be creating the user POJO as it is out of scope for this recipe.

    In an ideal scenario, one would be using a NoSQL or relational database to store the geolocations. In this case, NoSQL sounds more suitable due to several reasons, including the fact that our data is time series data, in JSON format, unstructured but will change over time and we will have a humongous amount of data.

  3. For simplicity purposes, we will be storing our geolocations in an in-memory java.util.List<GeoLocation> collection. Let's create our repository that holds all our geolocation objects, com.packt.microservices.geolocation.GeoLocationRepository.java:

            package com.packt.microservices.geolocation; 
     
            import java.util.ArrayList; 
            import java.util.Collections; 
            import java.util.List; 
     
            import org.springframework.stereotype.Repository; 
     
            @Repository 
            public class GeoLocationRepository { 
     
              private List<GeoLocation> geolocations = new
              ArrayList<GeoLocation>(); 
       
                public void addGeoLocation(GeoLocation geolocation) { 
                  geolocations.add(geolocation); 
                } 
       
               public List<GeoLocation> getGeoLocations() { 
                  return Collections.unmodifiableList(geolocations); 
               } 
             } 
    
  4. Now let's take a look at how your Service interface will look:

            package com.packt.microservices.geolocation; 
     
            import java.util.List; 
     
            public interface GeoLocationService { 
     
              public GeoLocation create(GeoLocation geolocation); 
              public List<GeoLocation> findAll(); 
            }  
    
  5. Both our repository and service have a very simple interface. Ideally in real-time applications, you might want to add more complicated methods that not only perform CRUD operations but also sort, filter, select only specific fields, and so on. Now let's take a look at our com.packt.microservices.geolocation.GeoLocationServiceImpl.java class:

            package com.packt.microservices.geolocation; 
     
            import java.util.List; 
     
            import org.springframework.beans.factory.annotation.Autowired; 
     
            import org.springframework.stereotype.Service; 
     
            @Service 
            public class GeoLocationServiceImpl implements
            GeoLocationService { 
       
              @Autowired 
              private GeoLocationRepository repository; 
     
              @Override 
              public GeoLocation create(GeoLocation geolocation) { 
               repository.addGeoLocation(geolocation); 
               return geolocation; 
              } 
     
              @Override 
              public List<GeoLocation> findAll() { 
                return repository.getGeoLocations(); 
              } 
            }

    Note

    It is always strongly recommended that you write unit test cases for any new code. But as that is a little out of scope for this book, we will not be writing unit test cases for any of the previous code. To learn more about unit testing Spring Boot applications, please take a look at Spring Boot's documentation at https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html.

  6. Now that our domain and service classes are all set to go, let's modify our Controller class to save and find geolocations. Add the following snippet into your Controller class body:

            @Autowired
            private GeoLocationService service;
    
            @RequestMapping(method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
            public GeoLocation create(@RequestBody GeoLocation geolocation) {
              return service.create(geolocation);
            }
      
            @RequestMapping(method = RequestMethod.GET, produces = "application/json")
            public List<GeoLocation> findAll() {
              return service.findAll();
            } 
    

In this implementation, there are a few things to notice. The @RequestMapping annotation does not have a path defined as it is already derived from the class-level annotation. For both the create and findAll methods, we are using the same path but different HTTP methods as per best practice. Since we are dealing only with JSON here, we have set the produces and consumes values to application/json. The return types of the create and findAll methods are GeoLocation and List<GeoLocation> respectively. Spring MVC internally uses Jackson to convert them to their equivalent JSON strings.

That's it! We are now ready to test our application:

  1. Let's try to create two geolocations using the POST API and later try to retrieve them using the GET method. Execute the following cURL commands in your terminal one by one:

          curl -H "Content-Type: application/json" -X POST -d'{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 41.803488, "longitude": -88.144040}' http://localhost:8080/geolocation
    
  2. This should give you an output similar to the following (pretty-printed for readability):

            { 
             "latitude": 41.803488, 
             "longitude": -88.14404, 
             "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", 
             "timestamp": 1468203975 
            } 
     
     
            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 9.568012, "longitude": 77.962444}' http://localhost:8080/geolocation
    
  3. This should give you an output similar to the following (pretty-printed for readability):

    {
              "latitude": 9.568012,
              "longitude": 77.962444,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
  4. To verify whether your entities were stored correctly, execute the following cURL command:

          curl http://localhost:8080/geolocation
    
  5. This should give you an output similar to the following (pretty-printed for readability):

            [ 
            { 
              "latitude": 41.803488, 
              "longitude": -88.14404, 
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", 
              "timestamp": 1468203975 
            }, 
            { 
              "latitude": 9.568012, 
              "longitude": 77.962444, 
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", 
              "timestamp": 1468203975 
            } 
            ]
    

You now have a fully working version of your microservice. The remaining recipes in this chapter try to achieve the same logic with different frameworks, such as WildFly Swarm and Dropwizard. Later in this chapter, we will also look at another framework that helps you build REST APIs quickly called SparkJava (different from Apache Spark). If you will be using Spring Boot for your microservices, you can jump to the next chapter. If you are interested in any of the frameworks that were mentioned, jump to the appropriate recipe in this chapter.

 

Writing microservices with WildFly Swarm


WildFly Swarm is a J2EE application packaging framework from RedHat that utilizes the in-memory Undertow server to deploy microservices. In this recipe, we will create the same GeoLocation API using WildFly Swarm and JAX-RS.

To avoid confusion and dependency conflicts in our project, we will create the WildFly Swarm microservice as its own Maven project. This recipe is just here to help you get started on WildFly Swarm. When you are building your production-level application, it is your choice to either use Spring Boot, WildFly Swarm, Dropwizard, or SparkJava based on your needs.

Getting ready

Similar to how we created the Spring Boot Maven project, create a Maven WAR module with the groupId  com.packt.microservices and name/artifactId  geolocation-wildfly. Feel free to use either your IDE or the command line. Be aware that some IDEs complain about a missing web.xml file. We will see how to fix that in the next section.

How to do it...

  1. Before we set up the WildFly Swarm project, we have to fix the missing web.xml error. The error message says that Maven expects to see a web.xml file in your project as it is a WAR module, but this file is missing in your project. In order to fix this, we have to add and configure maven-war-plugin. Add the following code snippet to your pom.xml file's project section:

            <build> 
              <plugins> 
                <plugin> 
                  <groupId>org.apache.maven.plugins</groupId> 
                  <artifactId>maven-war-plugin</artifactId> 
                  <version>2.6</version> 
                  <configuration> 
                    <failOnMissingWebXml>false</failOnMissingWebXml> 
                  </configuration> 
                </plugin> 
               </plugins> 
            </build> 
    
  2. After adding the snippet, save your pom.xml file and perform a Maven update. Also, if you see that your project is using a Java version other than 1.8, follow the Creating a project template using STS and Maven recipe to change the Java version to 1.8. Again, perform a Maven update for the changes to take effect.

  3. Now, let's add the dependencies required for this project. As we know that we will be exposing our APIs, we have to add the JAX-RS library. JAX-RS is the standard JSR-compliant API for creating RESTful web services. JBoss has its own version of JAX-RS. So let's add that dependency to the pom.xml file:

            <dependencies> 
              <dependency> 
                <groupId>org.jboss.spec.javax.ws.rs</groupId> 
                  <artifactId>jboss-jaxrs-api_2.0_spec</artifactId> 
                  <version>1.0.0.Final</version> 
                  <scope>provided</scope> 
              </dependency> 
            </dependencies> 
    

    Note

    The one thing that you have to note here is the provided scope. The provided scope in general means that this JAR need not be bundled with the final artifact when it is built. Usually, the dependencies with provided scope will be available to your application either via your web server or application server. In this case, when Wildfly Swarm bundles your app and runs it on the in-memory Undertow server, your server will already have this dependency.

  4. The next step toward creating the GeoLocation API using Wildfly Swarm is creating the domain object. Use the com.packt.microservices.geolocation.GeoLocation.java file from the previous recipe.

  5. Now that we have the domain object, there are two classes that you need to create in order to write your first JAX-RS web service. The first of those is the Application class. The Application class in JAX-RS is used to define the various components that you will be using in your application. It can also hold some metadata about your application, such as your basePath (or ApplicationPath) to all resources listed in this Application class. In this case, we are going to use /geolocation as our basePath. Let's see how that looks:

           package com.packt.microservices.geolocation; 
     
           import javax.ws.rs.ApplicationPath; 
           import javax.ws.rs.core.Application; 
     
           @ApplicationPath("/geolocation") 
             public class GeoLocationApplication extends Application { 
     
              public GeoLocationApplication() {} 
             } 
    

    There are two things to note in this class; one is the Application class and the other is the @ApplicationPath annotation-both of which we've already talked about.

  6. Now let's move on to the resource class, which is responsible for exposing the APIs. If you are familiar with Spring MVC, you can compare Resource classes to Controllers. They are responsible for defining the API for any specific resource. The annotations are slightly different from that of Spring MVC. Let's create a new resource class called com.packt.microservices.geolocation.GeoLocationResource.java that exposes a simple GET API:

            package com.packt.microservices.geolocation; 
     
            import java.util.ArrayList; 
            import java.util.List; 
     
            import javax.ws.rs.GET; 
            import javax.ws.rs.Path; 
            import javax.ws.rs.Produces; 
     
            @Path("/") 
            public class GeoLocationResource { 
     
             @GET 
             @Produces("application/json") 
             public List<GeoLocation> findAll() { 
               return new ArrayList<>(); 
             } 
            } 
    

    All the three annotations, @GET, @Path, and @Produces, are pretty self explanatory.

Before we start writing the APIs and the service class, let's test the application from the command line to make sure it works as expected. With the current implementation, any GET request sent to the /geolocation URL should return an empty JSON array.

So far, we have created the RESTful APIs using JAX-RS. It's just another JAX-RS project:

  1. In order to make it a microservice using Wildfly Swarm, all you have to do is add the wildfly-swarm-plugin to the Maven pom.xml file. This plugin will be tied to the package phase of the build so that whenever the package goal is triggered, the plugin will create an uber JAR with all required dependencies. An uber JAR is just a fat JAR that has all dependencies bundled inside itself. It also deploys our application in an in-memory Undertow server. Add the following snippet to the plugins section of the pom.xml file:

            <plugin> 
              <groupId>org.wildfly.swarm</groupId> 
              <artifactId>wildfly-swarm-plugin</artifactId> 
              <version>1.0.0.Final</version> 
              <executions> 
                <execution> 
                  <id>package</id> 
                  <goals> 
                    <goal>package</goal> 
                  </goals> 
                </execution> 
              </executions> 
            </plugin> 
    
  2. Now execute the mvn clean package command from the project's root directory, and wait for the Maven build to be successful. If you look at the logs, you can see that wildfly-swarm-plugin will create the uber JAR, which has all its dependencies. You should see something like this in your console logs:

  3. After the build is successful, you will find two artifacts in the target directory of your project. The geolocation-wildfly-0.0.1-SNAPSHOT.war file is the final WAR created by the maven-war-plugin. The geolocation-wildfly-0.0.1-SNAPSHOT-swarm.jar file is the uber JAR created by the wildfly-swarm-plugin. Execute the following command in the same terminal to start your microservice:

          java -jar target/geolocation-wildfly-0.0.1-SNAPSHOT-swarm.jar
    
  4. After executing this command, you will see that Undertow has started on port number 8080, exposing the geolocation resource we created. You will see something like this:

  5. Execute the following cURL command in a separate terminal window to make sure our API is exposed. The response of the command should be [], indicating there are no geolocations:

          curl http://localhost:8080/geolocation
    
  6. Now let's build the service class and finish the APIs that we started. For simplicity purposes, we are going to store the geolocations in a collection in the service class itself. In a real-time scenario, you will be writing repository classes or DAOs that talk to the database that holds your geolocations. Get the com.packt.microservices.geolocation.GeoLocationService.java interface from the previous recipe. We'll use the same interface here.

  7. Create a new class called com.packt.microservices.geolocation.GeoLocationServiceImpl.java that extends the GeoLocationService interface:

            package com.packt.microservices.geolocation; 
     
            import java.util.ArrayList; 
            import java.util.Collections; 
            import java.util.List; 
     
            public class GeoLocationServiceImpl implements
            GeoLocationService { 
       
              private static List<GeoLocation> geolocations = new 
               ArrayList<>
              (); 
     
             @Override 
              public GeoLocation create(GeoLocation geolocation) { 
                geolocations.add(geolocation); 
                return geolocation; 
              } 
     
             @Override 
              public List<GeoLocation> findAll() { 
                return Collections.unmodifiableList(geolocations); 
              } 
            } 
    
  8. Now that our service classes are implemented, let's finish building the APIs. We already have a very basic stubbed-out GET API. Let's just introduce the service class to the resource class and call the findAll method. Similarly, let's use the service's create method for POST API calls. Add the following snippet to GeoLocationResource.java:

           private GeoLocationService service = new
           GeoLocationServiceImpl(); 
     
           @GET 
           @Produces("application/json") 
           public List<GeoLocation> findAll() { 
             return service.findAll(); 
           } 
       
           @POST 
           @Produces("application/json") 
           @Consumes("application/json") 
           public GeoLocation create(GeoLocation geolocation) { 
             return service.create(geolocation); 
           } 
    
  9. We are now ready to test our application. Go ahead and build your application. After the build is successful, run your microservice: let's try to create two geolocations using the POST API and later try to retrieve them using the GET method. Execute the following cURL commands in your terminal one by one:

              curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 41.803488, "longitude": -88.144040}' http://localhost:8080/geolocation
    
  10. This should give you something like the following output (pretty-printed for readability):

    {
              "latitude": 41.803488,
              "longitude": -88.14404,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 9.568012, "longitude": 77.962444}' http://localhost:8080/geolocation
    
    
  11. This command should give you an output similar to the following (pretty-printed for readability):

            { 
              "latitude": 9.568012, 
              "longitude": 77.962444, 
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", 
              "timestamp": 1468203975 
            }
    
  12. To verify whether your entities were stored correctly, execute the following cURL command:

             curl http://localhost:8080/geolocation
    
  13. This should give you an output like this (pretty-printed for readability):

            [
              {
                 "latitude": 41.803488,
                 "longitude": -88.14404,
                 "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                 "timestamp": 1468203975
              },
              {
                "latitude": 9.568012,
                "longitude": 77.962444,
                "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                "timestamp": 1468203975
              }
            ]
    

Whatever we have seen so far will give you a head start in building microservices with WildFly Swarm. Of course, there are tons of features that WildFly Swarm offers. Feel free to try them out based on your application needs. I strongly recommend going through the WildFly Swarm documentation for any advanced usages. If you already know that you are going to be using WildFly Swarm for your microservices, you can skip the rest of the recipes in this chapter and jump to next chapter. The final two recipes in this chapter will show you how to create microservices using Dropwizard and how to create RESTful APIs with SparkJava.

 

Writing microservices with Dropwizard


Dropwizard is a collection of libraries that help you build powerful applications quickly and easily. The libraries vary from Jackson, Jersey, Jetty, and so on. You can take a look at the full list of libraries on their website. This ecosystem of libraries that help you build powerful applications could be utilized to create microservices as well. As we saw earlier, it utilizes Jetty to expose its services. In this recipe, we will create the same GeoLocation API using Dropwizard and Jersey.

To avoid confusion and dependency conflicts in our project, we will create the Dropwizard microservice as its own Maven project. This recipe is just here to help you get started with Dropwizard. When you are building your production-level application, it is your choice to either use Spring Boot, WildFly Swarm, Dropwizard, or SparkJava based on your needs.

Getting ready

Similar to how we created other Maven projects, create a Maven JAR module with the groupId  com.packt.microservices and name/artifactId  geolocation-dropwizard. Feel free to use either your IDE or the command line. After the project is created, if you see that your project is using a Java version other than 1.8, follow the Creating a project template using STS and Maven recipe to change the Java version to 1.8. Perform a Maven update for the change to take effect.

How to do it...

The first thing that you will need is the dropwizard-core Maven dependency. Add the following snippet to your project's pom.xml file:

  <dependencies> 
    <dependency> 
      <groupId>io.dropwizard</groupId> 
      <artifactId>dropwizard-core</artifactId> 
      <version>0.9.3</version> 
    </dependency> 
  </dependencies> 

Guess what? This is the only dependency you will need to spin up a simple Jersey-based Dropwizard microservice.

Before we start configuring Dropwizard, we have to create the domain object, service class, and resource class. Follow the steps from the previous recipe to create the following four files:

  • com.packt.microservices.geolocation.GeoLocation.java

  • com.packt.microservices.geolocation.GeoLocationService.java

  • com.packt.microservices.geolocation.GeoLocationServiceImpl.java

  • com.packt.microservices.geolocation. GeoLocationResource.java

Let's see what each of these classes does. The GeoLocation.java class is our domain object that holds the geolocation information. The GeoLocationService.java class defines our interface, which is then implemented by the GeoLocationServiceImpl.java class. If you take a look at the GeoLocationServiceImpl.java class, we are using a simple collection to store the GeoLocation domain objects. In a real-time scenario, you will be persisting these objects in a database. But to keep it simple, we will not go that far.

To be consistent with the previous recipe, let's change the path of GeoLocationResource to /geolocation. To do so, replace @Path("/") with @Path("/geolocation") on line number 11 of the GeoLocationResource.java class.

We have now created the service classes, domain object, and resource class. Let's configure Dropwizard.

In order to make your project a microservice, you have to do two things:

  1. Create a Dropwizard configuration class. This is used to store any meta-information or resource information that your application will need during runtime, such as DB connection, Jetty server, logging, and metrics configurations. These configurations are ideally stored in a YAML file, which will then be mapped to your Configuration class using Jackson. In this application, we are not going to use the YAML configuration as it is out of scope for this book.

    Note

    If you would like to know more about configuring Dropwizard, refer to their Getting Started documentation page at http://www.dropwizard.io/0.7.1/docs/getting-started.html .

  2. Let's create an empty Configuration class called GeoLocationConfiguration.java:

             package com.packt.microservices.geolocation; 
     
             import io.dropwizard.Configuration; 
     
             public class GeoLocationConfiguration extends Configuration { 
     
             } 
    
  3. The YAML configuration file has a lot to offer. Take a look at a sample YAML file from Dropwizard's Getting Started documentation page to learn more. The name of the YAML file is usually derived from the name of your microservice. The microservice name is usually identified by the return value of the overridden method public String getName() in your Application class. Now let's create the GeoLocationApplication.java application class:

            package com.packt.microservices.geolocation; 
     
            import io.dropwizard.Application; 
            import io.dropwizard.setup.Environment; 
      
            public class GeoLocationApplication extends
            Application<GeoLocationConfiguration> { 
        
              public static void main(String[] args) throws Exception { 
                new GeoLocationApplication().run(args); 
              } 
     
              @Override 
              public void run(GeoLocationConfiguration config, Environment 
                 env) throws Exception { 
                 env.jersey().register(new GeoLocationResource()); 
              } 
            } 
    

    There are a lot of things going on here. Let's look at them one by one. Firstly, this class extends Application with the GeoLocationConfiguration generic. This clearly makes an instance of your GeoLocationConfiguraiton.java class available so that you have access to all the properties you have defined in your YAML file at the same time mapped in the Configuration class. The next one is the run method. The run method takes two arguments: your configuration and environment. The Environment instance is a wrapper to other library-specific objects such as MetricsRegistry, HealthCheckRegistry, and JerseyEnvironment. For example, we could register our Jersey resources using the JerseyEnvironment instance. The env.jersey().register(new GeoLocationResource()) line does exactly that. The main method is pretty straight-forward. All it does is call the run method.

  4. Before we can start the microservice, we have to configure this project to create a runnable uber JAR. Uber JARs are just fat JARs that bundle their dependencies in themselves. For this purpose, we will be using the maven-shade-plugin. Add the following snippet to the build section of the pom.xml file. If this is your first plugin, you might want to wrap it in a <plugins> element under <build>:

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>2.3</version>
          <configuration>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
              <filter>
                <artifact>*:*</artifact>
                <excludes>
                  <exclude>META-INF/*.SF</exclude>
                  <exclude>META-INF/*.DSA</exclude>
                  <exclude>META-INF/*.RSA</exclude>
                </excludes>
              </filter>
            </filters>
          </configuration>
          <executions>
            <execution>
              <phase>package</phase>
              <goals>
                <goal>shade</goal>
              </goals>
              <configuration>
                <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
        <mainClass>com.packt.microservices.geolocation.GeoLocationApplication</mainClass>
                  </transformer>
                </transformers>
              </configuration>
            </execution>
          </executions>
        </plugin>
     
    
  5. The previous snippet does the following:

    It creates a runnable uber JAR that has a reduced pom.xml file that does not include the dependencies that are added to the uber JAR. To learn more about this property, take a look at the documentation of maven-shade-plugin.

    It utilizes com.packt.microservices.geolocation.GeoLocationApplication as the class whose main method will be invoked when this JAR is executed. This is done by updating the MANIFEST file.

    It excludes all signatures from signed JARs. This is required to avoid security errors.

  6. Now that our project is properly configured, let's try to build and run it from the command line. To build the project, execute mvn clean package from the project's root directory in your terminal. This will create your final JAR in the target directory. Execute the following command to start your microservice:

          java -jar target/geolocation-dropwizard-0.0.1-SNAPSHOT.jar server
    
  7. The server argument instructs Dropwizard to start the Jetty server. After you issue the command, you should be able to see that Dropwizard has started the in-memory Jetty server on port 8080. If you see any warnings about health checks, ignore them. Your console logs should look something like this:

  8. We are now ready to test our application. Let's try to create two geolocations using the POST API and later try to retrieve them using the GET method. Execute the following cURL commands in your terminal one by one:

            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 41.803488, "longitude": -88.144040}' http://localhost:8080/geolocation
    
  9. This should give you an output similar to the following (pretty-printed for readability):

    {
              "latitude": 41.803488,
              "longitude": -88.14404,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 9.568012, "longitude": 77.962444}' http://localhost:8080/geolocation
    
  10. This should give you an output like this (pretty-printed for readability):

    {  
              "latitude": 9.568012,
              "longitude": 77.962444,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
  11. To verify whether your entities were stored correctly, execute the following cURL command:

          curl http://localhost:8080/geolocation
    
  12. It should give you an output similar to the following (pretty-printed for readability):

    [
              {
                "latitude": 41.803488,
                "longitude": -88.14404,
                "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                "timestamp": 1468203975
              },
              {
                "latitude": 9.568012,
                "longitude": 77.962444,
                "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                "timestamp": 1468203975
             }
           ]
    

Excellent! You have created your first microservice with Dropwizard. Dropwizard offers more than what we have seen so far. Some of it is out of scope for this book. I believe the metrics API that Dropwizard uses could be used in any type of application. Therefore, we will look at how to use it in later chapters.

 

Writing REST APIs with SparkJava


In the previous recipes, we saw how to create a microservice using various frameworks such as Spring Boot, WildFly Swarm, and Dropwizard. This recipe is going to be a little different for the fact that we are going to see how to create a self-managed RESTful API using a framework called SparkJava. Not to be confused with Apache Spark, the SparkJava framework claims to be a micro-framework for building web applications. Their HTTP API was inspired by Ruby's Sinatra framework. It is so simple that bringing up an HTTP GET API requires fewer than ten lines of code. Owing to this, SparkJava is something that could be considered when you would like to quickly build HTTP-based microservices.

To avoid confusion and dependency conflicts in our project, we will create the SparkJava microservice as its own Maven project. This recipe is just here to help you get started with SparkJava. When you are building your production-level application, it is your choice to either use Spring Boot, WildFly Swarm, Dropwizard, or SparkJava based on your needs.

Getting ready

Similar to how we created other Maven projects, create a Maven JAR module with the groupId com.packt.microservices and name/artifactId geolocation-sparkjava. Feel free to use either your IDE or the command line. After the project is created, if you see that your project is using a Java version other than 1.8, follow the Creating a project template using STS and Maven recipe to change the Java version to 1.8. Perform a Maven update for the change to take effect.

How to do it...

The first thing that you will need is the SparkJava dependency. Add the following snippet to your project's pom.xml file:

  <dependencies> 
    <dependency> 
      <groupId>com.sparkjava</groupId> 
      <artifactId>spark-core</artifactId> 
      <version>2.5</version> 
    </dependency> 
  </dependencies> 

We now have to create the domain object and service class. Follow the Writing microservices with WildFly Swarm recipe to create the following three files:

  • com.packt.microservices.geolocation.GeoLocation.java

  • com.packt.microservices.geolocation.GeoLocationService.java

  • com.packt.microservices.geolocation.GeoLocationServiceImpl.java

Let's see what each of these classes does. The GeoLocation.java class is our domain object that holds the geolocation information. The GeoLocationService.java interface defines our interface, which is then implemented by the GeoLocationServiceImpl.java class. If you take a look at the GeoLocationServiceImpl.java class, we are using a simple collection to store the GeoLocation domain objects. In a real-time scenario, you will be persisting these objects in a database. But to keep it simple, we will not go that far.

The next thing that SparkJava needs is a controller. If you are familiar with Spring MVC, you can relate this controller to that of Spring MVC's. The controller has a collection of routes defined for each URL pattern in your API. Follow these steps:

  1. Let's create our controller com.packt.microservices.geolocation.GeoLocationController.java with a stubbed-out GET API:

          package com.packt.microservices.geolocation; 
     
          import static spark.Spark.*; 
     
          public class GeoLocationController { 
     
            public static void main(String[] args) { 
              get("/geolocation", (req, resp) -> "[]"); 
            } 
          } 
    
  2. The quickest way to test this is by running this class as a Java application. If you get SLF4J errors in your console after you start the application, add the following Maven dependency to your pom.xml file and restart your application:

          <dependency> 
            <groupId>org.slf4j</groupId> 
            <artifactId>slf4j-simple</artifactId> 
            <version>1.7.21</version> 
          </dependency> 
    

    The slf4j-simple dependency routes all the SLF4Jlog messages to the System.err stream.

  3. Your console logs should look something like this after the restart:

    From the logs, we can clearly see that the service is running on port 4567.

  4. Execute the following curl command in a terminal window to make sure our API is exposed. The response of the following command should be [], indicating there are no geolocations:

          curl http://localhost:4567/geolocation
    
  5. Now let's finish building the APIs. We already have a very basic stubbed-out GET API. Let's just introduce the service class to the controller and call the findAll method. Similarly, let's use the service's create method for POST API calls. Before we do that, we need to do one more thing. By default, SparkJava does not perform JSON serialization and deserialization. We will be using a library called gson to do that. So add the following dependency to your pom.xml file:

            <dependency>
              <groupId>com.google.code.gson</groupId>
              <artifactId>gson</artifactId>
              <version>2.7</version>
            </dependency>
  6. Now let's replace the main method of GeoLocationController.java with this:

        public static void main(String[] args) {
          GeoLocationService service = new GeoLocationServiceImpl();
          Gson gson = new Gson();
        
          get("/geolocation", (req, resp) -> {
            return service.findAll();
          }, gson::toJson);
        
          post("/geolocation", (req, resp) -> {
            return service.create(gson.fromJson(req.body(), GeoLocation.class));
          }, gson::toJson);
        }
    

Yes, there are too many things happening here. Let's try to understand them one by one:

  • The get method now uses the service's findAll method

  • The third argument to the get method is the ResponseTransformer, which says how your response should be transformed before being sent to the client

  • Since the ResponseTransformer is a FunctionalInterface with just one method render that takes in the rendering logic as an object, we are passing the method reference to Gson's toJson method as the rendering logic here.

  • The post method, which uses the service's create method, uses Gson to transform the request body to a GeoLocation value.

We are now ready to test our application. Restart the application. Let's try to create two geolocations using the POST API and later try to retrieve them using the GET method:

  1. Execute the following cURL commands in your terminal one by one:

            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 41.803488, "longitude": -88.144040}' http://localhost:4567/geolocation
    
  2. This should give you an output similar to the following (pretty-printed for readability):

            {
              "latitude": 41.803488,
              "longitude": -88.14404,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
            curl -H "Content-Type: application/json" -X POST -d '{"timestamp": 1468203975, "userId": "f1196aac-470e-11e6-beb8-9e71128cae77", "latitude": 9.568012, "longitude": 77.962444}' http://localhost:4567/geolocation
    
  3. This should give you an output like this (pretty-printed for readability):

            {
              "latitude": 9.568012,
              "longitude": 77.962444,
              "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
              "timestamp": 1468203975
            }
    
  4. To verify whether your entities were stored correctly, execute the following cURL command:

          curl http://localhost:4567/geolocation
    
  5. It should give you output similar to the following (pretty-printed for readability):

            [
              {
                "latitude": 41.803488,
                "longitude": -88.14404,
                "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                "timestamp": 1468203975
              },
              {
                "latitude": 9.568012,
                "longitude": 77.962444,
                "userId": "f1196aac-470e-11e6-beb8-9e71128cae77",
                "timestamp": 1468203975
              }
           ]
    

There are several other configurations that you can make to SparkJava, such as changing the default port, using query parameters, and using path parameters. I'll leave that to you to experiment.

 

Conclusion


At the beginning of this chapter, we quickly saw an overview of what microservices are and how they benefit organizations by making it easier to manage and deploy independent services. We looked at an example of a geolocation tracker application to see how it can be broken down into smaller and manageable services. Next, we saw how to create the GeoLocationTracker service using the Spring Boot framework. We also learned how to expose our APIs that consume and read geolocations using Spring MVC. Next, we saw how to build the same application using WildFly Swarm, and JAX-RS. Later, we built the same application using Dropwizard. Finally, we saw how to implement the same service using the SparkJava framework.

I hope you now have a good understanding of what microservices are and how to create them using your favorite framework. The choice of framework completely depends on your needs and your current ecosystem. We strongly recommend you evaluate them before picking one. In the next chapter, we will learn how to package this microservice and later containerize it using Docker.

About the Author
  • Vikram Murugesan

    Vikram Murugesan is a software architect who has over 10 years of experience building distributed systems and products. He currently works as a principal architect with Egen Solutions Inc. In his current job, he focuses on building platforms based on JVM (Java, Scala, and Groovy), big data, and cloud technologies. He is a passionate programmer and is interested in learning new technologies. He is also interested in coaching, mentoring, and building scalable teams that build great software.

    Browse publications by this author
Latest Reviews (1 reviews total)
Good book and delivery service
Microservices Deployment Cookbook
Unlock this book and the full library FREE for 7 days
Start now