My understanding of Jerome's e-mail of 2010-Aug-30 (has it really been that long?) is that it's not sufficient to unwind the stack, whether by exception or by testing response state. The main problem is arranging for the calls to afterHandle to occur in a different thread. These are calls that would have been executed on a committed response as part of the normal stack unwind.
While it *might *be a reasonable implementation choice to use an exception internally, it's not a real exception that can be allowed to propagate arbitrarily, because it's OK, not exceptional, for the original thread to return without a committed response. This is a tough problem. --tim On Fri, Dec 23, 2011 at 3:23 AM, Tal Liron <[email protected]>wrote: > Jerome, > > What about my idea of throwing a special exception, something like > "ResponseCommitDeferredException"? Exceptions are an easy and natural way > in the JVM to unwind a call stack. The exception would go up to the lowest > possible level, where it explicitly caught and set to wait. Nothing along > the way would have to know any specific about it. > > > > Hi Tim, > > > > > > > > Yes, this is a good summary of the API refactoring intent. Actually it > would > > be a bit simpler as the stack would only contain Restlet instances part > of > > the processing chain, not lower level Java methods. > > > > > > > > Another key aspect is that a call to Restlet#handle() would not take care > > itself of invoking the next Restlet in the chain otherwise the stack > > wouldn’t be properly populated. Maybe the next Restlet should be the > result > > of the call to Restlet#handle()…. “handle the call at your level and then > > return the control to the caller by indicating the next Restlet if any, > and > > let the caller invoke this next Restlet after updating the Restlet > stack”. > > > > > > > > Best regards, > > > > Jerome > > > > -- > > > > <http://www.restlet.org/> http://www.restlet.org > > > > <http://twitter.com/#!/jlouvel> http://twitter.com/#!/jlouvel > > > > > > > > > > > > > > > > > > > > De : tpeierls at gmail dot com [mailto:tpeierls at gmail dot com] De la > part de Tim > > Peierls > > Envoyé : jeudi 22 décembre 2011 19:01 > > À : discuss at restlet dot tigris dot org > > Objet : Re: Re: Status of Asynchronous Support > > > > > > > > Jerome said earlier in this conversation: > > > > > > > > The only way I see to solve this issue for now (2.1) would be to > maintain a > > custom Restlet call stack containing the list of Filters that intercepted > > the inbound call and make sure that their afterHandle() method is > invoked by > > the asynchronous response thread. > > > > > > > > Trying to flesh this out in my head: So the same logic that calls > > beforeHandle would push the corresponding afterHandle call onto a stack > > associated with the response; setting committed false would prevent the > > normal afterHandle machinery from executing, and the commit() machinery > > would be given access to the stack so it could pop those afterHandles and > > call them? > > > > > > > > Afaict, this isn't in yet, so I think it would be safer to say that > asynch > > I/O is still in preview mode for 2.1. Am I being too pessimistic? > > > > > > > > --tim > > > > > > > > > > > > > > > > On Thu, Dec 22, 2011 at 12:56 AM, Tal Liron <tal dot liron at > threecrickets dot com> > > wrote: > > > > I have created the simplest example I could to prove my point, and > hopefully > > to help find a solution to this important problem: > > > > https://github.com/tliron/restlet-async-test > > > > The current code works as expected -- but only because > AsyncResource.delay > > is non-zero. If you set the value to zero, then the Restlet chain will do > > its work before the AsyncResource commits, and then the resource will not > > return the entity. > > > > No exceptions get thrown -- the code is "thread safe" -- but it still > shows > > that it's impossible to reliably handle async responses. > > > > I hope other people can take a look and let me know if I missed something > > important. > > > > > > > > > Jerome, even though setCommitted(false) gets called, there still the > usual > > > processing of handle() in the entire restlet chain (the Finder, > delegating > > > to the UniformResource, etc.). Within these routines, the return values > > from > > > various callbacks are handled. Stuff that happens there on the response > > can > > > override work being done in another thread. The response is thread > safe, > > but > > > it's still not the intended result. > > > > > > I don't have a test case right now, but it would be easy to produce: > > simply > > > call setCommitted(false) in a ServerResource annotated @Get > > implementation, > > > and immediately move processing to a thread, where commit() is > eventually > > > called. The worker handler thread would overlap with the work done in > the > > > regular Restlet handling thread and you would get weird statuses and > > > response entities. > > > > > > The reason I suggest an exception (and I share Tim's unease with it) is > > that > > > it's a way to stop the handling chain in the regular thread, so that > only > > > the new handler thread would have free reign on the response. But it > > doesn't > > > have to be an exception. Another solution would be for ServerResource, > > > UniformResource and Finder to be refactored specifically to handle the > > > committed=false case. I worry, though, that future work or custom > > > implementations would not handle the case properly. > > > > > > -Tal > > > > > > > > On Sun, Jul 11, 2010 at 9:00 PM, Jerome Louvel <jerome dot louvel at > > noelios dot com>wrote: > > > > > > > > > Hi Tal and Tim, > > > > > > > > > > > > > > > > There is a way to signal an asynchronous response on a per-call > basis, > > > > calling Response#setCommitted(false). > > > > > > > > > > > > > > > > Then, if you call Response#commit() before the initial request thread > > > > reaches back the connector, this should work fine as well. I’m not > sure > > yet > > > > how it could get ‘corrupted’. Do you have a precise scenario? > > > > > > > > > > > > > > > > Note that the NIO version of the asynchronous internal connector has > > been > > > > moved to version 2.1. This feature should indeed be considered as > > preview > > > > feature for 2.0. > > > > > > > > > > > > > > > > Best regards, > > > > Jerome Louvel > > > > -- > > > > Restlet ~ Founder and Technical Lead ~ http://www.restlet.org > > > > Noelios Technologies ~ http://www.noelios.com > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > *De :* tpeierls at gmail dot com [mailto:tpeierls at gmail dot com] > *De > > la part de* Tim > > > > Peierls > > > > *Envoyé :* vendredi 18 juin 2010 13:51 > > > > > > > > *À :* discuss at restlet dot tigris dot org > > > > *Objet :* Re: Status of Asynchronous Support > > > > > > > > > > > > > > > > > > I never saw a response to this, but it does seem like a problem. > > > > > > > > > > > > > > > > I don't love the idea of a special exception used purely to handle > > control > > > > flow, but I can't think of anything better off-hand. > > > > > > > > > > > > > > > > --tim > > > > > > > > > > On Sat, May 22, 2010 at 8:05 PM, Tal Liron <tal dot liron at > > threecrickets dot com> > > > > > > wrote: > > > > > > > > Hi Jerome, > > > > > > > > > > > > > 2. There is a TaskService associated to your application that you > > could > > > > > leverage. It separates threads usage from tasks to process (such as > > > > > committing responses). > > > > > > > > I've tried this, but there is a concurrency problem with this > pattern in > > > > ServerResource -- > > > > > > > > If I set autoCommiting to false during a ServerResource.get() and > put my > > > > task on a separate thread pool, then my own task might try to update > the > > > > response at the same time as the upper parts of the call stack > > > > (Finder.handle(), for example) also try to update the response > according > > > > to my return value from get(). Both threads might be doing it at the > > > > same time, and the response ends up corrupted (no concurrency > > > > exceptions, but it's mismatched status/entity, for example). > > > > > > > > What would be the correct way to defer a response from within a > > > > ServerResource? > > > > > > > > My thought is that there should be a way to return from get() while > > > > signaling to the rest of the call stack that I am handling the > response. > > > > A null won't work, because it internally signifies an unavailable > > > > entity. Perhaps a new kind of ResourceException? > > > > DefferedResponseResourceException? > > > > > > > > -Tal > > > > > > > > ------------------------------------------------------ > > > > > > > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447 > > < > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2612 > > 147> &dsMessageId=2612147 > > > > > > > > > > > > > > > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447 > > < > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2899 > > 008> &dsMessageId=2899008 > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2899300 > ------------------------------------------------------ http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2899379

