resteasy client tutorial resteasy client tutorialIn this tutorial we will present you the RESTEasy client API  features and a little bit about the JAX-RS 2.0 specification for client side.
One of the lacks of JAX-RS 1.1 was the absence of a well defined client API. In Java, as in any other programming language, we have lots of resources to perform HTTP request and read its response, but these resources are not JAX-RS aware, which means that, consequently, they are not RESTful aware.


At this moment, we depend of proprietary implementation of the JAX-RS client side. RESTEasy, the JBoss JAX-RS implementation, 1.x and 2.x has a great client API that helps you to easily consume REST web services in a JAX-RS way. You can take advantage of all the JAX-RS resources like body parsing (using MessageBodyReader and MessageBodyWriter) and a “more RESTful way” to consume WS using Path and Query parameters. This API with the embedded container also helps you to unit test your JAX-RS resources.
Today we will show how to create clients to existing RESTful API and the resources from RESTEasy you can use. All the samples showed are in the compressed Eclipse project.

Working with the examples

All the examples of this article are attached to this article in the form of an Eclipse project. We use RESTeasy 2.3.1, but you don’t need to worry about that because the attached zip contains everything necessary to run your project. You just need to import it in an Eclipse IDE.
The IDE version I used was “Version: Indigo Service Release 1”. Have fun!

Creating simple requests with the ClientRequest class

The simpler way to create an individual HTTP request is using the org.jboss.resteasy.client.ClientRequest class. Let us say if you want to retrieve the www.mastertheboss.org code, you just need to do the following:

        ClientRequest cr = new ClientRequest("http://www.mastertheboss.com/");
        String result = cr.get(String.class).getEntity();
        System.out.println(result);


The code above will simply perform a GET to the site http://www.mastertheboss.com/ and the response will be parsed into a String. It’s enough to create a request and get the result as a plain String. But let us say if we are consuming a more complete API and you have lots of URIs to consume. You also might want to set query parameters (parameters that resides in URL in a GET request) or other stuff. The following piece of code show how to access some read-only(then only the GET verb will be used) methods of the famous Twitter REST API:

        // A factory for the Twitter REST API
        ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(
                "http://api.twitter.com/1").build());

        // What is trending?
        ClientRequest trendsRequest = crf
                .createRelativeRequest("/trends/1.json");
        String trends = trendsRequest.get(String.class).getEntity();
        System.out.println(trends);

        // The information of some Twitter's accounts
        ClientRequest userInfoRequest = crf
                .createRelativeRequest("/users/show.json");

        // RESTEasy's twitter information
        userInfoRequest.queryParameter("screen_name", "resteasy");

        System.out.println(userInfoRequest.get(String.class).getEntity());
        userInfoRequest.clear();

        // OpenShift's twitter information
        userInfoRequest.queryParameter("screen_name", "openshift");
        System.out.println(userInfoRequest.get(String.class).getEntity());

As you can see above we can reuse the request and change query parameter according our necessity.
So far of the main problems when dealing with RESTful Web Services remains, which is parse the body of the HTTP response to some object or simple get the useful information from a request. RESTEasy Client helps you with it using its built-in provider for most of the known formats of the WEB such as XML and JSON. All you have to do is to create a domain object and make it be recognizable by RESTEasy, so it can parse the response to it. RESTEasy has a JAX-B provider, and if you want to use it, you just need to use the JAX-B annotations in your model class. In the following example we use the XML parser, but you can user JSON or other providers as well.
@XmlRootElement(name = "user")
    public static class TwitterUser {
        private String id;
        private String name;
        private String description;
        private String location;

// Gets and sets...

        @Override
        public String toString() {
            return "Name: " + this.getName() + "\nDescription: "
                    + this.getDescription();
        }

    }

In this object we are omitting some XML attributes on purpose, but if you want to access other parameter, just declare it as a private String and create the get/sets methods. We can now parse the HTTP’s response body to our object:
        // The information of some Twitter's accounts
        ClientRequest userInfoRequest = new ClientRequest(
                "http://api.twitter.com/1/users/show.xml");

        // RESTEasy's twitter information
        userInfoRequest.queryParameter("screen_name", "resteasy");
        TwitterUser resteasy = userInfoRequest.get(TwitterUser.class)
                .getEntity();
        System.out.println(resteasy);
        userInfoRequest.clear();

        // OpenShift's twitter information
        userInfoRequest.queryParameter("screen_name", "openshift");
        TwitterUser openshift = userInfoRequest.get(TwitterUser.class)
                .getEntity();
        System.out.println(openshift);
        userInfoRequest.clear();
        
        // William's twitter information
        userInfoRequest.queryParameter("screen_name", "william_antonio");
        TwitterUser william = userInfoRequest.get(TwitterUser.class)
                .getEntity();
        System.out.println(william);

