将scala-async的依赖性添加到在scala上编写的项目中播放2 + slick

时间:2013-12-06 20:37:05

标签: scala asynchronous playframework-2.0 slick

我正在使用scala play 2 + slick编写一个Web应用程序。我也想使用akka + scala-async。将 scala-async 的依赖项添加到我的项目并从播放控制台运行应用程序(使用“运行”命令)后,我的应用程序失败打造。但是,当我使用“dist”命令并运行网站时,一切正常正常。我知道这个问题在某种程度上与使用的scala-async相关联。

使用“run”命令构建时,我得到以下异常:

play.api.UnexpectedException: Unexpected exception[NoSuchMethodException: slick.
tables.Requests$.<init>()]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anon
fun$1.apply(ApplicationProvider.scala:148) ~[play_2.10-2.2.1.jar:2.2.1]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anon
fun$1.apply(ApplicationProvider.scala:112) ~[play_2.10-2.2.1.jar:2.2.1]
        at scala.Option.map(Option.scala:145) ~[scala-library-2.10.3.jar:na]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply
(ApplicationProvider.scala:112) ~[play_2.10-2.2.1.jar:2.2.1]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply
(ApplicationProvider.scala:110) ~[play_2.10-2.2.1.jar:2.2.1]
        at scala.util.Success.flatMap(Try.scala:200) ~[scala-library-2.10.3.jar:
na]
Caused by: java.lang.NoSuchMethodException: slick.tables.Requests$.<init>()
        at java.lang.Class.getConstructor0(Class.java:2800) ~[na:1.7.0_40]
        at java.lang.Class.getConstructor(Class.java:1708) ~[na:1.7.0_40]
        at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$constructorToJa
va$1.apply(JavaMirrors.scala:1242) ~[scala-reflect-2.10.3.jar:na]
        at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$constructorToJa
va$1.apply(JavaMirrors.scala:1236) ~[scala-reflect-2.10.3.jar:na]
        at scala.reflect.runtime.TwoWayCache.toJava(TwoWayCache.scala:49) ~[scal
a-reflect-2.10.3.jar:na]
        at scala.reflect.runtime.JavaMirrors$JavaMirror.constructorToJava(JavaMi
rrors.scala:1236) ~[scala-reflect-2.10.3.jar:na]

如何使其有效?

修改

我知道这个问题在某种程度上与使用 scala-async 有关,因为当我尝试使用我的宏来生成 forInsert时会出现同样的错误我的光滑表中的语句,而不依赖于 scala-async

最近我发现了另一件有趣的事情。 如果我使用 class 而不是 object 来描述我的光滑表,则错误消失。虽然在这种情况下,play框架会启动无休止的重新编译循环我用我的宏。

修改

这是我的Buid.scala

import sbt._
import Keys._
import Defaults.defaultSettings
import org.scalastyle.sbt.ScalastylePlugin.{Settings => scalastyleSettings}
import play.Project.playScalaSettings
import net.virtualvoid.sbt.graph.Plugin.graphSettings

object Resolvers {
  val typesafe = Resolver.typesafeRepo("releases")
  val sonatype = Resolver.sonatypeRepo("releases")
}

import Resolvers._

object Dependencies {
  val scalatest = "org.scalatest" %% "scalatest" % "1.9.2" % "test"
  val scalamock = "org.scalamock" %% "scalamock-scalatest-support" % "3.0.1" % "test"
  val scalaz = "org.scalaz" %% "scalaz-core" % "7.0.4"
  val akka = "com.typesafe.akka" %% "akka-actor" % "2.2.3"
  val slickorm = "com.typesafe.slick" %% "slick" % "1.0.1"
  val scalacheck = "org.scalacheck" %% "scalacheck" % "1.10.1" % "test"
  val webjarsPlay = "org.webjars" %% "webjars-play" % "2.2.0"
  val underscorejs = "org.webjars" % "underscorejs" % "1.5.1"
  val jquery = "org.webjars" % "jquery" % "2.0.3-1"
  val angularjs = "org.webjars" % "angularjs" % "1.2.0-rc.3"
  val angularui = "org.webjars" % "angular-ui-bootstrap" % "0.6.0-1"
  val bootstrap = "org.webjars" % "bootstrap" % "2.3.2" exclude("org.webjars", "jquery")
  val requirejs = "org.webjars" % "requirejs" % "2.1.8"
  val playSlick = "com.typesafe.play" %% "play-slick" % "0.5.0.8"
  val logback = "ch.qos.logback" % "logback-classic" % "1.0.13"
  val postgresql = "postgresql" % "postgresql" % "9.1-901.jdbc4"
  val nscalaTime = "com.github.nscala-time" %% "nscala-time" % "0.6.0"
  val scalaAsync = "org.scala-lang.modules" %% "scala-async" % "0.9.0-M4"
}

