What’s new with REST in Open Liberty in 2018?

Originally posted on December 5, 2018 at:
https://openliberty.io/blog/2018/12/05/REST-Liberty-reactive-2018.html

It’s been a few months since you heard from us, so we wanted to check in and let you know about a few things we’ve been working on and a preview of what we’ve got in the 18.0.0.4 release of Open Liberty.

First, let’s take a look back at what we’ve done earlier this year. Over the summer, we shipped JAX-RS 2.1 in Open Liberty 18.0.0.2. This adds powerful new features like the Reactive Client, Server Sent Events, and more. If you missed it, check out our 18.0.0.2 blog post.

In September, we delivered the MicroProfile Rest Client 1.1 in Liberty 18.0.0.3. This adds asynchronous methods, URI support, better integration with CDI and a RestClientBuilderListener for third-party libraries to integrate with client instances.

While our upcoming 18.0.0.4 release won’t have any blockbuster spec implementations, we have still been hard at work. Here are some of the things we’ve been working on:

New async transport layer

We integrated the Apache HTTP Client transport layer from the CXF project. This improves asynchronous method invocations – in some performance benchmarks, we measured a 20-25% improvement in throughput (your mileage may vary).

Connection pooling enhancements

The JAX-RS client has had HTTP connection pooling for a while, but HTTPS connections were not being pooled. As more and more services require HTTPS (this is a good thing!), it can be a burden for systems to construct, tear down and reconstruct connections to the same endpoint. Starting with Liberty 18.0.0.4, HTTPS connections are now pooled.

Reactive extensions

JAX-RS 2.1 introduced the reactive client, but the spec only requires vendors to implement it using Java 8’s CompletionStage API. Other reactive frameworks can integrate with the reactive client, but that is optional in the spec. With Liberty 18.0.0.4, it is now possible to use these extensions. We’ve tested with RxJava 1 and 2 using providers from Apache CXF and Jersey, and we plan to test more. If there is a particular reactive technology that you would like to use, and it has a JAX-RS RxInvokerProvider implementation, please let us know!

Properties handling in the MicroProfile Rest Client

The RestClientBuilder and MicroProfile Config allows users to specify custom properties to the Rest Client instance. Now, you can use JAX-RS Client properties, such as:

  • com.ibm.ws.jaxrs.client.keepalive.connection – which you can set to close to prevent keeping connections alive for multiple requests
  • com.ibm.ws.jaxrs.client.connection.timeout – milliseconds to wait for the HTTP connection to be established before timing out
  • com.ibm.ws.jaxrs.client.receive.timeout – milliseconds to wait for a response from the remote service once the connection has been established
  • com.ibm.ws.jaxrs.client.proxy.host – hostname of the proxy server to use for requests from this client instance
  • com.ibm.ws.jaxrs.client.proxy.port – port number of the proxy server to use for requests from this client instance

Other bug fixes and minor enhancements

We’re constantly trying to improve the JAX-RS and MicroProfile Rest Client implementation. Sometimes we find things to fix on our own, and sometimes our users help us find bugs to fix. If you discover a bug or can think of something that we can do in Open Liberty to make it better, please let us know! The best way is probably to open an issue in GitHub, but you can also talk with us on the Open Liberty mailing list.

Thanks for checking in with us; we hope you enjoy our 18.0.0.4 release!

Introducing MicroProfile Rest Client 1.0

Originally posted on January 31, 2018 at:
https://openliberty.io/blog/2018/01/31/mpRestClient.html

The Liberty application server now offers the mpRestClient-1.0 feature. This is the implementation of the MicroProfile Rest Client 1.0 API spec released in December 2017. You can try out the MicroProfile Rest Client in our Open Liberty guide.

The MicroProfile Rest Client builds on JAX-RS 2.0 client APIs to provide a type-safe approach for invoking RESTful services. This means writing client applications with more model-centric code and less ‘plumbing’. Although these are client APIs, they are deployed in a server.

Here is a quick run-down of how to create your own REST clients:

The interface

First, we start off with an interface that represents the remote service. The methods of the interface should match the RESTful APIs of the endpoint. So if we want to access a service that provides online music and allows us to view and modify playlists, we might create an interface that looks like this:

@Path("/playlist")
@Consumes("application/json")
public interface MusicPlaylistService {

    @GET
    List<String> getPlaylistNames();

    @GET
    @Path("/{playlistName}")
    List<Song> getPlaylist(@PathParam("playlistName") String name)
        throws UnknownPlaylistException;

    @POST
    @Path("/{playlistName}")
    long newPlayList(@PathParam("playlistName") String name, List<Song> playlist)
        throws PlaylistAlreadyExistsException;

    @PUT
    @Path("/{playlistName}")
    long updatePlayList(@PathParam("playlistName") String name, List<Song> playlist)
        throws UnknownPlaylistException;
}

Just like JAX-RS on the server side, this interface uses annotations like @Path, @Consumes, @GET and @PathParam. From this, we know that when a user invokes the getPlaylistNames method, the MicroProfile Rest Client implementation sends a GET request to the endpoint at <baseUrl>/playlist. The GET request accepts the application/json media type of a list of strings indicating the available names of playlists.

