Since I’m so RESTless lately I started thinking about what JBoss could do to help with this effort. We’re involved with JSR-311, which is defining a server-side framework for REST web services, so I decided to contact Heiko Braun, our representative on this specification. I got a copy of the latest draft and dived in. Sometimes the rules of the JCP prevent you from talking about a specification publicly (please correct me if I’m wrong), so I wasn’t sure I could blog about this specification. But, since Brian Leonard has blogged about 311, then I guess I can too.

I don’t want to get into too much detail on 311. Instead please read Brian’s blog and follow the additional links he provides. 311 does seem like it is just standardizing the REST framework Sun has already written. I will though provide example code so that I can reference it later in this blog.

public class Shopping {
   @HttpMethod("GET")
   @UriTemplate("/shopping/orders")
   @ProduceMime("text/xml")
   public String getAllOrders(@QueryParam("expand") boolean expand) {...}

   @HttpMethod("POST")
   @UriTemplate("/shopping/orders")
   @ConsumeMime("text/xml")
   public String buy(Document order) {...}

   @HttpMethod("GET")
   @UriTemplate("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

   @HttpMethod("DELETE")
   @UriTemplate("/shopping/orders/{id}")
   public void deleteOrder(@UriParam("id") int orderNum) {...}
}

The spec allows you to map http header entries, query parameters, and individual elements within a URI to a method invocation and its parameters and return types. You can also specify what MIME types a method produces and consumes. The spec also provides you with the ability to define factories that can map representations to and from Java objects.

Change suggestions

After reading the specification and browing the Sun REST framework documentation, I have a few suggestions I’d like to make to JSR 311.

Remove magic methods

It seems like @HttpMethod can be placed without a http method identifier on a Java method and the HTTP method type inferred through the Java method name.

@HttpMethod String getOrders()

In this example, HTTP GET would be used because getOrders() begins with the string ‘get’. I never liked the idea of magic method names. They are too fragile and IMO, just bad programming practice. Instead let’s……..

Annotation refactoring of @HttpMethod

Annotation frameworks should be as tiny and concise as possible. Avoid verbosity at all costs. I’d like to see @HttpMethod replace with a more concrete set of http annotations with the additional ability of being able to define a uri template embedded within these applications. So, instead of @javax.ws.rest.HttpMethod (or whatever the package name will be), let’s instead have individual Get, Put, Post, Delete, and Options annotations under the package @javax.ws.rest.httpmethod:

public @interface Get {

   String value() default "";

}

The value() of Get, Post, Delete, etc. would be an optional uri template. So, instead of the verbose:

   @HttpMethod("GET")
   @UriTemplate("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

We would get:

   @Get("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

Reduces one line of typing and also, IMO, makes things easier to read.

Allow annotations on an interface instead

RESTful classes should be allowed to declare their REST annotations on the methods of an interface instead of on the class methods. IMO, this is a better way of isolating the published interface of a service. Doing so would also allow the EJB specification to adopt REST and be able to publish remote, local, and restful interfaces to the outside world. Another interesting side affect of this is….

How about a client side framework?

Another interesting side affect of being able to apply REST annotations to an interface is that this interface could be re-used by a client-side framework to generate a proxy that could invoke on REST web services. The client-side programmer could use the same annotations to describe many REST web services that may or may not be using the server-side implementation of 311 or even Java at all! Doesn’t seem like much more effort to define this client-side API.

@Location annotation?

One common pattern I’ve seen in the REST articles and books I have read is that when you have a service method that creates a new object or queries for an existing object, and Location header should be sent back to the client containing the URI the resource is locatable. The 311 spec seems to support this by allowing the user to return a spec-define Response class. What if instead, we provided the ability to map a return value to a Location header?

@Post("/shopping/orders")
@Location("/shopping/orders/{$r}")
public int buy(Document order) {...}

The $r would represent the string representation of the returned value of the buy() method. The client would receive an empty response with a Location header pointing to the new resource created by the buy() method. We could get even funkier in the @Location annotation and allow Unified EL expressions.

@Post("/shopping/orders")
@Location("/shopping/orders/{$r.getId()}")
public Order buy(Document order) {...}

This kind of flexibility could allow one object to be used both RESTfully and locally.

Security?

Another thing I see missing is security hooks. For instance, how about an annotation specifiying whether the resource should be accessed over HTTPS or not? How about an annotation that allows you to plug in an authentication mechanism? IMO, 311 shouldn’t be diving into defining security protocols, but should at least think about providing metadata that allows you to plug in your own implementation. Then again, maybe authentication is best left to being implemented in servlet filters. I don’t know…

XML Descriptor?

There are some bigots out there that despise annotations. An XML descriptor should be created that can define this type of metadata. It should follow the style of other EE components so that we can do things like integrating JAX-RS with EJB.

EJB bridge

The 311 specification does talk about how JAX-RS interacts in a servlet environment. I’d also like to see some work done so that EJBs can become restful as well. This will probably require some work around define lifecycle and creating an annotation like @Restful to ping the container that it needs to perform restful bindings. This would also require work with the EJB 3.1 JSR to expose JAX-RS XML descriptors within EJB 3.1. Red hat would be happy to drive this in the EJB 3.1 expert group.

More to come

I’m seriously thinking about implementing 311 with the changes I’ve suggested here and integrating it with our EJB3 implementation. Hopefully I have the time. Maybe somebody in the community would be interested? I’d be happy to help as long as the individual showed initiative and ability to work on their own. I’ll also talk to Heiko more on what he thinks should be massaged in the specification and blog about them here.