import Dependencies._

object BankSettings {
  val bankSettings = Seq(
    organization := "org.zeka",
    version := "0.0.0-SNAPSHOT",
    scalaVersion := "2.10.3",
    scalacOptions := Seq(
      "-optimise",
      "-deprecation",
      "-unchecked",
      "-feature",
      "-g:vars",
      "-target:jvm-1.7",
      "-encoding", "UTF-8",
      "-language:postfixOps"
    ),
    resolvers ++= Seq(
      typesafe,
      sonatype
    )
  )
}

import BankSettings._

object BankBuild extends Build {
  lazy val bank = Project(
    "bank",
    file ("."),
    settings = defaultSettings ++ scalastyleSettings ++ graphSettings ++ playScalaSettings ++ bankSettings ++ Seq(
      libraryDependencies ++= Seq(
        scalatest,
        scalamock,
        scalaz,
        akka,
        logback,
        playSlick,
        webjarsPlay,
        bootstrap,
        angularjs,
        angularui
      )
    )
  ) dependsOn (common, logick, slick) aggregate (common, logick, slick)

  lazy val common = Project(
    "common",
    file ("modules/common"),
    settings = defaultSettings ++ scalastyleSettings ++ graphSettings ++ bankSettings ++ Seq(
      libraryDependencies ++= Seq(
        scalatest,
        scalamock,
        nscalaTime
      )
    )
  )

  lazy val logick = Project(
    "logic",
    file ("modules/logic"),
    settings = defaultSettings ++ scalastyleSettings ++ graphSettings ++ bankSettings ++ Seq(
      libraryDependencies ++= Seq(
        scalatest,
        scalamock,
        akka,
        scalaAsync
      )
    )
  ) dependsOn (common, slick)

  lazy val slick = Project(
    "slick",
    file ("modules/slick"),
    settings = defaultSettings ++ scalastyleSettings ++ graphSettings ++ bankSettings ++ Seq(
      libraryDependencies ++= Seq(
        scalatest,
        scalamock,
        akka,
        slickorm,
        postgresql
      )
    )
  ) dependsOn common
}

修改

这是我的宏。

package slick

import scala.language.experimental.macros
import scala.reflect.macros.Context
import scala.slick.driver.PostgresDriver.simple._
import scala.slick.lifted.ColumnBase
import scala.reflect.api.Liftable._

object SlickMacro {
  def *[T]: ColumnBase[T] = macro starImpl[T]
  def starImpl[T: c.WeakTypeTag](c: Context): c.Expr[ColumnBase[T]] = {
    import c.universe._
    val tpe = weakTypeOf[T]
    if (!tpe.typeSymbol.asClass.isCaseClass) {
      c.abort(c.enclosingPosition, "not a case class")
    } else {
      val companion = tpe.typeSymbol.companionSymbol
      val params = tpe.declarations.collectFirst {
        case m: MethodSymbol if m.isPrimaryConstructor => m
      }.get.paramss.head
      def build(params: List[Symbol], acc: Tree): Tree = params match {
        case Nil => acc
        case h :: t => build(t, q"$acc ~ ${h.name}")
      }
      c.Expr[ColumnBase[T]] {
        q"${build(params.tail, q"id.?")} <> ($companion, $companion.unapply _)"
      }
    }
  }
  def forInsert[T]: ColumnBase[T] = macro forInsertImpl[T]
  def forInsertImpl[T: c.WeakTypeTag](c: Context): c.Expr[ColumnBase[T]] = {
    import c.universe._
    val tpe = weakTypeOf[T]
    if (!tpe.typeSymbol.asClass.isCaseClass) {
      c.abort(c.enclosingPosition, "not a case class")
    } else {
      val companion = tpe.typeSymbol.companionSymbol
      val params = tpe.declarations.collectFirst {
        case m: MethodSymbol if m.isPrimaryConstructor => m
      }.get.paramss.head
      def build(params: List[Symbol], acc: Tree): Tree = params match {
        case Nil => acc
        case h :: t => build(t, q"$acc ~ ${h.name}")
      }
      val paramsTail = params.tail
      def l1 = (1 to paramsTail.size).map(i => q"x.${newTermName("_" + i)}")
      def l2 = (2 to params.size).map(i => q"x.${newTermName("_" + i)}")
      c.Expr[ColumnBase[T]] {
        q"${build(paramsTail.tail, q"${paramsTail.head.name}")} <> ({ x => $companion(None, ..$l1) }, { (u: $tpe) => $companion.unapply(u).map(x => (..$l2)) })"
      }
    }
  }
}

0 个答案:

没有答案