The goal of this article is to give you an overview of the MicroProfile Rest Client (aka Rest Client), how it works and the advantages you can obtain when utilizing it to implement a Java REST client.

When we talk about microservices, we discuss many different architecture topics, but sometimes we forget the importance of a good client API. The Rest Client is a Java REST client based in JAX-RS 2.0, that uses its current features, but also provides a different way of interacting with the microservices. The 1.0 version of Rest Client was first introduced in MicroProfile version 1.3 — early in January 2018 — and it is the one currently supported by TomEE 8. For details of the TomEE 8 MicroProfile release check this blog post.

This Rest Client API simplifies access to REST-based microservices. It has the concept of type safety, which in this context, means you don’t need to worry about object transformation; it is implicit in the response and in the microservices parameters enforced by the Rest Client.

Now, let’s see how to use the Rest Client in practice. The example below will show you a microservice and then how to access it using the Rest Client.

MoviesResource Microservice

This is a simple JAX-RS microservice with no additional configuration. Note that the MoviesService is not required, it was just added to separate the business logic from the resource.

import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@Path("movies")
@ApplicationScoped
public class MoviesResource {

    @Inject
    private MoviesService service;

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Movie find(@PathParam("id") Long id) {
        return service.find(id);
    }
}

MoviesResource Client

Below is the client interface that you can use to make calls to the JAX-RS microservice. The client interface is very similar to the microservice itself. Therefore, what you need to do to make a client is basically copy paste the resource, make it an interface and make the methods abstract.

import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@Path("movies")
@RegisterRestClient
public interface MoviesResourceClient {

   @GET
   @Path("{id}")
   @Produces(MediaType.APPLICATION_JSON)
   public Movie find(@PathParam("id") Long id);
}

By doing this, you will be able to have direct access to the methods within the client.

Using client with CDI

The @RegisterRestClient annotation makes the client usable through CDI.

To inject a CDI bean you need to do the following:

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.eclipse.microprofile.rest.client.inject.RestClient;

@ApplicationScoped
public class CinemaService {
   @Inject
   @RestClient
   private MoviesResourceClient movieClient;
....
}

The @RestClient annotation is a qualifier required in the injection for a client to be identified within the CDI beans.

Calling a microservice method

Then calling a microservice method will be as simple as this:

public Movie getNextMovie(Long movieId){
      return movieClient.find(movieId);
}

Some of the advantages of using this approach are that you don’t need to look for a contract somewhere, as the contract will be available for you as you develop. Also, issues with type or mistakes not following the contract won’t happen anymore, as the contract is enforced while you use the microservice.

Adding URL with Microprofile Config

For the Rest Client to know the URL it uses the MicroProfile Config implementation, thus it will get the configuration with the URL from the META-INF/microprofile-config.properties. The property for the specific client will be configured like the following:

com.tomitribe.MoviesResourceClient/mp-rest/url=http://localhost:8080

RestClientBuilder approach

There is another way to use the Rest Client, the RestClientBuilder (builder). The builder will help you to get an instance of the client and also allow you to add configurations dynamically.

import org.eclipse.microprofile.rest.client.RestClientBuilder;

public Movie getNextMovie(Long movieId){
   MoviesResourceClient movieClient = RestClientBuilder.newBuilder().build(MoviesResourceClient.class);
   return movieClient.find(movieId);
}

Using the builder you will be able to change the base URI/URL, register JAX-RS providers and set the ExecutorService programmatically. We won’t cover this in detail here. If you want to know more about using builders check out the specification.

This was an overview of Microprofile Type-Safe Rest Client, in the next article we will be posting a tutorial on how to use it with TomEE 8.

Ivan Junckes Filho

Ivan Junckes Filho

Ivan joins the Tomitribe Product Team with 8+ years of software development experience, including several years at IBM. He is a passionate developer contributing to open-source projects: Eclipse JNoSQL, MicroProfile, and TomEE. He likes sharing interesting technical content with the Community through speaking engagements and blogging.
ivanjunckes

2 Comments

  • colonel says:

    Hi,

    Let me know if it is possible to use an object javax.ws.rs.core.Response instead of directly an object Movie in the interface Rest client?
    @Path(“movies”)
    @RegisterRestClient
    public interface MoviesResourceClient {

    @GET
    @Path(“{id}”)
    @Produces(MediaType.APPLICATION_JSON)
    public Response find(@PathParam(“id”) Long id);
    }

    thx

    • Ivan Junckes Filho says:

      Yes, you can use Response. This is what the spec says: “If you only need to inspect the body, you can provide a POJO can be processed by the underlying MessageBodyReader or MessageBodyWriter. Otherwise, you can receive the entire Response object for parsing the body and header information from the server invocation.”

Leave a Reply