Speaking in DC on REST, JAX-RS, and REST-*

Leave a comment

I’ll be speaking for NOVAJUG in WashingtonDC on Wednesday, January 20th 6:30pm-9:00pm. You can sign up for the event here.

The presentation will be about REST, JAX-RS, and REST-* specifically I will provide a short introduction to REST along with an explanation of the JAX-RS specification and how you can build RESTful web services with it. I will then get into how REST intersects with middleware services like messaging, transactions, and workflow.  Hope to see you there!

Possible POE support in Resteasy

Leave a comment

I was thinking about some POE support for Resteasy.  On the client side add a poe() set of methods on ClientRequest and a @POE annotation for the Proxy framework.  I.e.

ClienRequest request = ...;
request.body("<stuff/>", "appliation/xml");
ClientResponse response = request.poe();

@Path("/")
public interface MyService {
   @POE
   @Consumes("application/xml")
   public void poeIt(Data data);
}

The way they’d both work is a HEAD to the base URL would be sent to get the POE-Link, then a POST to the POE-Link would be done using the message body.  A Retry-like exception would be thrown if the POST fails.  For the serverside it could look something like this:

@Path("/foo/{sub}/{id}")
@POE
public void poeIt(@PathParam("sub") String subpath, @PathParam("id") @PoeGenerated int id) {...}

@PathParam combined with @PoeGenerated is an automatically uniquely generated id.  So, the user would invoke on /foo/{sub} and get back a POE link of /foo/{sub}/{id}.  i.e.

HEAD /foo/stuff

HTTP/1.1 200 OK
POE: 1
POE-Link: /foo/stuff/3333

Thoughts?

RESTEasy 1.2.1 Released

Leave a comment

Minor bug fix release.  Also, had to remove one of the referenced maven repositories because it was screwing up the build.

“rel” name requirement overloaded

2 Comments

The Atom link element and the Link header name their links using the “rel” attribute.  There is a requirement in the Atom Syndication Format and Link header RFCs that states that if the relationship is not registered with IANA, that you must use a IRI instead of a simple name.  Maybe I’m misinterpreting things, but it seems that this IRI must point to an actual resource that describes the link relationship.  IMO, this will make using links awkward as REST permeates into the application development space.  Why?  Applications will define new links.  It would be rather silly for each application to register themselves at IANA for every link they define.  So, they are stuck putting in an IRI that may change over time.  Clients that consume resources will be looking for specific relationships to do their processing.  The Link header specification, I think, tries to mitigate this problem by introducing a “title” attribute.  Which, still will be weird, because clients will be looking up “rel” or “title” attributes depending on what link relationships that want to traverse.  Seems very inconsistent to me.

What I wish they had done (or would do) is define a “relref” that is an optional URL to the description of the non-standard link relationship.  That way the rel attribute remains simple and not overloaded.

If I’m misinterpreting things, apologies.  But thats what I seem to read and what I see in examples.

Overview of REST-* Messaging Draft 4

2 Comments

Just finished draft 4 of REST-* Messaging.  Please check our our discussion group if you want to talk more about it.  Here’s a list of resources and their corresponding relationships for a high level overview.  See the spec for more details.  It relies heavily on Link headers.  The current draft shows a lot of example HTTP request/responses to give you a good idea of what is going on.

Destination

A queue or a topic resource.

Relationships:

  • post-message – link to POST/create a message to a queue or topic.  This can be
  • post-message-once – link to POST/create a message to a queue or topic using the POST-Once-Exactlly (POE) pattern
  • post-batch – POST/create a batch of messages using Atom or Multipart
  • post-batch-once – POST/create a batch using the POE pattern.

Message

Every message posted creates a message resource that can be viewed for adminstration, auditing, monitoring, or usage.

Links Relationships:

  • reply-to.  Destination that you can reply to
  • reply-to-once.  Destination that you can reply to once using the POST-Only-Once pattern
  • reply-to-batch. Destination that you can reply with a batch of messages
  • reply-to-batch-once.  Batch using POE.
  • next.  If pulling from a topic, messages will have this link.  This is the next message after this one.
  • acknowledgement.  If pulling from a queue, this link allows you to change the state of the message to acknowleged or not.
  • generator. Destination that the message came from

Topic

Has the same links as Destination with these added:

Link Relationships:

  • next.  GET the next incoming message.  Clients should use the Accept-Wait header to set a blocking timeout (see later).
  • last.  Last posted message to the topic
  • first.  First message posted to topic, or, the first message that is still around.
  • subscribers. URL that allows you to view (GET) or create/register (POST) a list of URLs to forward messages to.

Queue

Same as Destination, but these additional link relationships:

Link Relationships:

  • poller.  Alias to the next available message in the queue.  Returns a message representation along with a Content-Location header pointing to the real one.  a POST is required to access this because the state of the queue is changed.
  • subscribers.  Same as topic push model.


Etag embedded within a Link

2 Comments

I wanted to add acknowledgement to the queue consumer pull model in REST-* Messaging.  The way it would work is that consumers do a POST on the queue’s URL.  They receive the message as well as a Link header pointing to an acknowledgement resource.  When the client consumer successfully processes the message, it posts a form parameter, acknowledge=true to the acknowledgement link.

There is a problem with this though.  The design is connectionless to honor the stateless REST principle.  So there is no specific session resource that the client consumer is interacting with.  The consumer may never acknowledge the message, so I need the server to re-enqueue the message and deliver it to a new consumer.  The problem is, what if the old consumer tries to acknowledge after the message is re-enqueued or even after it is redelivered to a different consumer?

