Atmosphere & long-polling is broken

216 views
Skip to first unread message

ntto...@gmail.com

unread,
Sep 10, 2013, 8:39:09 AM9/10/13
to scalat...@googlegroups.com
Hey guys, 

I've been having an issue with a system I'm building that uses atmosphere and scalatra. It ends up with an illegal state exception.



Steps to re-produce:

1. Changed transport to "long-polling" in application.js

2. Start application (container:start)

3. navigate to localhost:8080 & type in a chat command

4. open a new tab and do the same thing

5. now close the first tab

6. type a chat command in second tab

You will then be greeted with an Illegal state exception. The whole application is also completely broken - even for new users in different browsers.

.atmosphere.cpr.AtmosphereFramework - AtmosphereFramework exception
java.lang.IllegalStateException: null
at org.eclipse.jetty.server.session.AbstractSession.checkValid(AbstractSession.java:109) ~[jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.session.HashedSession.checkValid(HashedSession.java:73) ~[jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.session.AbstractSession.getAttribute(AbstractSession.java:132) ~[jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_40]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_40]
at org.scalatra.servlet.AttributesMap$class.get(AttributesMap.scala:26) ~[scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.servlet.RichSession.get(RichSession.scala:9) ~[scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.servlet.RichSession.get(RichSession.scala:9) ~[scalatra_2.10-2.2.1.jar:2.2.1]
at scala.collection.MapLike$class.apply(MapLike.scala:140) ~[scala-library.jar:0.13.0]
at org.scalatra.servlet.RichSession.apply(RichSession.scala:9) ~[scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.atmosphere.ScalatraAtmosphereHandler.onRequest(ScalatraAtmosphereHandler.scala:77) ~[scalatra-atmosphere_2.10-2.2.1.jar:2.2.1]
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:256) ~[atmosphere-runtime-1.0.12.jar:1.0.12]
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:166) ~[atmosphere-runtime-1.0.12.jar:1.0.12]
at org.atmosphere.container.Jetty7CometSupport.service(Jetty7CometSupport.java:96) ~[atmosphere-runtime-1.0.12.jar:1.0.12]
at org.atmosphere.container.JettyAsyncSupportWithWebSocket.service(JettyAsyncSupportWithWebSocket.java:70) ~[atmosphere-runtime-1.0.12.jar:1.0.12]
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:1342) ~[atmosphere-runtime-1.0.12.jar:1.0.12]
at org.scalatra.atmosphere.AtmosphereSupport$$anonfun$handle$1.apply(AtmosphereSupport.scala:129) [scalatra-atmosphere_2.10-2.2.1.jar:2.2.1]
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) [scala-library.jar:0.13.0]
at org.scalatra.DynamicScope$class.withResponse(DynamicScope.scala:80) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.ScalatraServlet.withResponse(ScalatraServlet.scala:49) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.DynamicScope$$anonfun$withRequestResponse$1.apply(DynamicScope.scala:60) [scalatra_2.10-2.2.1.jar:2.2.1]
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) [scala-library.jar:0.13.0]
at org.scalatra.DynamicScope$class.withRequest(DynamicScope.scala:71) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.ScalatraServlet.withRequest(ScalatraServlet.scala:49) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.DynamicScope$class.withRequestResponse(DynamicScope.scala:59) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.ScalatraServlet.withRequestResponse(ScalatraServlet.scala:49) [scalatra_2.10-2.2.1.jar:2.2.1]
at org.scalatra.atmosphere.AtmosphereSupport$class.handle(AtmosphereSupport.scala:123) [scalatra-atmosphere_2.10-2.2.1.jar:2.2.1]
at org.scalatra.example.atmosphere.ChatController.handle(ChatController.scala:18) [classes/:na]
at org.scalatra.ScalatraServlet.service(ScalatraServlet.scala:54) [scalatra_2.10-2.2.1.jar:2.2.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) [javax.servlet-3.0.0.v201112011016.jar:na]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669) [jetty-servlet-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455) [jetty-servlet-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560) [jetty-security-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382) [jetty-servlet-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.Server.handle(Server.java:361) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:937) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:998) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:856) [jetty-http-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240) [jetty-http-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82) [jetty-server-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628) [jetty-io-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52) [jetty-io-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) [jetty-util-8.1.8.v20121106.jar:8.1.8.v20121106]
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) [jetty-util-8.1.8.v20121106.jar:8.1.8.v20121106]

I'm desperate for this to be working else I'm going to have to find another set of technologies to enable long-polling. So if I can help, please let me know.

ntto...@gmail.com

unread,
Sep 10, 2013, 8:48:13 AM9/10/13
to scalat...@googlegroups.com
Also, this problem happens when the transport is set to "polling".

Victor Antofica

unread,
Sep 10, 2013, 11:28:08 AM9/10/13
to scalat...@googlegroups.com
I have the same issue...

ntto...@gmail.com

unread,
Sep 11, 2013, 6:40:57 AM9/11/13
to scalat...@googlegroups.com
I can give you a clue about what is wrong.

After sending a message from the second browser tab, scalatra tries to find the corresponding atmosphere resource (which represents a separate user session). I notice that when it does this, for the second tab it finds two resources - but both have the same uuid - which by definition is meant to be unique. If you look in the network tab of the browser, though, you can definitely see that the second tab has a different uuid in the requests made by atmosphere.js

 Here's the code that helped me identify this issue:


final class ScalatraBroadcaster(id: String, config: AtmosphereConfig)(implicit wireFormat: WireFormat, system: ActorSystem) extends DefaultBroadcaster(id, config) {

  private[this] val logger: Logger = Logger[ScalatraBroadcaster]

  def broadcast[T <: OutboundMessage](msg: T, clientFilter: ClientFilter)(implicit executionContext: ExecutionContext): Future[T] = {
    val selectedResources = resources.asScala map (_.client) filter clientFilter
    logger.info("Sending %s to %s".format(msg, selectedResources.map(_.uuid)))
    broadcast(wireFormat.render(msg), selectedResources.map(_.resource).toSet.asJava).map(_ => msg)
  }

}

If I have some spare time I may be able to look further into the cause of this problem.

ntto...@gmail.com

unread,
Sep 11, 2013, 7:09:17 AM9/11/13
to scalat...@googlegroups.com
To clarify the last post:

1. I am calling send on the server which should send the message to only the tab who sent the request

2. when it finds 2 resources with the same uuid, they have the uuid for the first tab - even though the request and response should be for the second tab
Reply all
Reply to author
Forward
0 new messages