为什么Scalatra有时会给我一个FlashMap转换错误?

时间:2014-08-04 23:03:28

标签: scala scalatra scalate

在代码重新加载模式下运行Scalatra时,如果我在重新初始化scalate引擎之前加载页面,则会出现500错误。

如果我看终端直到看起来引擎已完全重新加载,它运行正常,但我认为当我在a)成功编译和b)容器重启之间加载页面时会发生这种情况。

在我改变其他内容并强制进行新的编译和代码重新加载之前,这不会纠正自己。

我似乎无法找到为什么会这样,有没有人有任何想法?

以下是我重新加载代码的方法:

./sbt "container:start" "~ ;copy-resources;aux-compile"

以下是我看到的错误:

HTTP ERROR 500

Problem accessing /. Reason:

    org.scalatra.FlashMap cannot be cast to org.scalatra.FlashMap
Caused by:

java.lang.ClassCastException: org.scalatra.FlashMap cannot be cast to org.scalatra.FlashMap
    at org.scalatra.FlashMapSupport$$anonfun$org$scalatra$FlashMapSupport$$getFlash$2$$anonfun$1.apply(flashMap.scala:182)
    at org.scalatra.FlashMapSupport$$anonfun$org$scalatra$FlashMapSupport$$getFlash$2$$anonfun$1.apply(flashMap.scala:182)
    at scala.Option.map(Option.scala:145)
    at org.scalatra.FlashMapSupport$$anonfun$org$scalatra$FlashMapSupport$$getFlash$2.apply(flashMap.scala:181)
    at org.scalatra.FlashMapSupport$$anonfun$org$scalatra$FlashMapSupport$$getFlash$2.apply(flashMap.scala:180)
    at scala.Option.getOrElse(Option.scala:120)
    at org.scalatra.FlashMapSupport$class.org$scalatra$FlashMapSupport$$getFlash(flashMap.scala:180)
    at org.scalatra.FlashMapSupport$class.flash(flashMap.scala:192)
    at beekeeper.controllers.HomeServlet.flash(HomeServlet.scala:13)
    at org.scalatra.FlashMapSupport$$anonfun$handle$1.apply$mcV$sp(flashMap.scala:137)
    at org.scalatra.FlashMapSupport$$anonfun$handle$1.apply(flashMap.scala:136)
    at org.scalatra.FlashMapSupport$$anonfun$handle$1.apply(flashMap.scala:136)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57)
    at org.scalatra.DynamicScope$class.withRequest(DynamicScope.scala:71)
    at org.scalatra.ScalatraServlet.withRequest(ScalatraServlet.scala:49)
    at org.scalatra.FlashMapSupport$class.handle(flashMap.scala:136)
    at beekeeper.controllers.HomeServlet.handle(HomeServlet.scala:13)
    at org.scalatra.ScalatraServlet.service(ScalatraServlet.scala:54)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:365)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485)
    at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:926)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:988)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Thread.java:744)

2 个答案:

答案 0 :(得分:0)

此错误表示同一个类有2个实例,由不同的类加载器加载。这种行为植根于java:来自不同类加载器的类是不一样的。基本上equals类的方法是类名和类加载器的功能。在这种情况下,即使它们来自同一个jar或文件夹,类也不一样。

当容器重新加载代码时,它会创建一个新的类加载器,而你的会话仍然保存使用旧类加载器加载的flash map的实例。这很可能是问题的原因。

答案 1 :(得分:0)

在Java中,每个类都由其完全限定的类名加载它的类加载器标识,这意味着:

ClassLoader1.my.package.MyClass != ClassLoader2.my.package.MyClass

这表明无法将MyClass中加载的ClassLoader1类对象转换为从MyClass加载的ClassLoader2类型。您可以在

上找到更多详细信息

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

另一方面,不可能在同一个类加载器中加载相同的类两次,所以你需要一个新的类加载器,没有办法解决它。虽然我从未编写过执行类重新加载的代码,但可以假设类重新加载在实践中意味着:

  • 创建一个新的类加载器
  • 重新加载课程
  • 交换类加载器

由于上面所描述的内容,在设计应该重新加载的类时需要小心:参见http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html#designing