SBT 错误的编译顺序
SBT incorrect order of compilation
TL/DR:检查最后两次提交和 运行 sbt clean compile
:https://github.com/mirelon/akka-in-action/tree/json/chapter2
有RestInterface.scala:
package com.goticks
import akka.actor._
import spray.routing._
import spray.http.StatusCodes
import spray.httpx.SprayJsonSupport._
import spray.routing.RequestContext
import akka.util.Timeout
import scala.concurrent.duration._
import scala.language.postfixOps
class RestInterface extends HttpServiceActor
with RestApi {
def receive = runRoute(routes)
}
trait RestApi extends HttpService { actor: Actor =>
import context.dispatcher
import com.goticks.TicketProtocol._
implicit val timeout = Timeout(10 seconds)
import akka.pattern.ask
def routes: Route =
path("events") {
get { requestContext =>
context.actorOf(Props[Resu]).ask(GetEvents)
}
}
}
class Responder(requestContext:RequestContext) extends Actor {
import TicketProtocol._
def receive = {
case Events(events) =>
requestContext.complete(StatusCodes.OK, events)
self ! PoisonPill
}
}
和Resu.scala(注意Resu按字母顺序排在RestInterface之后)
package com.goticks
import akka.actor.Actor
class Resu extends Actor {
import TicketProtocol._
import spray.json._
def receive = {
case GetEvents => {
println(Event(event = "E").toJson)
}
}
}
object TicketProtocol {
import spray.json._
case class Event(event:String)
case object GetEvents
case class Events(events:List[Event])
object Event extends DefaultJsonProtocol {
implicit val format = jsonFormat1(Event.apply)
}
}
build.sbt:
name := "goticks"
version := "0.1-SNAPSHOT"
organization := "com.goticks"
scalaVersion := "2.11.1"
libraryDependencies ++= {
val akkaVersion = "2.3.4"
val sprayVersion = "1.3.1"
Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"io.spray" %% "spray-can" % sprayVersion,
"io.spray" %% "spray-routing" % sprayVersion,
"io.spray" %% "spray-json" % "1.2.6"
)
}
build.properties;
sbt.version=0.13.7
plugins.sbt:
resolvers += Classpaths.typesafeResolver
resolvers += "sbt-idea" at "http://mpeltonen.github.com/maven/"
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.10.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.8")
编译问题
当我运行sbt clean compile
时,一切正常。但是当我将 Resu
class 重构为 Ress
时(请注意 Ress
按字母顺序排列在 RestInterface
之前)(同时重命名其文件,可以在此处查看差异:https://github.com/mirelon/akka-in-action/commit/583ca801fb7d1564024eee2f98d57f03ecacc6e5),则出现编译错误:
[error] /home/miso/IdeaProjects/akka-in-action/chapter2/src/main/scala/com/goticks/Ress.scala:12: Cannot find JsonWriter or JsonFormat type class for com.goticks.TicketProtocol.Event
[error] println(Event(event = "E").toJson)
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
显然缺少一个隐含的 json 作者。可能是由于编译顺序不正确吗? sbt 能否按字母顺序编译 classes,忽略导入?
是的,sbt 总是按字母顺序编译。问题是 sbt 在运行编译器之前不知道文件之间的依赖关系。
您看到的是 Scala 编译器本身依赖于源文件的顺序。 Sbt 总是对源文件进行排序,因此您至少可以通过将代码置于有效的顺序来解决这些问题。
我不是 100% 确定你为什么会从一些隐式 + 宏 hackery 中遇到这样的问题,但这可能是错误的。
TL/DR:检查最后两次提交和 运行 sbt clean compile
:https://github.com/mirelon/akka-in-action/tree/json/chapter2
有RestInterface.scala:
package com.goticks
import akka.actor._
import spray.routing._
import spray.http.StatusCodes
import spray.httpx.SprayJsonSupport._
import spray.routing.RequestContext
import akka.util.Timeout
import scala.concurrent.duration._
import scala.language.postfixOps
class RestInterface extends HttpServiceActor
with RestApi {
def receive = runRoute(routes)
}
trait RestApi extends HttpService { actor: Actor =>
import context.dispatcher
import com.goticks.TicketProtocol._
implicit val timeout = Timeout(10 seconds)
import akka.pattern.ask
def routes: Route =
path("events") {
get { requestContext =>
context.actorOf(Props[Resu]).ask(GetEvents)
}
}
}
class Responder(requestContext:RequestContext) extends Actor {
import TicketProtocol._
def receive = {
case Events(events) =>
requestContext.complete(StatusCodes.OK, events)
self ! PoisonPill
}
}
和Resu.scala(注意Resu按字母顺序排在RestInterface之后)
package com.goticks
import akka.actor.Actor
class Resu extends Actor {
import TicketProtocol._
import spray.json._
def receive = {
case GetEvents => {
println(Event(event = "E").toJson)
}
}
}
object TicketProtocol {
import spray.json._
case class Event(event:String)
case object GetEvents
case class Events(events:List[Event])
object Event extends DefaultJsonProtocol {
implicit val format = jsonFormat1(Event.apply)
}
}
build.sbt:
name := "goticks"
version := "0.1-SNAPSHOT"
organization := "com.goticks"
scalaVersion := "2.11.1"
libraryDependencies ++= {
val akkaVersion = "2.3.4"
val sprayVersion = "1.3.1"
Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"io.spray" %% "spray-can" % sprayVersion,
"io.spray" %% "spray-routing" % sprayVersion,
"io.spray" %% "spray-json" % "1.2.6"
)
}
build.properties;
sbt.version=0.13.7
plugins.sbt:
resolvers += Classpaths.typesafeResolver
resolvers += "sbt-idea" at "http://mpeltonen.github.com/maven/"
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.10.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.8")
编译问题
当我运行sbt clean compile
时,一切正常。但是当我将 Resu
class 重构为 Ress
时(请注意 Ress
按字母顺序排列在 RestInterface
之前)(同时重命名其文件,可以在此处查看差异:https://github.com/mirelon/akka-in-action/commit/583ca801fb7d1564024eee2f98d57f03ecacc6e5),则出现编译错误:
[error] /home/miso/IdeaProjects/akka-in-action/chapter2/src/main/scala/com/goticks/Ress.scala:12: Cannot find JsonWriter or JsonFormat type class for com.goticks.TicketProtocol.Event
[error] println(Event(event = "E").toJson)
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
显然缺少一个隐含的 json 作者。可能是由于编译顺序不正确吗? sbt 能否按字母顺序编译 classes,忽略导入?
是的,sbt 总是按字母顺序编译。问题是 sbt 在运行编译器之前不知道文件之间的依赖关系。
您看到的是 Scala 编译器本身依赖于源文件的顺序。 Sbt 总是对源文件进行排序,因此您至少可以通过将代码置于有效的顺序来解决这些问题。
我不是 100% 确定你为什么会从一些隐式 + 宏 hackery 中遇到这样的问题,但这可能是错误的。