RESTEasy Client: The Next Generation
Join the DZone community and get the full member experience.
Join For FreeWhat does the Next Generation REST client look like? Bill Burke had a few ideas... guess who's implementing them? Yours truly.
I like the general direction he was going in. Do you remember Roy Fielding's 2008 rant: REST APIs Must Be Hypertext Driven? One implication is that a client REST application should have a single starting "bookmark" URL, and from then on the client interacts with the server based on links that the server returns. Bill's approach is to use Link objects to describe the Link headers.
Bill's version:
@ResponseMapping
@ExpectedCode(200)
public interface MyResponse {
@Body
public Customer getCustomer();
@LinkHeader
public Link getNext();
@LinkHeader("last")
public Link getLastCustomer();
@Header("ETag")
public String getHash();
}
This is a leap ahead of the current RESTEasy client, which was pretty slick to begin with. However...
My version
Link objects are nice, but I have an alternative that to me feels a bit more sexy, and a bit more Java centric:
@ResponseMapping(status=200)
public class MyResponse {
public Callable<MyResponse> next;
public Callable<Status> remove;
@Body
public Customer customer;
@StatusValue
public int status;
@HeaderParam("ETag")
public String getHash();
// you can alternatively set an interface that matches the classic
// RESTEasy paradigm, which will automatically be proxied
@GET
@LinkHeader(relationship="next")
public setNext(Callable<MyResponse> next){
this.next = next;
}
@DELETE
@LinkHeader(title="remove")
public setNext(Callable<Status> remove){
this.remove = remove;
}
}
The client side code would look something like:
ClientRequestFactory factory = new ClientRequestFactory("http://mysite.com");
factory.setInterceptor(...);
MyResponse response = factory.createRequest("clientSearch?name=" + nameToSearch).getEntity(MyResponse.class);
MyResponse next = response.next.call();
next.remove.call();
This would make three HTTP calls in three lines. The intent of the code is pretty clear (at least I think it's clear... please comment).
Comparison
There are a few key differences between Bill's version and my version:
- I use a concrete class instead of an interface.
- It made my development a bit faster, since this now looks and acts more like a server-side Resource. This change allowed me to leverage existing server-side infrastructure to facilitate my prototype
- This also will allow the class to encapsulate some interesting functionality related to processing the Customer body. In essence, this class becomes a rich domain object.
- I added @StatusValue
- I reused existing JAX-RS annotation (such as @HeaderParam, @CookieParam and etc.)
- Replacing the Link object with Callable.
I wanted a to have more Java-centric feel for the remote call, while still directly expressing the HTTP details. It took an hour or so of tinkering with my prototype before Callable "called out" to me.
Quick Rant on Link header and <atom:link../> Usage
As an aside, I had to use setter methods because I had to specify the @GET/@DELETE annotations, since they can only be applied to Java Methods. Usage of Link headers, which ere inspired by <atom:link../> unfortunately requires out-of-band description of HTTP Method, which is not the ideal REST situation. Link headers and <atom:link../> are used in ways that weren't expressed in the original vision of ATOM Pub usage. Traditional ATOM Link usage was CRUDdy (Create = POST, Read = GET, Update = PUT, Delete = DELETE). Current usage doesn't always match to CRUD (for example, what which VERB would you use for a rel="Pay"). Link headers and <atom:link../> don't have any place for VERB, so REST practitioners had to use out-of-band information to match a "rel" value with a particular VERB.... In short, I would prefer to have an explicit VERB as part of the Link, but for now, I'll have to settle for out-of-band documentation and compile time annotations...
Anyway, if you don't understand (or GET) what I said in the last paragraph, don't worry, I'll expand on this philosophical idea more in the future. This blog entry was about the new client API prototype implementation, not about REST philosophy...
Next steps
IMHO, Bill's ideas on Java REST clients are truly innovative. He gave me free reign to work on this, and I've been having fun doing that. Like I said earlier, I have a prototype up and running already...
I'm definitely interested in feed back. If you have any comments, enhancements, concerns or simply want this feature released ASAP, just let me know.
Update: I realized that I didn't escape the < in my code... now that I escaped it, my code should look a lot more intuitive.
Opinions expressed by DZone contributors are their own.
Comments