[英]How can I connect a scala play application to postgres database
I'm trying to connect a basic play application to my remote postgres database. 我正在尝试将基本播放应用程序连接到我的远程postgres数据库。 After overcoming a few walls, I'm now stuck on a seemingly unexplained exception when connecting.
在克服了几面墙之后,我现在在连接时遇到了一个看似无法解释的异常。 The application is barely more than that created from "activator new".
该应用程序仅比“activator new”创建的应用程序更多。
tl;dr TL;博士
When creating database in play application, an exception is thrown: 在Play应用程序中创建数据库时,会抛出异常:
[ClassNotFoundException: slick.jdbc.hikaricp.HikariCPJdbcDataSource$]
Details 细节
Here's my simple application.scala : 这是我简单的application.scala :
package controllers
import play.api._
import play.api.mvc._
import play.api.Logger
import slick.jdbc.JdbcBackend.Database
class Application extends Controller {
def index = Action {
testdb()
Ok(views.html.index("Your new application is ready."))
}
def testdb(): Unit = {
val db = Database.forConfig("db.local")
}
}
And my build.sbt : 我的build.sbt :
name := """elophant"""
version := "0.0.1"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test,
"org.postgresql" % "postgresql" % "9.4-1204-jdbc4",
"com.zaxxer" % "HikariCP" % "2.4.1",
"com.typesafe.slick" %% "slick" % "3.1.0",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
routesGenerator := InjectedRoutesGenerator
And application.conf : 和application.conf :
play.crypto.secret = "xxx"
play.i18n.langs = [ "en" ]
db.local.driver: org.postgresql.Driver
db.local.url="jdbc:postgresql://"${?ELOPHANT_GATEWAY}":xxx/elophant"
db.local.username=elophantuser
db.local.password=${?ELOPHANT_USER_PASSWORD}
(Note: I verified that the above environment variables are all set correctly) (注意:我确认上面的环境变量都设置正确)
But when I hit the index action, I get the following exception: 但是当我点击索引操作时,我得到以下异常:
[info] - application - Creating Pool for datasource 'local'
[info] - play.api.db.DefaultDBApi - Database [local] connected at jdbc:postgresql://174.1.53.209:19213/elophant
[info] - play.api.Play - Application started (Dev)
[error] - application -
! @6nnd5nh6h - Internal server error, for (GET) [/] ->
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ClassNotFoundException: slick.jdbc.hikaricp.HikariCPJdbcDataSource$]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:265) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:191) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:179) [play_2.11-2.4.3.jar:2.4.3]
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:212) [play_2.11-2.4.3.jar:2.4.3]
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:94) [play_2.11-2.4.3.jar:2.4.3]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:158) [play-netty-server_2.11-2.4.3.jar:2.4.3]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:155) [play-netty-server_2.11-2.4.3.jar:2.4.3]
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.6.jar:na]
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:215) [scala-library-2.11.6.jar:na]
at scala.util.Try$.apply(Try.scala:191) [scala-library-2.11.6.jar:na]
at scala.util.Failure.recover(Try.scala:215) [scala-library-2.11.6.jar:na]
at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.6.jar:na]
at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.6.jar:na]
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) [scala-library-2.11.6.jar:na]
at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109) [play-iteratees_2.11-2.4.3.jar:2.4.3]
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71) [play-iteratees_2.11-2.4.3.jar:2.4.3]
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) [scala-library-2.11.6.jar:na]
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) [scala-library-2.11.6.jar:na]
at scala.concurrent.Promise$class.complete(Promise.scala:55) [scala-library-2.11.6.jar:na]
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) [scala-library-2.11.6.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23) [scala-library-2.11.6.jar:na]
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40) [akka-actor_2.11-2.3.13.jar:na]
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397) [akka-actor_2.11-2.3.13.jar:na]
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library-2.11.6.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.11.6.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.6.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.6.jar:na]
Caused by: java.lang.ClassNotFoundException: slick.jdbc.hikaricp.HikariCPJdbcDataSource$
at java.lang.ClassLoader.findClass(ClassLoader.java:530) ~[na:1.8.0_60]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_60]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_60]
at slick.util.ClassLoaderUtil$$anon$1.loadClass(ClassLoaderUtil.scala:12) ~[slick_2.11-3.1.0.jar:na]
at slick.jdbc.JdbcDataSource$.loadFactory$1(JdbcDataSource.scala:30) ~[slick_2.11-3.1.0.jar:na]
at slick.jdbc.JdbcDataSource$.forConfig(JdbcDataSource.scala:35) ~[slick_2.11-3.1.0.jar:na]
at slick.jdbc.JdbcBackend$DatabaseFactoryDef$class.forConfig(JdbcBackend.scala:268) ~[slick_2.11-3.1.0.jar:na]
at slick.jdbc.JdbcBackend$$anon$3.forConfig(JdbcBackend.scala:33) ~[slick_2.11-3.1.0.jar:na]
at controllers.Application.testdb(Application.scala:17) ~[classes/:na]
at controllers.Application$$anonfun$index$1.apply(Application.scala:11) ~[classes/:na]
at controllers.Application$$anonfun$index$1.apply(Application.scala:10) ~[classes/:na]
at play.api.mvc.ActionBuilder$$anonfun$apply$17.apply(Action.scala:439) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.ActionBuilder$$anonfun$apply$17.apply(Action.scala:439) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:408) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:407) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$.invokeBlock(Action.scala:533) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$.invokeBlock(Action.scala:530) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.11-2.4.3.jar:2.4.3]
at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103) ~[play_2.11-2.4.3.jar:2.4.3]
at scala.Option.map(Option.scala:146) ~[scala-library-2.11.6.jar:na]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.libs.iteratee.DoneIteratee$$anonfun$mapM$2.apply(Iteratee.scala:741) ~[play-iteratees_2.11-2.4.3.jar:2.4.3]
at play.api.libs.iteratee.DoneIteratee$$anonfun$mapM$2.apply(Iteratee.scala:741) ~[play-iteratees_2.11-2.4.3.jar:2.4.3]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [scala-library-2.11.6.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [scala-library-2.11.6.jar:na]
... 6 common frames omitted
Some googling suggested that I include that hikari library in my build.sbt, but it hasn't seemed to help (also, it's not in any of the documentation for play itself). 一些谷歌搜索建议我在我的build.sbt中包含hikari库,但它似乎没有帮助(同样,它不在任何游戏本身的文档中)。
My java configuration skills are negligible, so any help would be appreciated! 我的java配置技能可以忽略不计,所以任何帮助都将不胜感激!
I managed to resolve it. 我设法解决了它。 After some searching I stumbled upon a more modern slick/postgres tutorial (incidentally, this seems like a very useful blog post for anyone trying to setup a slick+postgres play app):
经过一番搜索后,我偶然发现了一个更现代的光滑/ postgres教程(顺便说一下,这似乎是一个非常有用的博客文章,任何人试图设置一个光滑+ postgres播放应用程序):
Below is the link to the post : 以下是帖子的链接:
https://stonecolddev.in/posts/playing-with-scala-building-a-small-web-app-with-play-2-4-play-slick-and-postgres.html
As a result, I added these two libraries to my build.sbt: 结果,我将这两个库添加到build.sbt中:
"com.typesafe.play" %% "play-slick" % "1.1.0",
"com.typesafe.play" %% "play-slick-evolutions" % "1.1.0"
This caused my exception to change into this: 这导致我的异常改为:
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) A binding to play.api.db.DBApi was already configured at play.api.db.slick.evolutions.EvolutionsModule.bindings(EvolutionsModule.scala:15):
Binding(interface play.api.db.DBApi to ConstructionTarget(class play.api.db.slick.evolutions.internal.DBApiAdapter) in interface javax.inject.Singleton) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
at play.api.db.DBModule.bindings(DBModule.scala:25):
Binding(interface play.api.db.DBApi to ProviderConstructionTarget(class play.api.db.DBApiProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
1 error]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:165) ~[play-server_2.11-2.4.3.jar:2.4.3]
...
Fortunately this error is a little more common, and some quick googling confirmed my hunch - I had a library included multiple times. 幸运的是,这个错误更常见,一些快速的谷歌搜索证实了我的预感 - 我有一个包含多次的库。 Google came up with:
谷歌想出了:
https://groups.google.com/forum/#!topic/play-framework/NOFbfx13fio
The answer by Mirco Dotta suggests that jdbc is being including multiple times, and lo and behold, removing that from my build.sbt resolved the issue: Mirco Dotta的回答表明jdbc正在被多次包含,并且看哪,从我的build.sbt中删除它解决了这个问题:
libraryDependencies ++= Seq(
jdbc, # Remove this
cache,
ws,
specs2 % Test,
"org.postgresql" % "postgresql" % "9.4-1204-jdbc4",
"com.typesafe.play" %% "play-slick" % "1.1.0",
"com.typesafe.play" %% "play-slick-evolutions" % "1.1.0",
"com.typesafe.slick" %% "slick" % "3.1.0",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
Note : jdbc was automatically put in there by activator's project generator, which made it easier to miss. 注意 :jdbc被激活器的项目生成器自动放入其中,这使得它更容易被遗漏。
Note 2 : For anyone for whom this doesn't resolve your issue, the stonecolddev blog post also suggests he had connectivity issues which were resolved by adding the following to his application.conf, in this order: 注意2 :对于没有解决问题的任何人,stonecolddev博客文章还建议他有连接问题,通过在他的application.conf中添加以下内容来解决:
slick.dbs.default.driver="slick.driver.PostgresDriver$"
slick.dbs.default.db.driver="org.postgresql.Driver"
Note 3 : The Hikaricp library does not need to be included, as it is built into play as of version 2.4. 注3 :Hikaricp库不需要包含在内,因为它是从版本2.4开始构建的。 This is why the official docs don't refer to it.
这就是官方文档没有提到它的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.