为什么我不能挑选我的案例类?下次我该怎么做才能手动解决这个问题?

时间:2016-04-22 02:16:47

标签: jvm scala.js akka-http scala-pickling

编辑2:观察和问题

  1. 我非常肯定Justin下面的评论者认为问题是由错误的build.sbt配置引起的。但是,这是我第一次看到错误的build.sbt配置,除了之外,所有其他用于拾取器。也许这是因为他们使用宏而我通常会避免它们。

  2. 如果Flow.merge出现问题,为什么使用Flow.map vs sbt会有什么关系?

  3. 可疑的build.sbt提取

    lazy val server = project .dependsOn(sharedJvm, client)

  4. 可疑堆栈跟踪

  5. 所以这是堆栈的顶层:它从我找不到的方法到链接环境到字符串编码工具。确定。

    server java.lang.RuntimeException: stub
    

    咦? stub

    server  at scala.sys.package$.error(package.scala:27)
    server  at scala.scalajs.runtime.package$.linkingInfo(package.scala:143)
    server  at scala.scalajs.runtime.package$.environmentInfo(package.scala:137)
    

    HUH?

    server  at scala.scalajs.js.Dynamic$.global(Dynamic.scala:78)
    

    ???

    server  at boopickle.StringCodec$.encodeUTF8(StringCodec.scala:56)
    

    编辑1:我的大而美丽的build.sbt可能是问题

    您看不到的是我在project文件夹中组织的内容:

    • JvmDependencies.scala,它具有常规的Jvm依赖关系
    • SjsDependencies.scala Def.settingsKey上有libraryDependencies JsModuleID个<{1}}
    • WebJarDependencies.scala有javascripts和css的

    build.sbt

    lazy val    shared = (crossProject.crossType(CrossType.Pure) in file("shared"))
      .configure(_.enablePlugins(ScalaJSPlugin))
      .settings(SjsDependencies.pickling.toSettingsDefinition(): _*)
      .settings(SjsDependencies.tagsAndDom.toSettingsDefinition(): _*)
      .settings(SjsDependencies.css.toSettingsDefinition(): _*)
    
    lazy val sharedJvm = shared.jvm
    lazy val  sharedJs = shared.js
    
    lazy val    cmdlne = project
      .dependsOn(sharedJvm)
      .settings(
        libraryDependencies ++= (
          JvmDependencies.commandLine ++
          JvmDependencies.logging     ++
          JvmDependencies.akka        ++
          JvmDependencies.serialization
        )
      )
    
    lazy val    client = project
      .enablePlugins(ScalaJSPlugin, SbtWeb, SbtSass)
      .dependsOn(sharedJs)
      .settings(
        (SjsDependencies.shapeless ++ SjsDependencies.audiovideo ++ SjsDependencies.databind ++ SjsDependencies.functional ++ SjsDependencies.lensing ++ SjsDependencies.logging ++ SjsDependencies.reactive).toSettingsDefinition(),
        jsDependencies ++= WebjarDependencies.js,
        libraryDependencies ++= WebjarDependencies.notJs,
        persistLauncher in Compile := true
      )
    
    lazy val    server = project
      .dependsOn(sharedJvm, client)
      .enablePlugins(SbtNativePackager)
      .settings(
    
        copyWebJarResources := { streams.value.log("Copying webjar resources")
          val `Web Modules target directory` = (resourceManaged in Compile).value / "assets"
          val `Web Modules source directory` = (WebKeys.assets in Assets in client).value / "lib"
    
          final class UsefulFileFilter(acceptable: String*) extends FileFilter {
    
            // TODO ADJUST TO EXCLUDE JS MAP FILES
            import scala.collection.JavaConversions._
            def accept(file: File) = (file.isDirectory && FileUtils.listFiles(file, acceptable.toArray, true).nonEmpty) || acceptable.contains(file.ext) && !file.name.contains(".js.")
          }
    
          val `file filter` = new UsefulFileFilter("css", "scss", "sass", "less", "map")
    
          IO.createDirectory(`Web Modules target directory`)
          IO.copyDirectory(source = `Web Modules source directory`, target = `Web Modules target directory` / "script")
          FileUtils.copyDirectory(`Web Modules source directory`, `Web Modules target directory` / "style", `file filter`)
        },
    
        // run the copy after compile/assets but before managed resources
        copyWebJarResources <<= copyWebJarResources dependsOn(compile in Compile, WebKeys.assets in Compile in client, fastOptJS in Compile in client),
        managedResources in Compile <<= (managedResources in Compile) dependsOn copyWebJarResources,
    
        watchSources <++= (watchSources in client),
    
    
        resourceGenerators in Compile <+= Def.task {
          val files = ((crossTarget in(client, Compile)).value ** ("*.js" || "*.map")).get
          val mappings: Seq[(File,String)] = files pair rebase((crossTarget in(client, Compile)).value, ((resourceManaged in  Compile).value / "assets/").getAbsolutePath )
          val map: Seq[(File, File)] = mappings.map { case (s, t) => (s, file(t))}
          IO.copy(map).toSeq
        },
    
        reStart <<= reStart dependsOn (managedResources in Compile),
    
        libraryDependencies ++= (
          JvmDependencies.akka                ++
          JvmDependencies.jarlocating         ++
          JvmDependencies.functional          ++
          JvmDependencies.serverPickling      ++
          JvmDependencies.logging             ++
          JvmDependencies.serialization       ++
          JvmDependencies.testing
        )
      )
    

    编辑0:一个非常模糊的聊天帖子有一个人说出我的感受:不,不是**** scala,但是

      

    Mark Eibes @ i-am-the-slime 2015年10月15日09:37   @ochrons我还在战斗。我似乎无法腌制任何东西。   https://gitter.im/scala-js/scala-js/archives/2015/10/15

    我有一个相当简单的要求 - 我在akka http服务器上有一个定义为AkkaServerLogEventToMessageHandler()的Web套接字路由:

    object AkkaServerLogEventToMessageHandler
      extends Directives {
    
      val sourceOfLogs =
    
        Source.actorPublisher[AkkaServerLogMessage](AkkaServerLogEventPublisher.props) map {
          event ⇒
            BinaryMessage(
              ByteString(
                Pickle.intoBytes[AkkaServerLogMessage](event)
              )
            )
        }
    
      def apply(): server.Route = {
        handleWebSocketMessages(
          Flow[Message].merge(sourceOfLogs)
        )
      }
    
    }
    

    这最明显的方式适用于一小部分路线。

    现在为什么我无法让boopickleupickleprickle序列化像这个愚蠢的案例类一样简单的东西?

    sealed case class AkkaServerLogMessage(
                                     message:   String,
                                     level:     Int,
                                     timestamp: Long
                                   )
    
    • 没有嵌套
    • 所有原始类型
    • 没有泛型
    • 只有三个

    这些都产生了大致相同的错误

    • 使用所有三个常用的选择器来编写
    • 使用TextMessage代替BinaryMessage以及相应的upickleprickle writeJs或其他任何方法
    • case class变为零(没有,没有成员)
    • 将输入本身改为case class
    • 导入Implicits和下划线内容的各种排列

    ......具体来说,他们给了我同样愚蠢错误的变体(不是同样的错误,但非常相似)

    server [ERROR] [04/21/2016 22:04:00.362] [app-akka.actor.default-dispatcher-7] [akka.actor.ActorSystemImpl(app)] WebSocket handler failed with stub
    server java.lang.RuntimeException: stub
    server  at scala.sys.package$.error(package.scala:27)
    server  at scala.scalajs.runtime.package$.linkingInfo(package.scala:143)
    server  at scala.scalajs.runtime.package$.environmentInfo(package.scala:137)
    server  at scala.scalajs.js.Dynamic$.global(Dynamic.scala:78)
    server  at boopickle.StringCodec$.encodeUTF8(StringCodec.scala:56)
    server  at boopickle.Encoder.writeString(Codecs.scala:338)
    server  at boopickle.BasicPicklers$StringPickler$.pickle(Pickler.scala:183)
    server  at boopickle.BasicPicklers$StringPickler$.pickle(Pickler.scala:134)
    server  at boopickle.PickleState.pickle(Pickler.scala:511)
    server  at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1$Pickler$macro$1$2$.pickle(AkkaServerLogEventToMessageHandler.scala:35)
    server  at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1$Pickler$macro$1$2$.pickle(AkkaServerLogEventToMessageHandler.scala:35)
    server  at boopickle.PickleImpl$.apply(Default.scala:70)
    server  at boopickle.PickleImpl$.intoBytes(Default.scala:75)
    server  at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1.apply(AkkaServerLogEventToMessageHandler.scala:35)
    server  at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1.apply(AkkaServerLogEventToMessageHandler.scala:31)
    

    这有效

    • 不使用Flow.merge(违背目的,我希望继续发送带有日志的内容)
    • 使用静态值
    • 其他无用的东西

    上诉

    请让我知道我愚蠢的地点和原因......今天我以不同的形式在这个问题上花了四个小时,这让我疯狂。

2 个答案:

答案 0 :(得分:1)

build.sbt,您有:

lazy val shared = (crossProject.crossType(CrossType.Pure) in file("shared"))
  .configure(_.enablePlugins(ScalaJSPlugin))

不要这样做。您不能在跨项目上启用Scala.js插件。这也将它添加到JVM端,这将造成严重破坏。最值得注意的是,这将导致%%%解析JVM项目中依赖项的Scala.js工件,这非常糟糕。这就是导致您出现问题的原因。

crossProject已经将Scala.js插件添加到JS部分,只有那个插件。因此,只需删除enablePlugins行。

答案 1 :(得分:0)

神秘解决了。感谢@Justin du Coeur指出我正确的方向。

NavLink特别没有工作的原因是因为在依赖关系链中我包含了Linkboopickle版本的sjs jvm项目。

我删除了boopickle的{​​{1}} serverserver,并从共享依赖项中删除了dependsOn。现在它有效。