Configuring the MicroProfile Rest Client

Invoke the MicroProfile Rest Client to provide a type-safe way to invoke RESTful services.

The information in this topic describes how to invoke the MicroProfile Rest Client with the mpRestClient-1.0 or mpRestClient-1.1 feature.
  • Use the mpRestClient-1.0 feature to invoke MicroProfile Rest Client 1.0. The mpRestClient-1.0 feature is part of the MicroProfile 1.3 programming model.
  • Use the mpRestClient-1.1 feature to invoke MicroProfile Rest Client 1.1. The mpRestClient-1.1 feature is part of the MicroProfile 1.4 and 2.0 programming models.

Open Liberty Documentation about MicroProfile Rest Client 1.2 or later is available on the Open Liberty website.

Before you begin

MicroProfile Rest Client 1.0 and 1.1 require Java SDK 8.

About this task

The MicroProfile Rest Client builds on the JAX-RS 2.0 Client APIs to provide a type-safe approach to invoke RESTful services over HTTP. You can write client applications with more model-centric code. Complete the following steps to create your own REST clients.

Procedure

  1. Create an interface that represents the remote service. Match the methods of the interface to the RESTful APIs of the endpoint.

    The following example shows a sample interface that accesses a service for online music.

    @Path("/playlist")
    @Consumes("application/json")
    public interface MusicPlaylistService {
    
        @GET
        List<String> getPlaylistNames();
    
        @GET
        @Path("/{playlistName}")
        List<Song> getPlaylist(@PathParam("playlistName") name)
            throws UnknownPlaylistException;
    
        @POST
        @Path("/{playlistName}")
        long newPlayList(@PathParam("playlistName") name, List<Song> playlist)
            throws PlaylistAlreadyExistsException;
    
        @PUT
        @Path("/{playlistName}")
        long updatePlayList(@PathParam("playlistName") name, List<Song> playlist)
            throws UnknownPlaylistException;
    }

    Like JAX-RS on the server side, the sample interface uses annotations like @Path, @Consumes, @GET, and @PathParam.

  2. Invoke methods that are defined in the interface.
    The sample interface defines methods that you can invoke.
    • Invoke the getPlaylistNames method to get the available names of playlists. The REST client implementation sends a GET request to the endpoint at the <baseUrl>/playlist location. This location accepts the application/json media type of a list of strings that indicate the available names of playlists.
    • Invoke the getPlaylist method to see which songs are included in a playlist. This method throws an UnknownPlaylistException error, which might also be indicated on the remote service and might return an HTTP 404 response.
  3. Use a ResponseExceptionMapper command to handle exceptions.

    The following example converts the HTTP 404 response to a specific exception.

    @Provider
    public class PlaylistResponseExceptionMapper implements
        ResponseExceptionMapper<BasePlaylistException> {
    
        @Override
        public boolean handles(int statusCode, MultivaluedMap<String, Object> headers) {
            return statusCode == 404  // Not Found
                || statusCode == 409; // Conflict
        }
    
        @Override
        public BasePlaylistException toThrowable(Response response) {
            switch(response.getStatus()) {
            case 404: return new UnknownPlaylistException();
            case 409: return new PlaylistAlreadyExistsException();
            }
            return null;
        }
    
    }
    In the example, both UnknownPlaylistException and PlaylistAlreadyExistsException cases are subclasses of the BasePlaylistException case. The toThrowable response returns an instance of the exception rather than throwing it.
  4. After you write the interface and response exception mapper, build the implementation and start it. You can build the implementation with either the RestClientBuilder API or Contexts and Dependency Injection (CDI) and MP Config.
  5. Optional: Use the RestClientBuilder API, which is more verbose but is useful in environments where CDI is not available, such as in testing.
    1. Create an instance of the RestClientBuilder API.
    2. Specify the baseURL URL of the remote endpoint, which is necessary before you build the client.
    3. Register the response exception mapper. If you need to register other provider classes, such as MessageBodyReaders, MessageBodyWriters, filters, or interceptors, register them with the register method.
    4. Build the client and pass in the interface class.
    5. Invoke methods on the client as you would with another Java™ object.

    The following example shows sample code that builds and invokes the implementation with the RestClientBuilder API.

    ...
    URL apiUrl = new URL("http://localhost:9080/onlineMusicService");
    MusicPlaylistService playlistSvc =
        RestClientBuilder.newBuilder()
                         .baseUrl(apiUrl)
                         .register(PlaylistResponseExceptionMapper.class)
                         .build(MusicPlaylistService.class);
    
    List<String> playlistNames = playlistSvc.getPlaylistNames();
    for (String name : playlistNames) {
        List<Song> songs = playlistSvc.getPlaylist(name);
        if (hasSongBy(songs, "band name")) {
            coolPlaylists.add(name);
        }
    }
    ...
  6. Optional: Use CDI and MP Config to instantiate the client.
    1. Install the mpRestClient-1.0 or mpRestClient-1.1 feature in the Liberty server.xml file.
    2. Add either the cdi-1.2 or cdi-2.0 feature.
    3. Add the mpConfig-1.1, mpConfig-1.2, or mpConfig-1.3 feature.
    4. Update the MusicPlaylistService interface with the following annotations:
      @Path("/playlist")
      @Consumes("application/json")
      @Dependent
      @RegisterRestClient
      @RegisterProvider(PlaylistResponseExceptionMapper.class)
      public interface MusicPlaylistService {
          ...
      The @Dependent annotation or another scope annotation, such as @ApplicationScoped or @RequestScoped, is required for CDI to detect and manage the Rest Client interface. The @RegisterRestClient annotation tells the MicroProfile Rest Client implementation to dynamically implement the interface. The @RegisterProvider annotation tells the MicroProfile Rest Client implementation code to register the specified provider class. You can repeat the @RegisterProvider annotation on the same interface for as many providers as you need.
    5. Inject the client into another managed object. Combine the @Inject annotation with the @RestClient decorator to tell CDI to inject an instance of the MusicPlaylistService interface:
      @WebServlet(urlPatterns = "/PlaylistServlet")
      public class PlaylistServlet extends HttpServlet {
      
          @Inject
          @RestClient
          private MusicPlaylistService playlistService;
      
          @Override
          public void doGet(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
      
              List<String> names = playlistService.getPlaylistNames();
              ...
    6. Use MP Config to indicate the baseUrl URL of the remote endpoint in the MP Rest Client implementation. Specify the <fullyQualifiedInterfaceName>/mp-rest/url configuration property with MicroProfile Config. One option is to set a system property in the jvm.options file:
      -Dcom.mypkg.MusicPlaylistService/mp-rest/url=http://localhost:9080/onlineMusicService

      CDI injection is simpler when you want to bootstrap the client. With MP Config, you can use different URLs for different environments, such as having one URL for test and another URL for production, without needing to change code.