So far we talked only about GET request, but obviously it’s possible to create POST, PUT or DELETE request with the org.jboss.resteasy.client.ClientRequest class. You just need to call the appropriate method and set the parameters correctly.

This is the simplest way to build HTTP requests with the client API. Of course we have much more features that are out of scope of this article because we have a few things to show, but the documentation will help you to learn more about it.


RESTEasy Proxy client

This is, in my opinion, the most excited way of creating client when using RESTEasy client. You can create an interface that describe your REST request in the JAX-RS way and then use it to create a proxy that will use the JAX-RS annotations and perform requests to the server. It’s pretty simple and has a lot of advantages over the ClientRequest class, but also presents a few disadvantages. You have to choose the right client according your necessities.
To use the Proxy client the first thing you have to do is create an interface with the corresponding JAX-RS annotations. Let us say we want to consume the Master The JBoss RESTEasy Tutorial, what we have to do is to create an interface and use JAX-RS annotations describe the requests like the following interface:

    @Path("/web-interfaces")
    public interface MasterJBoss{
        @GET
        @Path("273-resteasy-tutorial-.html")
        public String resteasyTutorial();        
    }


Now we can create concrete implementation of these interfaces using the <strong>org.jboss.resteasy.client.ClientRequestFactory</strong> class:
        ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(
                "http://www.mastertheboss.com").build());
        MasterJBoss mb = crf.createProxy(MasterJBoss.class);
        System.out.println(mb.resteasyTutorial());

It may not look very advantageous at the first look, but when we are dealing with complex and well REST oriented APIs/Web Services, this kind of client is very useful. Other circumstance that make this client a good choose is when we want to share an interface between the server and the client.
I said that we can use JAX-RS features with this approach, we have a more complex example that uses the Twitter API. The related interface is showed in the following code:
    public interface TwitterAPI {
        @GET
        @Path("users/show.xml")
        public TwitterUser userInformation(
                @QueryParam("screen_name") String screenName);

        @GET
        @Path("statuses/show.xml")
        public Status status(@QueryParam("id") String id);
    }

Then you can simply create a new implementation based in this interface and call the methods you want.
        ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(
                "https://api.twitter.com/1").build());
        TwitterAPI twitterAPI = crf.createProxy(TwitterAPI.class);
        System.out.println(twitterAPI.userInformation("resteasy"));        
        System.out.println(twitterAPI.status("112652479837110273"));

Of course, nothing is magical and perfect. You may face some incompatibility of what you described in the interface and how your interface really is. RESTEasy has a lot of resources to help you to workaround some of them (for example when using lists RESTEasy lets you map lists using a proprietary annotation), but it’s out of scope of this article describe all of these possibilities of incompatibilities.

Using RESTEasy interceptors

The last topic is to show you a very useful feature of the client API. You create interceptors that will help you to, for the most common use, create log of the application or other things.
The interceptor may be called before(prefix interceptor) and after the request(suffix interceptor), I mean, when send the request to the server and when the server responds to you.
To use this feature you simply need to create a class that implements the interface org.jboss.resteasy.spi.interception.ClientExecutionInterceptor and register this class as a prefix or suffix interceptor in the ClientRequestFactory. In the following piece of code we show how to register two interceptors.

        ClientRequestFactory crf = new ClientRequestFactory(UriBuilder.fromUri(
                "http://api.twitter.com/1").build());

        crf.getPrefixInterceptors().getExecutionInterceptorList()
                .add(new ClientExecutionInterceptor() {
                    @Override
                    public ClientResponse execute(ClientExecutionContext ctx)
                            throws Exception {
                        System.out.println("Starting execution of method "
                                + ctx.getRequest().getHttpMethod() + " in URL "
                                + ctx.getRequest().getUri());
                        return ctx.proceed();
                    }
                });
        
        crf.getSuffixInterceptors().getExecutionInterceptorList()
        .add(new ClientExecutionInterceptor() {
            @Override
            public ClientResponse execute(ClientExecutionContext ctx)
                    throws Exception {
                System.out.println("End execution of method "
                        + ctx.getRequest().getHttpMethod() + " in URL "
                        + ctx.getRequest().getUri());
                return ctx.proceed();
            }
        });

JAX-RS 2.0 Client API

JAX-RS 2.0 (JSR 339) is almost finished and it will specify a a client API.

Response res = client.target("http://example.org/hello")
.queryParam("MyParam","...")
.request("text/plain")
.header("MyHeader", "...")
.get();

It will be based in builders and will not use the proxy concept we presented here. RESTEasy 3.0 will implement JAX-RS.

Conclusion

We presented the main features of the RESTEasy client API. Of course according your necessities it will be necessary to go more deeper in the API documentation, but I hope we could introduce you this API.

Download the code of this tutorial.

0
0
0
s2smodern