|
View:
New views
15 Messages
—
Rating Filter:
Alert me
|
|
|
implementing long poll in grailsHi,
I'm trying to implement a simple long poll in a Grails controller, so that the controller will go to sleep until something interesting happens, and maybe take 10-20 seconds before rendering the response. (Yeah, I know this is a naive, inefficient implementation, and that DWR/Jetty continuations could do it nicely!) To see whether anything interesting has happened, I'm sending the latest known version numbers of each domain entity with the request, and then looking at the domain classes for changes periodically. So, something like this: def longpoll={ //read known version numbers def counter = 0 localPoll: while (counter < 10){ def changed=getChanges() if (changed){ //render a response to say something has changed break localPoll }else{ Thread.currentThread.sleep(5000) counter+=1 } } if (counter>10){ //render a null response } } def getChanges(){ def things=Thing.findAll() for (t in things){ //is version number different? If so, return true } return false } So in the longpoll closure, I enter a loop, and check every 5 seconds for changes, based on incremented version numbers, by iterating through every object in the domain (like I said, I'm not looking for efficiency here!) If I find a change, I report back immediately, and only return a "no change" response after a set timeout, here 50 seconds. My 5 second interval is long, but better for debugging - because I'm just polling on the server, not across the network. I could go for a much smaller interval. Anyway, it's looking like a good pedagogical example of how to do things the hard way, but I find that Thing.findAll() doesn't return the changes in the version number, even if I go in and manually update an entity through a scaffolding/admin screen. I'm guessing that this is because the entire controller closure is wrapped in a single transaction or hibernate session, which is an entirely sensible thing to do when the response returns almost-instantly, as in the majority of web apps. So, my question is, is there a way in which I can manually create a new transaction within the controller closure, so that I can see updates that occur between the request first arriving and the response being rendered? Thanks in advance, Dave ------------------------------------------------------- --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsDave,
I'm also implementing long polling. Have you been able to solve your original problem? I'm using plain while with return, not a closure with break. When I tried my code with break like you did I didn't have any success. For your checking of changes, how do you keep track of the last change? I used the session context together with beforeInsert in all classes so that a Date session.objectcreated gets set when an instance of the class is created. Also I'm still having a couple of things left that I couldn't yet solve. I have an alarm button on all of my views, so all of them re-open a request to the server script. When you now switch between views in the browser, firefox aborts running requests while IE6 doesn't. So I used req.transport.abort to be safe(using prototype) when req is the handler to my xmlhttprequest. This solved the problem partially. On the server side however the controller with the polling loop continues to run until its timeout. Do you know a good way to recognize that the request was aborted? A related probem occurs when the user logs out (using acegi). This creates an unknown state exception on the server, because the session context is no longer there in which I stored my time stamps for the updates. However, I can't use a check whether the session context is null because the controller is still running with its local instance of the session context so the result is not nul, strangely. I would greatly appreciate if you don't mind sharing some of your experience. Thanks, Martin
|
|
|
Re: implementing long poll in grailsWhy is your controller in a loop? Are you trying for some kind of server-push implementation?
~~ Robert. redheat wrote: > Dave, > > I'm also implementing long polling. Have you been able to solve your > original problem? > > I'm using plain while with return, not a closure with break. When I tried my > code with break like you did I didn't have any success. > > For your checking of changes, how do you keep track of the last change? I > used the session context together with beforeInsert in all classes so that a > Date session.objectcreated gets set when an instance of the class is > created. > > Also I'm still having a couple of things left that I couldn't yet solve. > > I have an alarm button on all of my views, so all of them re-open a request > to the server script. > When you now switch between views in the browser, firefox aborts running > requests while IE6 doesn't. So I used req.transport.abort to be safe(using > prototype) when req is the handler to my xmlhttprequest. This solved the > problem partially. > On the server side however the controller with the polling loop continues to > run until its timeout. > > Do you know a good way to recognize that the request was aborted? > > A related probem occurs when the user logs out (using acegi). This creates > an unknown state exception on the server, because the session context is no > longer there in which I stored my time stamps for the updates. However, I > can't use a check whether the session context is null because the controller > is still running with its local instance of the session context so the > result is not nul, strangely. > > I would greatly appreciate if you don't mind sharing some of your > experience. > > Thanks, Martin > > > Dave Crane-3 wrote: >> Hi, >> >> I'm trying to implement a simple long poll in a Grails controller, so that >> the controller will go to sleep until something interesting happens, and >> maybe take 10-20 seconds before rendering the response. (Yeah, I know >> this >> is a naive, inefficient implementation, and that DWR/Jetty continuations >> could do it nicely!) To see whether anything interesting has happened, >> I'm >> sending the latest known version numbers of each domain entity with the >> request, and then looking at the domain classes for changes periodically. >> So, something like this: >> >> def longpoll={ >> //read known version numbers >> def counter = 0 >> localPoll: while (counter < 10){ >> def changed=getChanges() >> if (changed){ >> //render a response to say something has changed >> break localPoll >> }else{ >> Thread.currentThread.sleep(5000) >> counter+=1 >> } >> } >> if (counter>10){ >> //render a null response >> } >> } >> >> def getChanges(){ >> def things=Thing.findAll() >> for (t in things){ >> //is version number different? If so, return true >> } >> return false >> } >> >> So in the longpoll closure, I enter a loop, and check every 5 seconds for >> changes, based on incremented version numbers, by iterating through every >> object in the domain (like I said, I'm not looking for efficiency here!) >> If I >> find a change, I report back immediately, and only return a "no change" >> response after a set timeout, here 50 seconds. My 5 second interval is >> long, >> but better for debugging - because I'm just polling on the server, not >> across >> the network. I could go for a much smaller interval. >> >> Anyway, it's looking like a good pedagogical example of how to do things >> the >> hard way, but I find that Thing.findAll() doesn't return the changes in >> the >> version number, even if I go in and manually update an entity through a >> scaffolding/admin screen. >> >> I'm guessing that this is because the entire controller closure is wrapped >> in >> a single transaction or hibernate session, which is an entirely sensible >> thing to do when the response returns almost-instantly, as in the majority >> of >> web apps. So, my question is, is there a way in which I can manually >> create a >> new transaction within the controller closure, so that I can see updates >> that >> occur between the request first arriving and the response being rendered? >> >> Thanks in advance, >> >> Dave >> >> ------------------------------------------------------- >> >> --------------------------------------------------------------------- >> To unsubscribe from this list, please visit: >> >> http://xircles.codehaus.org/manage_email >> >> >> >> > -- ~~ Robert Fischer, Smokejumper IT Consulting. Enfranchised Mind Blog http://EnfranchisedMind.com/blog Check out my book, "Grails Persistence with GORM and GSQL"! http://www.smokejumperit.com/redirect.html --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsYes, Robert, exactly.
My understanding of what Dave posted is that he is also trying to achieve that, see for example the part localPoll: while (counter < 10){ if (changed){ //render a response to say something has changed break localPoll }else{ Thread.currentThread.sleep(5000) counter+=1 } I'm doing similar things but with plain while and return, not localPoll:while and break. The idea is not to have the client ask for news all the time, cluttering the server with requests. Instead, the client opens an Ajax request, lets it sit there waiting, and the server loops checking for new database items and re-renders the list view to the response if new items are found in my case. The client side Javascript, after receiving the response, updates the DOM element with the list and re-issues the request for updates. This kind of approach is referred to often as Ajax long polling, or reverse Ajax, a variant of Comet style Ajax. I used a controller and not a service for that because, with services you would first need to expose them somehow and you have all sorts of limitations if you want to access scopes like session from a service which I couldn't solve.
|
|
|
Re: implementing long poll in grailsHave you done any kind of proof-of-concept on this? I'm pretty sure this is premature optimization
at its worst, and this kind of approach will kill your web server. They're really, *really* not designed for that kind of usage. Cluttering the server with requests is much more what they're used to, and can actually fairly efficient given HTTP 1.1 caching[1] and connection optimizations[2]. Some of those connection optimizations actually take care of common performance concerns—for instance, it's unlikely a user will be re-opening new TCP/IP connections for each request. You probably want to look into different ways of doing this, Jabber/XMPP being the most popular (and there's both a Jabber and XMPP plugin in Grails). Doing long polling via PeriodicUpdater (either the built-in Prototype version or my jQuery version[3]) is also a good way to go. It's got built in decay for users who don't see changes often. Don't fight HTTP's nature: work with it. If you really don't want to, create a Java or Flash rich client that can form a persistence connection back to some other port over raw TCP/IP. [1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html [2] http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html [3] http://enfranchisedmind.com/blog/posts/jquery-periodicalupdater-ajax-polling/ ~~ Robert. redheat wrote: > Yes, Robert, exactly. > > My understanding of what Dave posted is that he is also trying to achieve > that, see for example the part localPoll: while (counter < 10){ > if (changed){ > //render a response to say something has changed > break localPoll > }else{ > Thread.currentThread.sleep(5000) > counter+=1 > } > > I'm doing similar things but with plain while and return, not > localPoll:while and break. > > The idea is not to have the client ask for news all the time, cluttering the > server with requests. Instead, the client opens an Ajax request, lets it sit > there waiting, and the server loops checking for new database items and > re-renders the list view to the response if new items are found in my case. > The client side Javascript, after receiving the response, updates the DOM > element with the list and re-issues the request for updates. > This kind of approach is referred to often as Ajax long polling, or reverse > Ajax, a variant of Comet style Ajax. > > I used a controller and not a service for that because, with services you > would first need to expose them somehow and you have all sorts of > limitations if you want to access scopes like session from a service which I > couldn't solve. > > > Robert Fischer wrote: >> Why is your controller in a loop? Are you trying for some kind of >> server-push implementation? >> >> ~~ Robert. >> >> >> > -- ~~ Robert Fischer, Smokejumper IT Consulting. Enfranchised Mind Blog http://EnfranchisedMind.com/blog Check out my book, "Grails Persistence with GORM and GSQL"! http://www.smokejumperit.com/redirect.html --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsThanks, Robert, for sharing all that expertise.
I have several reasons why I'm pursuing this approach. The most important one is, as you said, >Don't fight HTTP's nature: work with it. With this kind of Ajax long polling implementation you don't need any plugins neither client side nor server side or any extra standards. It's just plain HTTP, HTML and a bit of Javascript. That's why it works with all browsers out there, no exceptions. And all server side languages, not just Java. Firt of all please take care in using the expression long polling. Long polling does not mean that you wait a long time between client side polls. Long polling means that you poll and wait for the server reply, and then re-poll. What you are proposing is just Ajax periodical update with decay. With a decay, you are implementing a mix of both approaches. Why don't you just right away wait until the server has news and replies. There is nothing against it. I made a long design study and concluded for myself that Ajax long polling (i.e., wait for the reply forever) is actually the better way of implementing Comet style, because traditional comet uses XHRstreaming or hidden IFrame and stuff, all of which don't work properly in all browsers. Sorry my best reference is only a German website on long polling (i.e., wait for reply, then re-poll) but just have a look at the code example if you care and you'll see how simple it is. http://wiki.ajax-community.de/tutorial:erste-schritte-mit-comet-longpoll#kompatibilitaet I'm developing without any plugins because my web app must work with even the simplest clients like PDAs that don't have any rendering plugins whatsoever, just a browser. Besides, all the recent browser updates made a lot of effort speeding up JS rendering. Just look at Apple's recent Safari which is supposed to beat the JS rendering speed of the other browsers by a factor of six. I really want to stick to plain JS and don't adopt another specific rendering plugin which could, in two years, no longer be on the market. My product is supposed to be long lasting. Here is an English reference which is second best in my list but please first look at the code example in the first reference. http://www.webreference.com/programming/javascript/rg28/ The only drawbacks I've seen so far is that a) in older browsers the number of open requests is limited to two. So you need to make sure you close requests client side that are not needed. b) open requests on the server side normally mean an extra threat per request. But please imagine that a web server must be able to handle thousands of them, so if a few of them add a second threat for a while it doesn't make a big difference. Honestly, if I had a choice I would wait until HTML 5.0 web socket standard is available in all browsers http://cometdaily.com/2008/07/04/html5-websocket/ which would provide a standard way of two way communications. But until then, just plain HTTP. |
|
|
Re: implementing long poll in grailsI know what I mean when I say "long polling". And I agree with you that fanciness with iFrames and
browser plugins is overkill for most RIA websites. However, I think you're substantially underestimating the problems you're going to run into with this "constant connection" approach. For instance, I guaranty you that you'll end up having to send some kind of keep-alive to clients, because they're really, REALLY going to want to timeout your connections (because, y'know, they expect HTTP to be for a request/response usage). And your dismissiveness about the browser (and app server's!) active response pool is almost certainly an error. Active threads are usually measured in the hundreds (see the standard Apache mpm_worker config here[0]), but you're talking about needing one per client, so you're effectively limiting your active client pool to some number in the hundreds—and even that is straining the server! And this isn't even taking into account the development problems you're going to run into because web development frameworks expect request/response patterns, not request/response...response...response... patterns. Which you're already encountering. Worst of all, I really wonder if you're gaining as much as you think you're gaining. You get effectively the same effect by setting Apache with a high KeepAliveTimeout[1] and KeepAliveRequests[2]. So this may all be for nothing. On the other hand, you can use a minimized jQuery via Google's CDN for free[3], and that's a bit under 56k (from the get's Content-Length), which is less than a 1 second download for even the slow cell phones. And that's assuming it's not cached from hitting another site using Google's jQuery. Then, using Google's jQuery and my PeriodicalUpdater[4] (I'd recommend minimizing it) with Apache's KeepAliveTimeout and KeepAliveRequests basically give you the same functionality in a much more HTTP-friendly format. And that's all simply very compatible JavaScript. [0] http://httpd.apache.org/docs/2.2/mod/worker.html [1] http://httpd.apache.org/docs/2.2/mod/core.html#keepalivetimeout [2] http://httpd.apache.org/docs/2.2/mod/core.html#maxkeepaliverequests [3] http://code.google.com/apis/ajaxlibs/documentation/index.html#jquery [4] http://enfranchisedmind.com/blog/posts/jquery-periodicalupdater-ajax-polling/ ~~ Robert. redheat wrote: > Thanks, Robert, for sharing all that expertise. > > I have several reasons why I'm pursuing this approach. > > The most important one is, as you said, > >> Don't fight HTTP's nature: work with it. > > With this kind of Ajax long polling implementation you don't need any > plugins neither client side nor server side or any extra standards. It's > just plain HTTP, HTML and a bit of Javascript. That's why it works with all > browsers out there, no exceptions. And all server side languages, not just > Java. > > Firt of all please take care in using the expression long polling. Long > polling does not mean that you wait a long time between client side polls. > Long polling means that you poll and wait for the server reply, and then > re-poll. What you are proposing is just Ajax periodical update with decay. > With a decay, you are implementing a mix of both approaches. Why don't you > just right away wait until the server has news and replies. There is nothing > against it. > > I made a long design study and concluded for myself that Ajax long polling > (i.e., wait for the reply forever) is actually the better way of > implementing Comet style, because traditional comet uses XHRstreaming or > hidden IFrame and stuff, all of which don't work properly in all browsers. > > Sorry my best reference is only a German website on long polling (i.e., wait > for reply, then re-poll) but just have a look at the code example if you > care and you'll see how simple it is. > http://wiki.ajax-community.de/tutorial:erste-schritte-mit-comet-longpoll#kompatibilitaet > > I'm developing without any plugins because my web app must work with even > the simplest clients like PDAs that don't have any rendering plugins > whatsoever, just a browser. Besides, all the recent browser updates made a > lot of effort speeding up JS rendering. Just look at Apple's recent Safari > which is supposed to beat the JS rendering speed of the other browsers by a > factor of six. I really want to stick to plain JS and don't adopt another > specific rendering plugin which could, in two years, no longer be on the > market. My product is supposed to be long lasting. > > Here is an English reference which is second best in my list but please > first look at the code example in the first reference. > http://www.webreference.com/programming/javascript/rg28/ > > The only drawbacks I've seen so far is that > a) in older browsers the number of open requests is limited to two. So you > need to make sure you close requests client side that are not needed. > b) open requests on the server side normally mean an extra threat per > request. But please imagine that a web server must be able to handle > thousands of them, so if a few of them add a second threat for a while > it doesn't make a big difference. > > Honestly, if I had a choice I would wait until HTML 5.0 web socket standard > is available in all browsers > http://cometdaily.com/2008/07/04/html5-websocket/ > which would provide a standard way of two way communications. > > But until then, just plain HTTP. > > > > ~~ Robert Fischer, Smokejumper IT Consulting. Enfranchised Mind Blog http://EnfranchisedMind.com/blog Check out my book, "Grails Persistence with GORM and GSQL"! http://www.smokejumperit.com/redirect.html --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsHi Martin, Robert,
I did solve the original problem that I posted to the list - as I recall, I needed to explicitly call save() on domain classes before going to sleep so that other calls to the server would see them. However, note my comments that I was doing things the hard way here, and I certainly was! The code I was working on was for the Apress "Comet and Reverse Ajax" book that I wrote last year. In the first couple of chapters, I built a comet implementation from scratch, in order to demonstrate various gotchas, and then go on to demonstrate how much easier it is to use a well-built Comet API, such as Jetty+dojox.comet (for which I didn't have to move over entirely to Dojo code, the demo app used Prototype & Scriptaculous for doing the UI stuff), or DWR (which I know less about, my co-author Phil did that section). I provided a rudimentary Grails plugin for working with the Jetty/Dojo comet stack in Grails, and you can probably download that from the publisher's site, but since then, Mingfai Ma's done a nicer Comet plugin around the same technology - big improvement over my efforts is that it uses Spring singleton abstractions to hold the server-side Comet bus components, whereas I was rather hackily stuffing them in the servlet context (ok for a single VM, but won't scale out). Mingfai's plugin here: http://www.grails.org/Cometd+Plugin (gotta love RESTful, intuitive URLs!) So, Robert's spot-on when he cautions you about messing with HTTP's request/response, and I'd strongly advise you to look at a robust implementation of Comet rather than rolling your own. Clients, servers, network routers, firewalls, etc. all will expect timeouts, and generally get in the way of keeping your connection open, depending on your network, their network, the weather, etc. etc. The dojo client, for example, understands several approaches to comet, from request streaming to long polling to simple client-side polling. Going from left to right here, the mechanism is getting less efficient, but more likely to survive the presence of proxy servers, firewalls, etc. During the handshake/setup phase, the comet client will fire off test packets in order to assess which is the most efficient communication that can be maintained in a given situation. Caucho's comet stack does the same, I believe, and I guess most of the others do too. Trying to do all this yourself will be painful and error-prone. Client-side, the Bayeux implementation is pretty nice to work with too - and you can initiate messages on the server too. HTH, and good luck with whatever you're up to! Cheers, Dave 2009/7/3 Robert Fischer <robert.fischer@...> I know what I mean when I say "long polling". And I agree with you that fanciness with iFrames and browser plugins is overkill for most RIA websites. |
|
|
Re: implementing long poll in grailsDave Crane wrote:
> I did solve the original problem that I posted to the list - as I > recall, I needed to explicitly call save() on domain classes before > going to sleep so that other calls to the server would see them. > Getting back to the original version: you'll probably need a .save(flush:true). And depending on the transaction settings on the DB, maybe a transaction commit. ~~ Robert Fischer, Smokejumper IT Consulting. Enfranchised Mind Blog http://EnfranchisedMind.com/blog Check out my book, "Grails Persistence with GORM and GSQL"! http://www.smokejumperit.com/redirect.html --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsMingfai does good work in general. I'll have to check this out: might work well for a future
evolution of the project I'm on that spawned the PeriodicalUpdater. ~~ Robert. Dave Crane wrote: > Hi Martin, Robert, > > I did solve the original problem that I posted to the list - as I > recall, I needed to explicitly call save() on domain classes before > going to sleep so that other calls to the server would see them. > > However, note my comments that I was doing things the hard way here, and > I certainly was! The code I was working on was for the Apress "Comet and > Reverse Ajax" book that I wrote last year. In the first couple of > chapters, I built a comet implementation from scratch, in order to > demonstrate various gotchas, and then go on to demonstrate how much > easier it is to use a well-built Comet API, such as Jetty+dojox.comet > (for which I didn't have to move over entirely to Dojo code, the demo > app used Prototype & Scriptaculous for doing the UI stuff), or DWR > (which I know less about, my co-author Phil did that section). I > provided a rudimentary Grails plugin for working with the Jetty/Dojo > comet stack in Grails, and you can probably download that from the > publisher's site, but since then, Mingfai Ma's done a nicer Comet plugin > around the same technology - big improvement over my efforts is that it > uses Spring singleton abstractions to hold the server-side Comet bus > components, whereas I was rather hackily stuffing them in the servlet > context (ok for a single VM, but won't scale out). > > Mingfai's plugin here: http://www.grails.org/Cometd+Plugin (gotta love > RESTful, intuitive URLs!) > > So, Robert's spot-on when he cautions you about messing with HTTP's > request/response, and I'd strongly advise you to look at a robust > implementation of Comet rather than rolling your own. Clients, servers, > network routers, firewalls, etc. all will expect timeouts, and generally > get in the way of keeping your connection open, depending on your > network, their network, the weather, etc. etc. > > The dojo client, for example, understands several approaches to comet, > from request streaming to long polling to simple client-side polling. > Going from left to right here, the mechanism is getting less efficient, > but more likely to survive the presence of proxy servers, firewalls, > etc. During the handshake/setup phase, the comet client will fire off > test packets in order to assess which is the most efficient > communication that can be maintained in a given situation. Caucho's > comet stack does the same, I believe, and I guess most of the others do > too. Trying to do all this yourself will be painful and error-prone. > > Client-side, the Bayeux implementation is pretty nice to work with too - > and you can initiate messages on the server too. > > HTH, and good luck with whatever you're up to! > > Cheers, > > Dave > > > > 2009/7/3 Robert Fischer <robert.fischer@... > <mailto:robert.fischer@...>> > > I know what I mean when I say "long polling". And I agree with you > that fanciness with iFrames and browser plugins is overkill for most > RIA websites. > > However, I think you're substantially underestimating the problems > you're going to run into with this "constant connection" approach. > For instance, I guaranty you that you'll end up having to send some > kind of keep-alive to clients, because they're really, REALLY going > to want to timeout your connections (because, y'know, they expect > HTTP to be for a request/response usage). And your dismissiveness > about the browser (and app server's!) active response pool is almost > certainly an error. Active threads are usually measured in the > hundreds (see the standard Apache mpm_worker config here[0]), but > you're talking about needing one per client, so you're effectively > limiting your active client pool to some number in the hundreds—and > even that is straining the server! > > And this isn't even taking into account the development problems > you're going to run into because web development frameworks expect > request/response patterns, not > request/response...response...response... patterns. Which you're > already encountering. > > Worst of all, I really wonder if you're gaining as much as you think > you're gaining. You get effectively the same effect by setting > Apache with a high KeepAliveTimeout[1] and KeepAliveRequests[2]. So > this may all be for nothing. > > On the other hand, you can use a minimized jQuery via Google's CDN > for free[3], and that's a bit under 56k (from the get's > Content-Length), which is less than a 1 second download for even the > slow cell phones. And that's assuming it's not cached from hitting > another site using Google's jQuery. Then, using Google's jQuery and > my PeriodicalUpdater[4] (I'd recommend minimizing it) with Apache's > KeepAliveTimeout and KeepAliveRequests basically give you the same > functionality in a much more HTTP-friendly format. And that's all > simply very compatible JavaScript. > > [0] http://httpd.apache.org/docs/2.2/mod/worker.html > [1] http://httpd.apache.org/docs/2.2/mod/core.html#keepalivetimeout > [2] http://httpd.apache.org/docs/2.2/mod/core.html#maxkeepaliverequests > [3] http://code.google.com/apis/ajaxlibs/documentation/index.html#jquery > [4] > http://enfranchisedmind.com/blog/posts/jquery-periodicalupdater-ajax-polling/ > > ~~ Robert. > > > redheat wrote: > > Thanks, Robert, for sharing all that expertise. > > I have several reasons why I'm pursuing this approach. > > The most important one is, as you said, > > Don't fight HTTP's nature: work with it. > > > With this kind of Ajax long polling implementation you don't > need any > plugins neither client side nor server side or any extra > standards. It's > just plain HTTP, HTML and a bit of Javascript. That's why it > works with all > browsers out there, no exceptions. And all server side > languages, not just > Java. > > Firt of all please take care in using the expression long > polling. Long > polling does not mean that you wait a long time between client > side polls. > Long polling means that you poll and wait for the server reply, > and then > re-poll. What you are proposing is just Ajax periodical update > with decay. > With a decay, you are implementing a mix of both approaches. Why > don't you > just right away wait until the server has news and replies. > There is nothing > against it. > > I made a long design study and concluded for myself that Ajax > long polling > (i.e., wait for the reply forever) is actually the better way of > implementing Comet style, because traditional comet uses > XHRstreaming or > hidden IFrame and stuff, all of which don't work properly in all > browsers. > > Sorry my best reference is only a German website on long polling > (i.e., wait > for reply, then re-poll) but just have a look at the code > example if you > care and you'll see how simple it is. > http://wiki.ajax-community.de/tutorial:erste-schritte-mit-comet-longpoll#kompatibilitaet > > I'm developing without any plugins because my web app must work > with even > the simplest clients like PDAs that don't have any rendering plugins > whatsoever, just a browser. Besides, all the recent browser > updates made a > lot of effort speeding up JS rendering. Just look at Apple's > recent Safari > which is supposed to beat the JS rendering speed of the other > browsers by a > factor of six. I really want to stick to plain JS and don't > adopt another > specific rendering plugin which could, in two years, no longer > be on the > market. My product is supposed to be long lasting. > > Here is an English reference which is second best in my list but > please > first look at the code example in the first reference. > http://www.webreference.com/programming/javascript/rg28/ > > The only drawbacks I've seen so far is that a) in older browsers > the number of open requests is limited to two. So you > need to make sure you close requests client side that are not > needed. > b) open requests on the server side normally mean an extra > threat per > request. But please imagine that a web server must be able to handle > thousands of them, so if a few of them add a second threat for a > while > it doesn't make a big difference. > > Honestly, if I had a choice I would wait until HTML 5.0 web > socket standard > is available in all browsers > http://cometdaily.com/2008/07/04/html5-websocket/ > which would provide a standard way of two way communications. > > But until then, just plain HTTP. > > > > > > ~~ Robert Fischer, Smokejumper IT Consulting. > Enfranchised Mind Blog http://EnfranchisedMind.com/blog > > Check out my book, "Grails Persistence with GORM and GSQL"! > http://www.smokejumperit.com/redirect.html > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > -- ~~ Robert Fischer, Smokejumper IT Consulting. Enfranchised Mind Blog http://EnfranchisedMind.com/blog Check out my book, "Grails Persistence with GORM and GSQL"! http://www.smokejumperit.com/redirect.html --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: implementing long poll in grailsYes, probably - a straightforward save() did it for me, but I don't think that code ever got run outside of dev mode with the in-memory database. If I ever did deploy it against a real database, I'd probably find my mileage varying.
The interesting thing that came out of it for me was that my home-grown comet was falling foul of another standard assumption baked into Grails, and a lot of other web frameworks - namely that the entire request runs in a single transaction. This makes perfect sense when we assume that a request will be very short-lived, which is a good assumption to make until Comet comes along. There were other similar gotchas that came up during that code - Prototype's Ajax.Request classes make similar assumptions somewhere along the way, for one - reinforcing my point that trying to do it yourself is asking for trouble - although you learn quite a bit in the attempt :) Cheers, Dave 2009/7/3 Robert Fischer <robert.fischer@...>
|
|
|
Re: implementing long poll in grailsDave, Robert,
thank you for your sharing your insights. I now have a feeling that I'm not enough of a programmer to understand all the implications yet. On the other hand I really need to reduce the number of dependencies in this app. Speaking about Gotchas, the ones that are left bugging me are the following. Can you give any hint on what is going on? None of them completely breaks what I wanted to do. What I do is I make an Ajax request to a controller that is just there to do background checking. It then writes back Javascript to the response that can update the DOM. When the user leaves the page, the browser closes the request. I don't know how to make the controller aware of that - presently I just use a timeout for the while loop. Another problem occurs when the user logs off I get an illegal state exception that has to do with http connection handling somewhere along the lines. I suppose both could be solved by letting the server know of closed connections. Either it should be able to detect it server side or receive a message client side. However, I don't see any issues when there is a timeout, neither client nor server side. This is caught on the client side and a new request established. Thanks, Martin |
|
|
Re: implementing long poll in grailsHi Martin,
These two gotchas you describe seem to me like further proof that trying to roll your own long polling/cometd system is a mistake. If you did manage to fix these, I suspect you'd run into something else before too long, and getting a fix that is robust, scalable, resilient, yadda yadda is going to take a lot of head-scratching and hair-tearing. My question to you is this: why do you need to reduce the number of dependencies in your app? Are you worried about bloat? It can look scary to see that "to do Comet you've got to use Dojo", but I hope I've made it clear that using dojox.cometd requires a fairly minimal amount of dojo, and can peacefully sit alongside jQuery, moo, P&S and/or your home-grown javascript utilities. You don't need to download 3MB of dojo in order for their cometd client to work, Dylan S and the dojo guys had a great opportunity to tie comet users into their toolkit when they wrote the cometd library, and they very wisely avoided doing this. Also, you can get various versions of Dojo pre-loaded on the big CDN's from google, AOL, etc., so the extra dependency you've added can be available over fast bandwidth in many parts of the world at no extra cost. I agree that "Reduce the number of dependencies in your app" is a golden rule for software developers, but so is this: "Don't reinvent the wheel" - especially when the wheel has hundreds of well-engineered moving parts that have stood the test of time! I don't understand all the implications of writing a comet stack yet, and I'm pretty sure that not I'm enough of a programmer to do so in the time that I have available to me. In the time you'll save by adopting a comet stack, where dojox/jetty or something else, I'm sure you can add a lot of polish to your app in other areas. The business case seems pretty clear-cut to me: stable, resilient app with extra polish or app with flaky, unstable comms and rushed/neglected other features. That's the price you'll pay for avoiding an extra dependency - are you willing to pay it? Are your support team? From the issues that you describe, it sounds like you're fairly well advanced in coding your solution, but I still reckon you'd be better off drawing a line under it and switching to a framework. Disclaimers in order here: I'm not actively involved in cometd, dojo or jetty, or any other comet stack. I don't even use comet regularly at the moment. I'm not asking you to buy my book, and have no other inside interests here. I just don't want to see you embark on a path that I went down, and then had to U-turn on. Sorry for the tough-talk, but I hope it helps. Best regards, and good luck with your project. Dave Crane 2009/7/6 redheat <martin.fuchs-lautensack@...>
|
|
|
Re: implementing long poll in grailsDon't get me wrong, I really appreciate what other designers have made available.
The support thing is actually also true - it can, however, also happen the other way round. I'm not going to do a lot of fancy things with my long poll, just basics. I thought its better to know the actual steps involved to be able to debug them, rather than to rely on a toolkit - which also comes with its very own syntax. As for the problems I'm currently facing I would like to find out how actually to send sth. from the client to the server after the Ajax request had been issued. It was already good to know that you can actively abort it, but is it possible to send something after the request was made? This could be a way to go with these problems, because then I could just ask the server loop to abort. For now I decided, based on your feedback, that I will give these two gotchas another try because once they are solved I'm pretty much done with what I wanted to have. In case I can't solve it then I'll consider Dojo. Also now I had to use prototype for some things, so why not use Dojo right away. |
|
|
Re: implementing long poll in grailsAs an update,
one of the two remaining flaws of my home brew server push is fixed. On logout (acegi), a looping controller would generate an illegalstate exception when trying to access the session - because when the session is gone it would then try to generate a new one. I knew that I needed to check whether the session is still valid and here is how to do it: if (!request.getSession(false)) {return} You read it directly from the request object because then you have a flag to say don't create a new session. Next up I'm still trying to figure out how to detect a client side request.abort on server side. |
| Free embeddable forum powered by Nabble | Forum Help |