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.
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
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.”