Hybrid Deployments

Java Microservices with MicroProfile – Rest Client and JSON-B

Share this post:

MicroProfile Rest Client and JSON-B make working with REST easier

The RESTful design architecture is here to stay, just as how HTTP, which REST closely imitates, has withstood the test of time as our primary way of navigating the Internet. It’s a great model for user-server communication, and implementing the REST architecture style in your microservice application brings many benefits, including great performance, scalability, and simplicity. To help us effectively implement REST, we have powerful languages, such as Java, that provide us with a vast library of convenient tools to use. Today’s blog will highlight two features—MicroProfile’s Rest Client 1.0 and JSON-B—and how to build them into your Java EE microservice application to help you achieve these benefits.

Simply stated, MicroProfile Rest Client and JSON-B make working with REST easier. MicroProfile Rest Client organizes your code, making the invocation of certain RESTful services seem more natural; JSON-B makes converting a Java object to JSON and back child’s play.

MicroProfile

To demonstrate these features in action, we will be using IBM’s BlueCompute storefront application on GitHub as our sandbox . This repository hosts a Spring Boot implementation, and more recently, a MicroProfile version. For those who enjoy hands-on experience or want the extra supplementary material to explore while reading this blog, I encourage you to download and try the application yourself.

A quick recap of this Java Microservices series

In our last installment, we covered how to easily create RESTful APIs with Eclipse MicroProfile. In today’s installment, I’ll cover MicroProfile’s Rest Client 1.0 and JSON-B features.

For those who may have joined late, this blog series is based on my team’s experience migrating our simple storefront application from a Spring Boot-based microservices to MicroProfile, an optimized microservices programming model for enterprise Java. It was originally coded using Spring Boot (source code) and migrated to MicroProfile (source code). Both the projects are hosted on GitHub with source code and full documentation.

If you would like more background on Java microservices architectures:

You can also explore the Open Liberty guides to become a MicroProfile master.

BlueCompute’s microservice implementation in Spring Boot

JSON: In actuality, plenty of libraries already exist that can format objects into JSON. From my experience, JSON-java and Gson have seen the most common and persistent use. In the Spring Boot-based implementation of the BlueCompute app, we built a RESTRequest class that uses StringBuilder to manually, but programmatically, construct our responses.

Rest Client/Cloudant: To paint a better picture of how our Rest Client works, let’s first cover how we make REST calls. Please refer to the code excerpt below:

// RESTRequest.java

// Prepare to make the connection
HttpsURLConnection connection = null;
URL url = new URL(baseUrl + target);
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslContext,getSocketFactory());
connection.setRequestMethod("POST");

// Write the body data and send the request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(body);
wr.close();

int responseCode = connection.getResponseCode();

I’ve omitted some of the finer details, such as the writing of the body or payload, but for the most part, this code reflects one-for-one what we have in the RESTRequest class. You can split this code into three distinct sections:

  1. Making the connection
  2. Sending the request
  3. Checking the response code

The snapshot shows a bit of the complexity required to make an effective REST call, at least in the way we’ve implemented using a Spring framework.

With MicroProfile, we’ll eventually use the RESTful API to communicate with our Cloudant database. Spring uses Cloudant’s external library instead, so it’s a matter of personal coding preference here. Still, it’ll be good to compare what your code would look like depending on which approach suits your preference.

// CustomerController.java

private Database cloudant;
@Autowired
private CloudantPropertiesbean cloudantProperties;

private void init() throws MalformedURLException {
    ...
    ...
    final CloudantClient cloudantClient = ClientBuilder ...
    cloudant = cloudantClient.database(cloudantPropeties.getDatabase(), true);
}

private Database getCloudantDatabase() {
    return cloudant;
}

ResponseEntity<?> getbyId( ... ) {
    ...
    Customer cust = getCloudantDatabase().find(Customer.class, customerId);
    return ResponseEntity.ok(cust);
}

The BlueCompute store app’s CustomerController constructs its database with properties and some admin-level setup that I’ve omitted. The two key observations are the getter, getCloudantDatabase(), and the method which we call, find() given a customerId. Although maybe more rigid and structural in approach, most developers follow this coding pattern for tighter handling of what’s happening.

The journey from Spring Boot to MicroProfile

While transitioning from Spring Boot to MicroProfile, we updated our approaches. As you may have guessed by now, we added JSON-B and restructured how we make REST requests. The journey didn’t even feel particularly bumpy, with the Open Liberty guides giving some great pointers and interactive tutorials. Let’s review some of the details.

JSON-B: Among a few other core principles, Java EE prides itself on JSON-B’s ease of use. For example, when it comes down to converting a Java object to JSON out of the box, you only need two lines of code. JSON-B really simplifies that job for Java EE developers and additionally provides the option to customize their object mapping to remain flexible and powerful.

We use JSON-B in the Catalog microservice of the storefront app where we’d like to easily manipulate our items repository. Below is a simplified version of such items we’ll be playing with (you can view the full item class here):

// Item.java

public class Item {
    private long id;
    private String name;
}

When it comes down to making an item for a database, it doesn’t really get much simpler than this. We make a unique ID to represent the item in our database and give it a human-friendly name. With that, all we’d need now is to initialize a JSON-B object and start playing with it:

