Почему я не могу мариновать свои кейсы? Что я должен сделать, чтобы решить эту проблему вручную в следующий раз?

Изменить 2: Наблюдения и вопросы

  1. Я почти уверен вместе с комментатором Джастином, что проблема связана с ошибкой build.sbt конфигурации. Тем не менее, я впервые вижу странствующего build.sbt конфигурация, которая буквально работает для всего остального, кроме сборщиков. Может быть, это потому, что они используют макросы, а я, как правило, избегаю их.

  2. Почему это важно Flow.merge используется против Flow.map если проблема с sbt?

  3. Подозрительный экстракт build.sbt

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

  4. Подозрительный след стека

Так что это вершина стека: он идет от метода, который я не могу найти, к среде связывания с утилитами кодирования строк. Хорошо.

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)

А?

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 на JsModuleIDs
  • WebJarDependencies.scala который имеет JavaScript и 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, но

Марк Эйбс @i-am-the-slime 15 октября 2015 09:37 @ochrons Я все еще сражаюсь. Я не могу больше мариновать. https://gitter.im/scala-js/scala-js/archives/2015/10/15

У меня довольно простое требование - у меня есть один маршрут веб-сокета на akka http-сервер, который определен AkkaServerLogEventToMessageHandler():

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)
    )
  }

}

Это вписывается в крошечный набор маршрутов наиболее очевидным способом.

Теперь почему я не могу получить boopickle, upickle, или же prickle сериализовать что-то столь же простое, как этот тупой класс case?

sealed case class AkkaServerLogMessage(
                                 message:   String,
                                 level:     Int,
                                 timestamp: Long
                               )
  • Нет вложенности
  • Все примитивные типы
  • Нет дженериков
  • Только три из них

Все это выдает примерно одинаковую ошибку

  • Используя все три общих сборщика, чтобы написать
  • С помощью TextMessage вместо BinaryMessage и соответствующий upickle или же pricklewriteJs или какими-либо методами
  • Меняя 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 ответа

В вашем build.sbt, у тебя есть:

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

Не делайте этого. Вы никогда не должны включать плагин Scala.js для кросс-проекта. Это также добавляет это к стороне JVM, которая вызовет хаос. В частности, это приведет к %%% разрешить артефакты Scala.js ваших зависимостей в проекте JVM, и это действительно плохо. Это то, что вызывает вашу проблему.

crossProject уже добавляет плагин Scala.js к части JS, и только эту. Так просто убери это enablePlugins линия.

Тайна разгадана. Спасибо @Justin du Coeur за то, что указал мне правильное направление.

Причина boopickle не работал, в частности, потому что в цепочке зависимостей я включал как sjs и jvm версия boopickle в server проект.

Я удалил serverdependsOn за client и для sharedJs а также удалены boopickle из общих зависимостей. Теперь это работает.

Другие вопросы по тегам