ResponseExceptionMappers

To see what songs are in a given playlist, invoke the getPlaylist method. Notice that this method throws an UnknownPlaylistException – this situation might be indicated on the remote service as returning an HTTP 404 response. In order to convert this response to a specific exception, we need a ResponseExceptionMapper like this:

@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;
    }

}

This code assumes that both UnknownPlaylistException and PlaylistAlreadyExistsException are both sub-classes of BasePlaylistException. Notice that the toThrowable returns an instance of the throwable rather than throwing it.

Implementation

Now that we have the interface and response exception mapper written, we just need to build the implementation and then invoke it. There are two ways to build the implementation: using the RestClientBuilder API or using CDI and MicroProfile Config. We’ll start with the RestClientBuilder – it is a little more verbose but can come in handy in environments where CDI is not available, like testing.

RestClientBuilder

...
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 of Horses")) {
        coolPlaylists.add(name);
    }
}
...

First we create a new instance of the RestClientBuilder. We must specify the baseUrl value for the remote endpoint – this is required before building the client. Next, we register the response exception mapper. If we need to register other provider classes like MessageBodyReaders or MessageBodyWriters, filters, interceptors, etc., we would do that here with the register method. Then we build the client, passing in the interface class. After that we can invoke methods on the client like it was any other Java object.

CDI and MicroProfile Config integration

It is also possible to let CDI instantiate the client. For all of the code we have covered so far, the user only needs to install the mpRestClient-1.0 feature in the Liberty server.xml. In order for this CDI approach to operate, we need to add two more features: cdi-1.2 (or 2.0) and mpConfig-1.1 (or 1.2). First, we need to update the MusicPlaylistService with some new annotations:



@Path("/playlist")
@Consumes("application/json")
@Dependent
@RegisterRestClient
@RegisterProvider(PlaylistResponseExceptionMapper.class)
public interface MusicPlaylistService {
    ...

The @Dependent and @RegisterRestClient annotations declare that this interface is to be managed by CDI. The @RegisterProvider annotation tells the MicroProfile Rest Client implementation code to register the specified provider class. This annotation can be repeated for as many providers as necessary. Now we can inject the client in another managed object like this:

@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();
        ...
    }

The @Inject combined with the @RestClient decorator tells CDI that we want to inject an instance of the MusicPlaylistService interface. There is still one more step…​ we need to tell the MicroProfile Rest Client implementation the baseUrl value for the remote endpoint. For that, we use MicroProfile Config. The config property to use is <fullyQualifiedInterfaceName>/mp-rest/url. So you could specify this as a system property in the jvm.options file like this:

-Dcom.mypkg.MusicPlaylistService/mp-rest/url=http://localhost:9080/onlineMusicService

CDI injection makes things a lot simpler when it comes to bootstrapping the client and, with MicroProfile Config, it is possible to use different URLs for different environments; for example, use one URL for test and another URL for production, without needing to change code.

Additional Information

For more information on the MicroProfile Rest Client, see the MicroProfile Rest Client 1.0 spec

Get involved in the MicroProfile community at: https://microprofile.io

My Favorite Part of JAX-RS 2.1: An Implementer’s View

Originally posted on September 19, 2017 at:
https://www.linkedin.com/pulse/my-favorite-part-jax-rs-21-implementers-view-j-andrew-mccright/

In the Spring of 2016, my manager asked me to take the JAX-RS team lead rolefor WebSphere. This responsibility included participation in the Apache CXF open source community and the JAX-RS 2.1 (JSR 370) expert group. I haven’t had much experience in the open source community, and I was definitely not an expert in JAX-RS. Nevertheless, both of these communities accepted me with welcome arms. I mention this mainly to encourage anyone interested in joining either of these communities, but also to highlight my inexperience with this technology. Over the last year and a half, I have learned a lot – and I hope to be able to share some of that knowledge in this article.

The Java API for RESTful Web Services (JAX-RS) is an amazing technology. It makes the development of RESTful services very simple – using POJOs and annotations, but also allows for more complex edge cases. JAX-RS 2.0 further advanced the technology adding powerful features like filters and interceptors, and a Client API that rivals many third party APIs (like the Apache Wink client API or Apache Commons HTTP Client). By doing this in the JAX-RS spec, the user is no longer tied to a particular vendor.

JAX-RS 2.1 continues to advance RESTful services in Java. There are quite a few minor updates – like the addition of the @PATCH annotation to easily enable the increasingly popular PATCH HTTP method, and better support for executors in both the client and server APIs. Perhaps the biggest splash in JAX-RS 2.1 is the Reactive Client. JAX-RS 2.1 requires Java 8, so now it can utilize some of the Java 8 language features like lambda expressions – this can make for some very powerful client code when reacting to server responses.

Still, my favorite part of the JAX-RS 2.1 spec has to be Server Sent Events (SSE). As a former runtime guy and as a father of three, I can say unequivocally that polling stinks (“Are we there yet? Are we there yet? How about now?”). Other tricks for handling server originated responses (like long polling) are better, but only SSE really makes sense.

