在规范“从java.util.concurrent.ThreadPoolExecutor拒绝的任务slick.backend.DatabaseComponent"中播放Slick异常. [英] Play Slick exception in Specs "Task slick.backend.DatabaseComponent rejected from java.util.concurrent.ThreadPoolExecutor"
问题描述
我在运行Spec测试时使用Play从Slick获取ThreadPoolException,这是使用Play 2.4.x,Slick 3,Specs 2吗?
I am getting a ThreadPoolException from Slick using Play when running my Spec tests, This is using Play 2.4.x, Slick 3, Specs 2?
我的测试如下:
val jsonHeaders = FakeHeaders(Seq((CONTENT_TYPE, MimeTypes.JSON)))
def fakeApp: FakeApplication = FakeApplication(additionalConfiguration = Map(
"slick.dbs.default.driver" -> "slick.driver.H2Driver$",
"slick.dbs.default.db.driver" -> "org.h2.Driver",
"slick.dbs.default.db.url" -> "jdbc:h2:mem:test;MODE=PostgreSQL;DATABASE_TO_UPPER=FALSE"
))
"Add new group" in new WithApplication(FakeApp.fakeApp){
val vg = new ViewGroup(0, "Test", "Tests")
val add = route(FakeRequest(POST, "/api/new-group", jsonHeaders, vg.toJson())).get
status(add) must equalTo(OK)
contentType(add) must beSome.which(_ == MimeTypes.JSON)
}
哪个叫端点:
def newGroup = AuthenticatedAction(authType).async(parse.json) { request =>
request.body.validate[ViewGroup].fold(
errors => {
Future { BadRequest(JsError.toJson(errors)) }
}, viewGroup => {
Groups.add(new Group(viewGroup.Name, viewGroup.Description)).map( i => Ok(i.toString) )
}
)
}
依次调用DAO:
object Groups {
val groups = TableQuery[GroupTableDef]
val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
def add(group: Group): Future[Int] = {
dbConfig.db.run(groups += group)
}
}
运行测试时,出现以下错误:
When I run the tests, I get the following errors:
[error] ! Add new group
[error] Task slick.backend.DatabaseComponent$DatabaseDef$$anon$2@10277fb0 rejected from java.util.concurrent.ThreadPoolExecutor@794e3935[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 9] (DatabaseComponent.scala:230)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runSynchronousDatabaseAction(DatabaseComponent.scala:230)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runSynchronousDatabaseAction(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runInContext(DatabaseComponent.scala:207)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runInContext(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runInternal(DatabaseComponent.scala:75)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runInternal(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.run(DatabaseComponent.scala:72)
[error] slick.jdbc.JdbcBackend$DatabaseDef.run(JdbcBackend.scala:38)
[error] database.Groups$.add(Group.scala:33)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1$$anonfun$apply$13.apply(AuthenticationAPIv1.scala:74)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1$$anonfun$apply$13.apply(AuthenticationAPIv1.scala:73)
[error] play.api.libs.json.JsResult$class.fold(JsResult.scala:72)
[error] play.api.libs.json.JsSuccess.fold(JsResult.scala:9)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1.apply(AuthenticationAPIv1.scala:70)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1.apply(AuthenticationAPIv1.scala:69)
[error] auth.scala.AuthenticatedActionBuilder$$anon$1.invokeBlock(AuthenticatedActionBuilder.scala:23)
[error] auth.scala.AuthenticatedActionBuilder$$anon$1.invokeBlock(AuthenticatedActionBuilder.scala:19)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
[error] play.utils.Threads$.withContextClassLoader(Threads.scala:21)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103)
[error] play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103)
[error] play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96)
[error] play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
[error] play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537)
[error] akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
[error] akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
这可能与以下方面有关: Slick 3.0-RC3因java.util.concurrent而失败. RejectedExecutionException https://github.com/slick/slick/issues/1183
This may be related to: Slick 3.0-RC3 fails with java.util.concurrent.RejectedExecutionException https://github.com/slick/slick/issues/1183
但是这些都没有解决方案(至少有效) 我曾尝试在规格中添加顺序"标志,但这没做任何事情
However none of these have any solutions (that work at least) I have tried adding the "sequential" flag to my specs but that didn't do anything
推荐答案
问题可能是由于为每个测试套件(规格)重新创建了Play应用所引起的,如
The problem is likely caused by the play app being re-created for every test suite (spec), as described here. In short, objects don't get re-created, and thus dbConfig
inside your Groups
remains, but is "stale" during the second test.
一种快速而肮脏的解决方法是最初不获取一次dbConfig
,而是为每个操作重新获取它:
A quick and dirty workaround is to not get dbConfig
once initially, but re-grab it for every operation:
object Groups {
val groups = TableQuery[GroupTableDef]
// note this is a function now
def dbConfig() = DatabaseConfigProvider.get[JdbcProfile](Play.current)
def add(group: Group): Future[Int] = {
dbConfig().db.run(groups += group)
}
}
这显然不是理想的性能,但是由于数据库操作无论如何往往很昂贵,因此重新夺回成本可能不会带来太大的负担.
This is obviously not ideal performance-wise, but since database operations tend to be expensive anyway, this re-grabbing cost might not carry too much weight.
这篇关于在规范“从java.util.concurrent.ThreadPoolExecutor拒绝的任务slick.backend.DatabaseComponent"中播放Slick异常.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!