Learning objectives

Create a simple microservice that manages product reviews in a Cloudant NoSQL database.

Estimated time

It takes approximately 30 minutes to an one hour to read and follow the steps in this tutorial.

Prerequisites

To complete this tutorial, you need the following:

Once you’ve installed these tools, clone the sample application from GitHub to your local environment:


java
git clone https://github.com/gangchen03/refarch‑cloudnative‑micro‑socialreview.git

Steps

Step 1. Provision a Cloudant NoSQL DB in IBM Cloud

To provision the Cloudant service, you need an IBM Cloud account. Log in to your IBM Cloud account or register for a new, free account.

To create the Cloudant service, go to the Cloudant NoSQL DB service in the IBM Cloud catalog (remember to log in to your IBM Cloud account). To name your Cloudant service (for example, refarch-cloudantdb), select Rename Service from the ACTIONS drop-down menu in the list of services.

For testing, you can select the Lite plan, then click Create. Once created, open the credentials tab and note your Cloudant Service credentials. For example:


{
 'username': 'xxxx‑yyyy‑bluemix',
 'password': 'zzzzz',
 'host': 'xxxx‑yyyy‑bluemix.cloudant.com',
 'port': 443,
 'url': 'https://xxxx‑yyyy‑bluemix:zzzzz@xxxx‑yyyy‑bluemix.cloudant.com'
}

Click the Launch button to open the Cloudant management console. It’s empty now.

Step 2. Build the sample application with Gradle

Now, you can work on the application. Spring Boot application can be built with either Gradle or Maven. For this how-to, the instructions are for Gradle.

Navigate into the GitHub repository root folder refarch-cloudnative-micro-socialreview; you should find the build.gradle file in that folder. It defines the library dependencies and basic build configuration such as built output. The app uses the following dependencies:


java
compile("org.springframework.boot:spring‑boot‑starter‑web:1.4.0.RELEASE") {
    exclude module: "spring‑boot‑starter‑tomcat"
}
compile("org.springframework.boot:spring‑boot‑starter‑jetty:1.4.0.RELEASE")
compile("org.springframework.boot:spring‑boot‑starter‑actuator:1.4.0.RELEASE")
compile group: 'com.cloudant', name: 'cloudant‑spring‑boot‑starter', version: '0.0.2'
compile("junit:junit")
compile group: 'org.springframework.boot', name: 'spring‑boot‑starter‑test', version: '1.4.0.RELEASE'

Notice the dependency cloudant-spring-boot-starter. It ensures that the Cloudant Spring Boot Starter is downloaded and added to the project when you build it. When you run the Gradle build later, all the dependencies will be downloaded when it is first run.

Step 3. Understand the code

With Spring Boot, building cloud-native microservices app is pretty easy and straightforward. Under the root directory, most of the files and folders are build related. The application code is managed under the src folder. Take a look at these four classes:

  • socialreview.cloudant.Application: bootstrap and server
  • socialreview.cloudant.Review: entity representation of a review in the database
  • socialreview.cloudant.ReviewRestController: microservice REST API for reviews
  • socialreview.cloudant.ReviewRestControllerTest: sniff test of microservice REST API for reviews

Code review: src/main/java/socialreview/cloudant/Application.java

This is the bootstrap class that loads the web application and starts an embedded server.


java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        System.out.println("SocialReview Spring Boot Microservice is ready");
    }
}

The @SpringBootApplication is a convenience annotation that loads useful Spring components such as the @Configuration, @ComponentScan, and @EnableAutoConfiguration. It also adds the Spring webmvc to the classpath and activates the DispatcherServlet to start handling request.

The main function invokes SpringApplication.run to bootstrap the application.

Code review: src/main/java/socialreview/cloudant/Review.java

This is an entity class that maps to the document saved in Cloudant NoSQL database. Spring Boot framework automatically serializes the entity object with the response from the Cloudant database as well as converts it to JSON when sending the request back for the REST request.


java
public class Review {

    private String _rev;
    private String _id;
    private String comment;
    private int itemId;
    private int rating;
    private String reviewer_email;
    private String reviewer_name;
    private String review_date;

    public Review(){}

    public Review(boolean isStub) {
        this.comment = "It works";
        this.itemId = 13401;
        this.rating = 5;
        this.reviewer_email = "gc@ibm.com";
        this.reviewer_name = "Gang Chen";
        this.review_date = "08/18/2016";
    }

Code review: src/main/java/socialreview/cloudant/ReviewRestController.java

This is the main class that exposes the REST API and interacts with the Cloudant database to perform save and query operations.


java
@RestController
@RequestMapping("/review")
public class ReviewRestController {