I first thought of letting the first consumer to acknowledge win and do something like POST-Once-Exactly (POE).  The problem with this is, what if there’s a network failure and the consumer doesn’t know if the acknowledgement happened or not?  It would redeliver the message and get back a Method Not Allowed response error code.  With this code, the consumer doesn’t know if somebody else acknowledged the message or if the older request just went through.  So, I went with a conditional POST.  The acknowledgement link, when performing a GET on it, would return an ETag header that the consumer must transmit with the acknowledgement POST.  If the message was re-enqueued, then the underlying ETag would change, and the conditional post would fail for the older consumer.

Still this solution is suboptimal because an additional GET request needs to be executed.  It is also subject to a race condition.  What if the message is re-enqueued before the consumer does a GET on the acknowledgement resource?  SO, what I decided to do was embed the etag value with the acknowledgement link.  For example:

1. Consume a message
Request:

POST /myqueue/consumer

Response:

HTTP/1.1 200 OK
Link: </myqueue/messages/111/acknowledgement>; rel=acknowledgement; etag=1
Content-Type: ...

...  body ...

2. Acknowledge the message
Request:

POST /myqueue/messages/111/acknowledgement
If-Match: 1
Content-Type: application/x-www-form-urlencoded

acknowledge=true

Success Response:

HTTP/1.1 204 No Content

Response when it was updated by somebody else.

HTTP/1.1 412 Precondition Failed

POE Redelivery Response.  It was already successfully updated by the consumer.

HTTP/1.1 405 Method Not Allowed

No Wait in HTTP

4 Comments

One thing the HTTP specification does not have is a “Server Timeout” response code.  The 408 and 504 response codes are the only thing that comes close.  The idea of a “Server Timeout” code is that the server received the request, but timed out internally trying to process the request.  Another thing I think that is missing from HTTP is a way for the client to tell the server how long it is willing to wait for a request to be processed.

I’ve run into both of these scenarios with the REST-* Messaging specification when I have pulling client consumers.  For the “Server Timeout” I decided upon 202, Accepted.  It seems to fit as I can tell the client to try again at a specific URL.  As for the client requesting a wait time?  I invented a new request header:  “X-RS-Wait”.  Its value is the time in seconds that the client wants to wait for a request to be processed.  Maybe there is a standard or drafted protocol I missed in my Google search?

REST-* Messaging Draft 3

Leave a comment

After prototyping, I’m back to writing another draft. This is a little bit more formal draft. I created a OSS project at:

http://sf.net/projects/rest-star

A draft of the PDF is at:

http://reststar-messaging.googlegroups.com/web/REST-Star-Messaging-draft-3.pdf

(You’ll have to click through an additional link that is *very* long). This draft only talks about the Message Publishing Protocol. I still have to write up the topic and queue push and pull model.  To discuss the draft please post at the REST-* Messaging Group.  I’m also looking for people to help prototype the specification.  Post to the RESTEasy developers list if you’re interested.

RESTEasy 1.2.GA Released

Leave a comment

After a few months RESTEasy 1.2.GA is finally ready.  This is mostly a cleanup, bug fix, and refactoring release, but here are some features of note:

I’d also like to thank Attila Kiraly for fixing some bugs that cropped up in Multipart and XOP support.  Pascal de Kloe, a new committer, also helped refactor content negotiation to support charset variants.  Solomon Duskis continues to be a seasoned veteran and helps with bugs and features here and there.

What’s next?  I’d like to focus next on getting complete OAuth support in.  I think it will help out our REST-* efforts as we look to secure the services we’re defining there.  RESTEasy is also going to expand beyond a simple JAX-RS implementation.  As JBoss projects like HornetQ, jBPM, Drools, Transactions, and Infinispan obtain RESTful interfaces, I’ll be creating a REST profile under the RESTEasy umbrella.

Useful links:

Parsing Link headers with Javascript and Java

Leave a comment

I wrote a Link header parser in Javascript. Thanks Mark Nottingham for sending me a link to his python equivalent.

var linkexp=/<[^>]*>\s*(\s*;\s*[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*")))*(,|$)/g;
var paramexp=/[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*"))/g;

function unquote(value)
{
    if (value.charAt(0) == '"' && value.charAt(value.length - 1) == '"') return value.substring(1, value.length - 1);
    return value;
}

function parseLinkHeader(value)
{
   var matches = value.match(linkexp);
   var rels = new Object();
   var titles = new Object();
   for (i = 0; i < matches.length; i++)
   {
      var split = matches[i].split('>');
      var href = split[0].substring(1);
      var ps = split[1];
      var link = new Object();
      link.href = href;
      var s = ps.match(paramexp);
      for (j = 0; j < s.length; j++)
      {
         var p = s[j];
         var paramsplit = p.split('=');
         var name = paramsplit[0];
         link[name] = unquote(paramsplit[1]);
      }

      if (link.rel != undefined)
      {
         rels[link.rel] = link;
      }
      if (link.title != undefined)
      {
         titles[link.title] = link;
      }
   }
   var linkheader = new Object();
   linkheader.rels = rels;
   linkheader.titles = titles;
   return linkheader;
}

I had written a non-regular-expression, hand-coded parser in Java for RESTEasy. Thought it might be faster than regexp. That could probably be ported to Javascript too.

Older Entries Newer Entries