Comet Issues

1. Long Connections

One of common questions asked is how does Lift handle long connections? Especially when we have like CISCO routers, proxy servers between that likely kill it when is inactive.

If the connection is lost for any reason, the browser will restart the long poll. The comet request timeout defaults to 120 seconds (LiftRules.cometRequestTimeout). If there's no change during that 120 seconds, a "Noop" is sent to the browser and the browser waits 100 milliseconds and restarts the long polling operation.

It's very unlikely that a router will shut down the TCP/IP connection between the client and the server. HTTP Keep-Alive is a very popular mechanism for improving browser performance (the TCP/IP connection to port 80 or 443 is kept open even after the HTTP request is done to avoid TCP/IP set-up time.) Most routers that have been made in the last 10-12 years are aware that HTTP connections may be kept alive for extended periods of time.

It's more likely that a proxy in between the browser and the Lift-based server will drop the connection. Apache-based proxies have a very limited number of open connections they can handle and they will often close a connection (traffic or no) after 30 seconds. But this makes no difference to Lift or the browser... they happily re-open the long poll and go on.

2. Error: CometComponent not found

There are three possible explanations for this error.

The Class Is Actually Missing

Somehow the class just isn't where you expect it to be. Check to make sure that the class file is actually being delivered.

The Class Isn't in An Official Comet Package

In Boot, if you have a call LiftRules.addToPackages("mypackage") then the class must be in "mypackage.comet". Check to make sure that the "addToPackages" call is there and correct and then check to make sure that your Comet Actor class is in the correct package.

There Is An Uncaught Exception In The Constructor

Lift (at least through 2.4) isn't smart enough to be able to distinguish between "not there" and "there but constructor throws exception". Anoying but true.

3. Error: Nothing Happens

If you don't get any errors, but none of your Comet functionality does anything (like render never getting called) then check "localSetup". If there is an uncaught exception in localSetup then no errors are reported but nothing happens - ever. Even more anoying.

4. Out Of Memory

One problem that I have run into using comet is trying to send messages to the actor faster than it can process them. This can cause the comet actor's mailbox to grow, slowing causing performance problems and eventually an OutOfMemory error. I found the problem using a Java profiler that tracked memory usage. If you suspect that you have this problem and don't have a profiler, you can override the message sending operators (such as !) to log incomming message objects.

You can also switch to Akka actors and use blocking actor to prevent message overflow.

5. Comet must be added during initial page load

You can't add a CometActor to a page via an Ajax request.  A CometActor must be placed on a page during the initial full page load.

6. Comet updates must take place in a message handler

Also, updates for those parts of the page that are managed by the CometActor must be generated in response to a message, i.e. within one of the cases of lowPriority (or mediumPriority or highPriority). Attempting to generate an update in any other way would be outside the context of a browser request and some of Lift's crucial internal mechanisms will not work correctly. For example, attempting to create an Ajax button outside of a request context might result in the following exception:

java.lang.NullPointerException: null
    at net.liftweb.http.S$.addFunctionMap(S.scala:2050) ~[lift-webkit_2.8.1-2.2.jar:2.2]
    at net.liftweb.http.S$.fmapFunc(S.scala:2413) ~[lift-webkit_2.8.1-2.2.jar:2.2]
    at net.liftweb.http.SHtml$.ajaxButton(SHtml.scala:244) ~[lift-webkit_2.8.1-2.2.jar:2.2]
    at net.liftweb.http.SHtml$.ajaxButton(SHtml.scala:328) ~[lift-webkit_2.8.1-2.2.jar:2.2]
    at your.code.where.you.call.ajaxButton

7. CometActor uses messages to work its magic

One sure fire way to send a CometActor down in flames is to start handling arbitrary messages in your CometActor implementation. This is because the CometActor implementation itself uses a number of messages that the developer does not normally see to implement its functionality. Rendering, for example, takes place in the render method, but only when called by a message handler in CometActor. So, if you write code to handle messages that are used by the system to implement the comet magic, you will prevent CometActor from doing its job and you application will not work.

When something prevents a CometActor from getting one of the messages that are normally handled internally, you will probably get an error something like this:

Error processing snippet comet. 
 Reason: Comet Component did not response to requests
net.liftweb.builtin.snippet.Comet$$anonfun$buildComet$1$$anonfun$apply$4.apply(Comet.scala:75)
net.liftweb.builtin.snippet.Comet$$anonfun$buildComet$1$$anonfun$apply$4.apply(Comet.scala:60)
net.liftweb.common.Full.map(Box.scala:398)
net.liftweb.builtin.snippet.Comet$$anonfun$buildComet$1.apply(Comet.scala:59)
net.liftweb.builtin.snippet.Comet$$anonfun$buildComet$1.apply(Comet.scala:53)
net.liftweb.common.Full.map(Box.scala:398)
net.liftweb.builtin.snippet.Comet$.buildComet(Comet.scala:53)
net.liftweb.builtin.snippet.Comet$.render(Comet.scala:37)
net.liftweb.builtin.snippet.Comet$$anonfun$dispatch$1$$anonfun$apply$1.apply(Comet.scala:30)
net.liftweb.builtin.snippet.Comet$$anonfun$dispatch$1$$anonfun$apply$1.apply(Comet.scala:30) XML causing this error:

 8. JavaScript doesn't run when added to a page

This is a quote from the book Exploring Lift (4.5.7):

Note that if you use the embed tag to access templates from within a JsCmd (typically an AJAX call), any JavaScript in the embedded template won’t be executed. This includes, but is not limited to, Comet widgets.