SSE was first introduced in HTML5. The idea is that a client (often a browser, but doesn’t have to be) will create an HTTP connection to the server and send it’s initial request, but instead of closing the connection, the client and server will keep the connection open, and the server will send data to the client at it’s own pace. The client can then process this data as events. Either side can close the connection. No more polling or tricks – we finally have a legit “pub/sub” type model in the web.

JAX-RS 2.1 makes SSE easy to implement – both as a client or a server. Let’s use a music radio service (like Pandora, or Spotify, etc.) as an example. We want a RESTful service that will tell us what we are listening to, who sings it, etc.

    @GET
    @Path("/songDataStream")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void songDataStream(@Context SseEventSink eventSink, @Context Sse sse) {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        Song song = RadioService.getCurrentSong();
        while (song != null) {
          OutboundSseEvent event = sse.newEventBuilder()
                                      .mediaType(MediaType.APPLICATION_JSON_TYPE)
                                      .data(Song.class, song)
                                      .build();
          eventSink.send(event);
          try {
            Thread.currentThread().sleep(song.timeRemaining());
          } catch (InterruptedException ex) {
            // ...
          }
        }  
      }
    }

Ok, this could probably be implemented better, but it shows how simple it can be to write a resource that will fire server sent events. What might the client code look like?

Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost/RadioSvc/rest/songDataStream");
try (SseEventSource source = SseEventSource.target(target).build()) {
  source.register(new Consumer<InboundSseEvent>(){

    @Override
    public void accept(InboundSseEvent event) {
      // called when we receive a new event
      Song song = event.readData(Song.class);
      System.out.println("Now playing " + song.title() + " by " + song.artist());
    }}, new Consumer<Throwable>(){

      @Override
      public void accept(Throwable t) {
        // called when something went wrong
        t.printStackTrace();
      }}, new Runnable() {

        @Override
        public void run() {
          // called when our connection is closed
          System.out.println("All done for now!");                            
        }});

  source.open();
  Thread.sleep(3600000);      // Consume song events for one hour

} catch (InterruptedException e) {
  e.printStackTrace();
}

Both of these examples assumes that the Song class can be easily converted interceptors JSON and back – otherwise, you may need a MessageBodyReader and MessageBodyWriter. But otherwise we’ve got a very straightforward example of sending and receiving server sent events.

Since SSE is part of the HTML5 spec, you don’t need JAX-RS. Most browsers (all major browsers except for Microsoft Internet Explorer) will support SSE. So we could create a simple web page to show what song is playing in HTML and JavaScript, like this:

<!DOCTYPE html>
<html>
<head>
  <title>SSE Radio - Now Playing</title>
</head>
<body>
  <h2>Now Playing:</h2>
  <div id="song">Song: </div>
  <div id="artist">Artist: </div>
  <script>
    var source = new EventSource('rest/songDataStream');

    source.onmessage = function(e) {
        var song = JSON.parse(e.data);
        document.getElementById("song").innerHTML = 'Song: ' + song.title;
        document.getElementById("artist").innerHTML = 'Artist: ' + song.artist;
      };
  </script>
</body>
</html>

If you package that HTML page with your web application, and then browse to it, it will receive song events from the server and automatically update the web page without a full page refresh. Very efficient!

The examples above show how to send data back to a specific client. If multiple clients invoked the songDataStream resource method, each method invocation would create a new thread that would send data specifically to that user. It might turn out to be the same event data – that would depend on the implementation of the business logic in the RadioService. But if you wanted to ensure that all active clients saw the same data, you could use a Broadcaster like this:

    @Context
    private Sse sse;

    private static SseBroadcaster broadcaster;

    private synchronized static SseBroadcaster getBroadcaster(Sse sse) {
        if (broadcaster == null) {
            broadcaster = sse.newBroadcaster();
        }
        return broadcaster;
    }

    @GET
    @Path("listen")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void listen(@Context SseEventSink sink, @Context Sse sse) {
        SseBroadcaster b = getBroadcaster(this.sse);
        b.register(sink);
    }

  @PUT
  @Path("playSong")
  public Response playSong(@PathParam("songId") String songId) {
    Song song = RadioService.getSong(songId);
    SseBroadcaster b = getBroadcaster(this.sse);
    OutboundSseEvent event = sse.newEventBuilder()
                                .mediaType(MediaType.APPLICATION_JSON_TYPE)
                                .data(Song.class, song)
                                .build();
        b.broadcast(event);
  }

In this example, multiple clients can “subscribe” to the radio station by invoking the “listen” SSE resource method. Then whenever somebody invokes the normal “playSong” resource method, all subscribing clients will receive the event with the newly selected song data. Both the JAX-RS client and JavaScript examples above would work with this broadcasting example – the only change necessary would be the URL.

Hopefully, you can see why I like this technology so much. It is a simple yet efficient way to send data to interested clients. Be sure to keep an eye out for this technology on WASdev.net – the next WebSphere Liberty Beta will have this tech preview. If you want a sneak peak, you can also see JAX-RS 2.1 in action in the newly-available Open Liberty project.