dev@jsr311.java.net

Re: Asynchronous REST service

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Fri, 18 May 2007 11:09:41 -0400

On May 16, 2007, at 3:29 AM, Hao He wrote:
>
> Thanks for the response. Yes, it is very neat and I like it.
>
> What if:
>
> @HttpMethod("POST")
> public process(Source xmlDoc, Response resp) {
> int processId = enqueueRequest(xmlDoc);
> URI processUri = getProcessUri(processId);
> Response.Builder.seeOther(processUri).header("Retry-After",
> 120).build(resp);
> resp.close();
> /* continue to do other processing */
> }
>
> ?
>
> In this way, we don't need to use a queue or start a new thread but
> doing the processing in the same method.
>
I think there are two reasons you might want to adopt an asynchronous
pattern:

- The processing is likely to take a long time
- The processing requires access to a shared resource (in the general
sense of the word) that doesn't support concurrent access very well

In both cases you probably don't want multiple request threads doing
the work since that is likely to negatively impact performance of
the web tier (since the request handling threads are tied up). For
this reason I think a queue-based approach with a separate thread (or
pool) to handle queued tasks would be a better solution.

Marc.

> -----Original Message-----
> From: Marc Hadley [mailto:Marc.Hadley_at_Sun.COM]
> Sent: Wed 16/05/2007 10:56
> To: dev_at_jsr311.dev.java.net
> Subject: Re: Asynchronous REST service
>
> I think you could do most of what you suggest just using HTTP and
> without inventing a receipt document. E.g. the response to the
> request that starts the async processing could use the 303 status and
> include a Location and Retry-After header. The client can then pick
> up the results or an error response from the URI provided after the
> time specified by the server has passed.
>
> Initial request:
>
> POST /processor HTTP/1.1
> Host: example.com
> Content-Type: application/xml
> Content-Length: nnnn
>
> ...
>
> Response:
>
> HTTP/1.1 303 See Other
> Location: http://example.com/processor/1234567890
> Retry-After: 120
> Content-Length: 0
>
> Susequent request to retrieve response:
>
> GET /processor/1234567890 HTTP/1.1
> Host: example.com
>
> Response:
>
> HTTP/1.1 200 OK
> Content-Type: application/xml
> Content-Length: nnnn
>
> ...
>
> Exactly how the back-end processing occurs doesn't concern us but I'd
> think it would involve posting the request to a message queue or
> something like that. You could implement the above with something like
>
> @UriTemplate("/processor")
> @ConsumeMime("application/xml")
> @ProduceMime("application/xml")
> public class Processor {
>
> @HttpMethod("POST")
> public Response process(Source xmlDoc) {
> int processId = enqueueRequest(xmlDoc);
> URI processUri = getProcessUri(processId);
> return Response.Builder.seeOther(processUri).header("Retry-
> After",120).build();
> }
>
> @HttpMethod
> @UriTemplate("{id}")
> public Response getResult(@UriParam("id") int id) {
> Result r = findResult(id);
> if (Result.completed()) {
> return Response.Builder.ok(r);
> } else {
> URI processUri = getProcessUri(id);
> return Response.Builder.seeOther(processUri).header("Retry-
> After",120).build();
> }
> }
>
> ...
> }
>
> Marc.
>
> On May 15, 2007, at 8:00 PM, Hao He wrote:
>
> >
> > Hi,
> >
> > One of a very patterns we found is what we call "Asynchronous REST
> > service" [1].
> >
> > "An asynchronous service needs to perform the following:
> >
> > 1. Return a receipt immediately upon receiving a request.
> > 2. Validate the request.
> > 3. If the request if valid, the service must act on the request
> > as soon as possible. It must report an error if the service cannot
> > process the request after a period of time defined in the service
> > contract.
> >
> > Request Receipt
> >
> > An example receipt is shown below:
> >
> > <receipt xmlns="http://www.xml.org/2004/rest/receipt" requestUri =
> > "http://www.example.com/xya343343" received = "2004-10-03T12:34:33
> > +10:00">
> > <transaction uri="http://www.example.com/xyz2343" status =
> > "http://www.example.com/xyz2343?view=status"/>
> > </receipt>
> >
> > A receipt is a confirmation that the server has received a request
> > from a client and promises to act on the request as soon as
> > possible. The receipt element should include a received attribute,
> > the value of which is the time the server received the request in
> > WXS dateTime type format. The requestUri attribute is optional. A
> > service may optionally create a request resource identified by the
> > requestUri. The request resource has a representation, which is
> > equivalent to the request content the server receives. A client may
> > use this URI to inspect the actual request content as received by
> > the server. Both client and server may use this URI for future
> > reference. "
> >
> > So, how does this case go with the current REST API?
> >
> > 1. http://www.xml.com/pub/a/2004/08/11/rest.html?page=2
> >
> > Hao
> >
>
> ---
> Marc Hadley <marc.hadley at sun.com>
> CTO Office, Sun Microsystems.
>
>
>
>

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.