// ElasticSearch.java

public void printJson() {
    Item item = new Item(1, "calculator");

    Jsonb jsonb = JsonBuilder.create();
    String jsonString = jsonb.toJson(item);

    System.out.println(jsonString);
}

The output comes out as {"id":1,"name":calculator}. With a little bit of extra string manipulation, you could construct whole REST requests very easily, similar to how loadRows() does it in our Catalog’s Elastic Search. That’s mostly as far as we got with using JSON-B, but as mentioned earlier, you can easily deserialize your JSON back to a workable Java object and use your own custom mapper, if required.

Rest Client: The journey takes a wild turn here regarding how we use the Cloudant database in our Customer microservice. Compared to our Spring implementation, where we used Cloudant’s external library to accomplish our tasks, our MicroProfile implementation replaces Cloudant’s REST API with our shiny new Rest Client.

Although you can create your Rest Client with either CDI or RestClientBuilder, both will involve at least creating an interface. I know setting this up requires a bit of preparation, but it’ll be worth it. I’ve barely abridged the code in this snapshot (you can view the full file here):

// CloudantClientService.java

@Dependent
@RegisterRestClient
@Produces("application/json")
@RegisterProvider(UnknownCustomerExceptionManager.class)
@Path("/customers")

public interface CloudantClientService {

    @GET
    @Path("/_design/username_searchIndex/_search/usernames")
    @Produces("application/json")
    public Response getCustomerByUsername( ... ) throws UnknownCustomerException;
}

I know we used a lot of keywords here, so let’s go one annotation at a time:

  • @Dependent and @RegisterRestClient make this interface get built automatically when using CDI.
  • @Produces tells you what format to return, be it JSON or String text.
  • @RegisterProvider connects your custom exception managers, which allows you to program different ways to react to different HTTP codes.
  • @Path and @GET should look familiar to the JAX-RS on the server’s side, which this interface also takes in.

After that’s done and pasted, add the REST API calls. For us, we’re simply retrieving the username given an ID from Cloudant. Our code to get the customer looks like this:

// CustomerService.java

@Inject
@RestClient
private CloudantClientService CloudantClient;

@Inject
private JsonWebToken jwt;

@GET
@Produces("application/json")
public Response getCustomerByUsername() {
    String username = "usernames:" + jwt.getName();
    return CloudantClient.getCustomerByUsername(username, "true");
}

Although the method to find the username looks almost exactly the same, we no longer have to use a private getter to access Cloudant. However, the real magic lies in what you don’t see. Besides having less visible code for a more natural object-oriented coding style, we completely changed how we invoke remote REST calls by letting our Rest Client manage all our connections and calls. Review the code we used in RESTRequest.java in our Spring implementation and notice that we no longer need it. This simplifies our code base. Even if we had to add an interface for the REST API, it’s a form of organization that also makes the code base less rigid.

For further supplemental reading, a great resource I’d recommend to check out is Open Liberty’s Rest Client blog and guide. The blog provides an excellent description and introduction to Rest Client, while the guide provides a demo for that walkthrough-tutorial feel. I relied on Open Liberty articles on my journey to MicroProfile; their friendly presentation style definitely helps any developer feel at ease when working with a new feature.

My experiences and impressions of MicroProfile

JSON-B, one of the many flavors of working with JSON, allows very quick and very simple serialization and deserialization of Java objects. For the off-the-rails cases for serializing custom objects, you can even customize your own mappings to expose specific public or private fields. Once you’ve figured out how your information gets digested between services, you then have to figure out communication between services. Rest Client provides that ability.

As noted earlier, Open Liberty’s Rest Client blog and guide were a huge help. They’re definitely a great addition to the MicroProfile suite for seasoned programmers and works-in-progress alike. I could have gone into this new tech cold, but the Open Liberty guides were there to ease the trip.

This blog only covers two features in the MicroProfile suite—Rest Client and JSON-B. Be sure to read the other blog posts in this series that cover more topics (see Migrating Java Microservices from Spring Boot to MicroProfile for a series introduction). The code snippets shown were simplified versions of the Java Microservices on Kubernetes code available on GitHub.

TL;DR: Rest Client is a great feature to the MicroProfile suite for using RESTful services and Open Liberty guides does an excellent job as a resource.

Software Developer

More Hybrid Deployments stories
November 27, 2018

Rationales and Resources for Running in the Cloud

If you're ready to transform your business, grow as a company and disrupt your industry, running in the IBM Cloud is your next step. Here's why . . .

Continue reading

November 21, 2018

Scaling Your Java MicroProfile-Based Microservices App (3 of 3)

Small errors can propagate into large problems (especially in a microservice architecture in a distributed systems environment) if you don't plan for fault tolerance! This final entry compares and contrasts the Spring Boot and MicroProfile approaches to handle the inevitable.

Continue reading

November 19, 2018

Deploying IBM Cloud Private on Amazon Web Services (AWS)

You can run IBM Cloud Private on IBM's public cloud, but you can equally run it on other public clouds, such as Amazon's AWS or externally on a third-party computing platform. To achieve the best outcome of running IBM Cloud Private on AWS, proper planning and operation are required. This series documents best practices based on proven experience working with clients.

Continue reading