2016-01-13 4 views
2

Я получаю исключение ThreadPoolException от Slick, используя Play при запуске тестов Spec, это использование Play 2.4.x, Slick 3 , Характеристики 2?Слушать исключение Slick в Specs «Задача slick.backend.DatabaseComponent отклонен из java.util.concurrent.ThreadPoolExecutor»

Мой тест выглядит следующим образом:

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

Когда я запускаю тесты, я получаю следующие ошибки:

[error] ! Add new group 
[error] Task [email protected] rejected from [email protected][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 fails with java.util.concurrent.RejectedExecutionException https://github.com/slick/slick/issues/1183

Однако ни один из них не имеет решений (которые работают по крайней мере) я попытался добавить «последовательный» флаг моей спецификации, но это не делать ничего

ответ

0

Проблема, скорее всего, вызвана тем, что приложение для воспроизведения было создано за каждый набор тестов (спецификация), как описано here. Короче говоря, объекты не воссоздаются, и поэтому dbConfig внутри вашего Groups остается, но является «устаревшим» во время второго теста.

быстрый и грязный обходной путь, чтобы не получить dbConfig раз на начальном этапе, но вновь захватить его для каждой операции:

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

Это, очевидно, не является идеальной точки зрения производительности, но, поскольку операции с базами данных, как правило, дороже во всяком случае, эта стоимость перехвата может нести слишком большой вес.