    @Autowired
    private Database db;

The @RestController tells the Spring MVC to handle web requests with the root web context root as review.

When the Cloudant Spring Boot Starter is added as a dependency, it is automatically hooked into the Spring application configuration. Using properties provided in the application’s property source, the starter configures a Cloudant database bean that can be injected via dependency injection by specifying the @Autowired annotation.


java
// Create a new review
@RequestMapping(method = RequestMethod.POST, consumes = "application/json")
public @ResponseBody String saveReview(@RequestBody Review review) {
    System.out.println("Save Review " + review);
    Response r = null;
    if (review != null) {
        r = db.post(review);
    }
    return r.getId();
}

This code saves/persists a review comment document into the Cloudant database. It is a POST request. The Cloudant Java client makes the persistent simple with a single API call, db.post(review), shown above. On the other hand, the GET (query) function is a little bit more complex.


java
// Query reviews for all documents or by ItemId
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody List getAll(@RequestParam(required=false) Integer itemId) {
    // Get all documents from socialreviewdb
    List allDocs = null;
    try {
        if (itemId == null) {
            allDocs = db.getAllDocsRequestBuilder().includeDocs(true).build().getResponse()
                        .getDocsAs(Review.class);
        } else {
            // create Index
            // Create a design doc named designdoc
            // A view named querybyitemIdView
            // and an index named itemId
        db.createIndex("querybyitemIdView","designdoc","json",
            new IndexField[]{new IndexField("itemId",SortOrder.asc)});
            System.out.println("Successfully created index");
            allDocs = db.findByIndex("{\"itemId\" : " + itemId + "}", Review.class);
        }
    } catch (Exception e) {
      System.out.println("Exception thrown : " + e.getMessage());
    }
    return allDocs;
}

With the @RequestParam(required=false) Integer itemId parameter, you can query the entire review documents or just all reviews associated with a specific itemId. Getting all documents is easy, as there is a built-in API from Cloudant Java library to do that.

Query by itemId is slightly more complex. Cloudant database typically uses the MapReduce mechanism to perform queries. To achieve this, you normally create an index and save that in the design document (a special Cloudant document). It is only created once at the first use. Once the index is created, you can perform the query by invoking the index using db.findByIndex().

The returned object is serialized as a Review entity object in JSON format.

Code review: src/main/resources/application.yml


java
#Spring properties
spring:
  application:
     name: socialreview‑microservice

#Server configuration
server:
  context‑path: /micro
  port: 8080

#Cloudant Confiugration
cloudant:
  db: socialreviewdb
  username:
  password:
  url:

This file defines the application configuration such as name of the application, the base URL for the web app, and which port it runs on. I also put the Cloudant configuration information in this file. You need to update the cloudant configuration section to fill in the Cloudant instance credentials you created earlier. The db property is already set to socialreviewdb to configure the Cloudant client to direct all database requests to that database name.

Note: Use your Cloudant credential url or host property that doesn’t include the password for your account for the url entry in the application.yml file. For instances running on IBM Cloud, this will be the host value and the protocol. For example: https://xxxx-yyyy-bluemix.cloudant.com.

Code review: src/test/java/socialreview/cloudant/ReviewControllerTest.java

ReviewControllerTest is a simple integration test case that validates that the connection to Cloudant is successful and able to fetch all the documents. You can follow the instruction later to run the test case.

Step 4. Build and run the application

Once you have Cloudant configured, update the src/main/resources/application.yml file for the Cloudant credentials:

  • username
  • password
  • url

Note: Use your Cloudant credential url or host property that doesn’t include the password for your account for the url entry in the application.yml file. For instances running on IBM Cloud this will be the host value and the protocol. For example: https://xxxx-yyyy-bluemix.cloudant.com.

Under the repository root directory, run the following commands to build and run the application:


java
\$ cd refarch‑cloudnative‑micro‑socialreview
$ ./gradlew build


$ ./gradlew build

Make sure that the application build completes successfully. It packages the compiled application under build/libs directory. Now, you can run the application with the following command:


java
\$ java ‑jar build/libs/micro‑socialreview‑0.1.0.jar

Yes, the final distribution of the application is in a jar file and all you need to run is to execute the Jar file. The application should be running at port 8080. Open a browser with following URL: http://localhost:8080/micro/review.

This returns all the reviews in the database. You can use Chrome POSTMAN to insert a new review document, or use the following curl command to insert a review comment:


java
curl ‑‑request POST
  ‑‑url 'http://localhost:8080/micro/review' 
  ‑‑header 'accept: application/json' 
  ‑‑header 'content‑type: application/json' 
  ‑‑data @‑ <<'EOF'
  {"comment": "Nice product",
    "itemId": 13402,
    "rating": 3,
    "reviewer_email":"gangchen@us.ibm.com",
    "reviewer_name": "Gang Chen",
    "review_date": "12/31/2017"}'
EOF

It should return a Cloudant document ID upon successful execution. You can validate the operation by hitting the GET URL again: http://localhost:8080/micro/review?itemId=13402.

The saved review comment should be returned. Alternatively, you can launch the Cloudant database console and review the documents there as well.

To run the simple integration test, use the command:


java
\$ ./gradlew clean test

Summary

This post showed you how easily you can build a microservice application to access a Cloudant database using Spring Boot and Cloudant Java client.