Posts Tagged: REST


19
Feb 10

Extension-based content negotiation and nested routes with Restlet

I’ve been working with Restlet to expose a RESTful api interface to the data model for one of my projects. Restlet is a super flexible library allowing one to configure and access all the properties of HTTP through a REST-oriented API.

The application bootstrapping options are also super flexible, allowing one to configure how routes are resolved and nest routes for cascading capabilities. I ran into a small caveat when I tried to configure extension based content negotiation. Basically, the idea of extension based content negotiation, is that instead of using “Accept” headers, one can append a mime extension to their request URI to request a particular return format. Say, we have a http://localhost/api/resource uri, one can request xml or json formats by simply doing http://localhost/api/resource.xml or http://localhost/api/resource.json. Of course your resource has to support these formats. The documentation on this type of content negotiation is non-existent. I had to scour a bunch of users group messages and javadocs before I figured it out. I figured I’ll shared if someone else is interested.

My applications is written in Scala, so examples will be provided as such. I’m sure any experienced developer can easily discern the java equivalent.

First, in your application bootstrapping, you must turn on the extensionsTunnel option. Here is my code, which also demonstrates nested routes. Then, in your resource you must conditionally infer the MediaType provided and emit the representation of this resource based on it.

import org.restlet.{Restlet, Application => RestletApplication}
import scala.xml._
//... other imports excluded

class TestApplication extends RestletApplication {
  override def createInboundRoot: Restlet = {

    val apiRouter = new Router(getContext)
    apiRouter.attach("/test", classOf[TestResource])

    val rootRouter = new Router(getContext)
    rootRouter.attach("/api/v1", apiRouter).getTemplate.setMatchingMode(Template.MODE_STARTS_WITH)

    getTunnelService.setExtensionsTunnel(true)

    return rootRouter
  }
}

class TestResource extends ServerResource {

  @Get("xml|json")
  def represent(v:Variant):String = {
    return v.getMediaType match {
          case MediaType.TEXT_XML | MediaType.APPLICATION_XML => <response><message>Hello from Restlet!</message></response>.toString
          case MediaType.APPLICATION_JSON => "{\"message\": \"Hello from Restlet\"}"
        }
  }
}

First, the root router’s matching mode must be set to Template.MODE_STARTS_WITH, otherwise it will try to match based on full absolute uri path and not find any nested resources. So the matching mode is very important in the case where you’re working with nested resources.

Second, you set the extensions tunnel property to true: getTunnelService.setExtensionsTunnel(true). This will turn on the extension tunneling service and perform content negotiation based on the URI’s extension. Note: if an extension is not provided, it will resort to first available representation supported by the resource. It can get more complicated I believe based on other configurations, but this is what happens in the most simple scenario.

Now, with content negotiation on, the resource has to conditionally infer the proper MediaType requested and provide its representation for the MediaType. In Scala this is very elegantly done using the super flexible match/case construct. This construct can be used as Java’s switch statement, but it is way more powerful and allows for advanced pattern matching. As you can see, I check for both xml and json media types and provide the proper representation. The supported media types are handled through @Get annotation. For more info, see Restlet’s annotations and Resource documentation.

Now, accessing the resources yields the following results:

  $ curl http://localhost:8080/api/v1/test.xml
  Hello from Restlet

  $ curl http://localhost:8080/api/v1/test.json
  {"message": "Hello from Restlet"}

25
Aug 09

RESTfully insane or insanely RESTful

First let me say, I love REST. I really enjoy its implementation simplicity and the fact that it’s mostly based on HTTP, for which frameworks have been developed and bullet tested for quite some time. I can’t same the same for SOAP and its convoluted related set of standards. Complexity is never good, but its especially not good when it’s not needed to accomplish a particular task at hand. That’s how SOAP and WS-* feels to me. Out of hundreds of times that I was forced to use it, there might have been a handful of valid scenarios when a simpler solution wouldn’t suffice.

So now that I got the fact that I enjoy REST out in the open, I feel that RESTful architectures need more time to evolve and develop a set of patterns. There just isn’t enough empirical information at this point to truly come up wit a set of patterns. Yes, there are books that are great and various other sources of information which help, but I wouldn’t per say call them real architectural patterns at this point, more like a set of experiences developing one or two applications that are labeled as patterns because of its buzzword status and ability to sell books. Patterns are extracted through years and years of empirical information gathering.

Today I was working on an interface, and trying to follow the good ol’ RESTful idioms to design a RESTful API for a particular service. I quickly realized that the constraints of destructive and non-destructive operations bound to particular verbs is a beauty when in its pure form, but don’t always elegantly allow you to model a use-case.

Take my use case as an example. We have a graphing services API which provides graphs to application clients. These clients can be a web front end, or any other client of choosing. Graphs take time to generate, so we want to create the graph resource on a PUT request and then expose a URI with which this graph can be accessed. Easy enough, sure, this is programming REST 101. But here is a catch. Depending on the resource, its lifecycle state changes based on various constraints. One of those resources has a constraint that it can only ever be viewed once and must be destroyed or not allowed to be accessed ever again. So for each graph request, we PUT and GET. But that means that the GET operation is now a destructible operation, which is supposedly against RESTful principals. Someone mentioned to me that such operations should be put behind a POST request, though you generate and return the resource. That’s fine, except there are constraints. If this resource is an image, which is what it is in the graph’s case, it must be embedded in the src=”uri” attribute of the image element in the html page. So can’t POST there. But even if we can use a POST in this case, what about the case where we want a resource accessed a certain amount of times, or what if we want to track the amount of time this resource is accessed, or what if accessing the resource is a stateful operation which modifies other state, whether its own resource’s state or some other resource’s state. One will say that something’s amiss here, but that’s not true. In imperative languages, state is king (not that it’s a good thing), but it’s really easy to model real world interaction scenarios. Where looking at something, or someone, changes some property about what ever you’re looking at. If a pretty lady looks at a guys (who’s a resource), his state will change or it will trigger an action, he will either perform an action, like going over and talking to the lady, or get nervous and start sweating, either one of these actions where triggered by resource view operation. Sorry, maybe it’s not the best example, but the only one that popped into my head at this time of night.

Now, you get my point? I think REST is great, but the lesson here is that you should approach it just like anything else, with caution. When you see something that can’t be done with RESTful purity, don’t beat yourself up. REST is not yet fully mature and we are yet to discover things we can and cannot do with it given today’s interpretation of what it should be. Things change with time, so just do what makes sense today.