Book Image

Microservices Deployment Cookbook

By : Vikram Murugesan
Book Image

Microservices Deployment Cookbook

By: Vikram Murugesan

Overview of 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.
Table of Contents (15 chapters)
Microservices Deployment Cookbook
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

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.