Upgrade ReactiveMongo Play 2.3 app from 2.6 to 3.0 - scala

I had a perfectly good working Scala Play 2.3 app using ReactiveMongo running on Heroku against a MongoLab 2.6 database, now that MongoLab have updated their sandbox databases to 3.0 I can not get my app to start up.
I have updated my local database to 3.0.
I have followed the instructions on http://reactivemongo.org/releases/0.11/documentation/tutorial/play2.html for 2.3, but I still get a stacktrace as follows:
--- (Running the application from SBT, auto-reloading is enabled) ---
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
(Server started, use Ctrl+D to stop and go back to the console...)
[info] application - ReactiveMongoPlugin starting... [info]
application - ReactiveMongoPlugin successfully started with db
'sites'! Servers:
[localhost:27017] [info] play - Application started (Dev) [ERROR] [10/02/2015 11:34:11.472]
[play-akka.actor.default-dispatcher-7] [ActorSystem(play)] Uncaught
error from thread [play-akka.actor.default-dispatcher-7] shutting down
JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.AbstractMethodError
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
at akka.actor.ActorCell.invoke(ActorCell.scala:487)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
[ERROR] [10/02/2015 11:34:11.473]
[play-akka.actor.default-dispatcher-8] [ActorSystem(play)] Uncaught
error from thread [play-akka.actor.default-dispatcher-8] shutting down
JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.AbstractMethodError Uncaught error from thread
[play-akka.actor.default-dispatcher-7] shutting down JVM since
'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[play]
java.lang.AbstractMethodError
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
at akka.actor.ActorCell.invoke(ActorCell.scala:487)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at akka.actor.ActorCell.create(ActorCell.scala:580)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:456)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
I've updated my references from ...default.BSONCollection to ...bson.BSONCollection etc.
I'm using the following config:
mongodb.uri = "mongodb://localhost:27017/sites"
mongo-async-driver {
akka {
loglevel = WARNING
}
}
My app dependency is:
"org.reactivemongo" %% "play2-reactivemongo" % "0.11.7.play23")
Please can someone advise on what the above stacktrace actually means as I can't figure that out?

Not entirely sure whats going on in your stacktrace but it looks like that setting akka.jvm-exit-on-fatal-error is just causing your app to crash rather than output what is causing the crash
Reading through the docs you might be able to disable it by doing something like this:
jvm-exit-on-fatal-error = off
In your akka config. Then you might get some more detailed stacktrace
http://doc.akka.io/docs/akka/snapshot/general/configuration.html
However I was also getting a fatal error after the Mongo 3.0 upgrade on MongoLab. My Error was this:
DatabaseException['not authorized for query on auth-test.user' (code = 13)]
Caused by 3.0 using a different authentication then 2.6
mongo 2.6 uses MONGODB-CR auth protocol and 3.0 uses MONGODB-SHA-1 by
default
To solve I changed my MongoURI to include authMode like this:
mongodb.uri = "mongodb://user:password#ds049621.mongolab.com:49431/DBName?authMode=scram-sha1"

Related

Akka Http Error: InvalidContentLengthException

We have an Akka HTTP Server serving some scala JS content on AWS. We've noticed that after some time, the server starts throwing the error below in the logs and although, the certain URL's work, but some files fail to be downloaded correctly with the Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH error in the browser. The server logs looks like below (it's exactly the same error in all instances):
[ERROR] [09/29/2016 21:29:22.150] [designer-actor-system-akka.actor.default-dispatcher-56831] [akka.actor.ActorSystemImpl(designer-actor-system)] Outgoing response stream error
akka.http.scaladsl.model.InvalidContentLengthException: HTTP message had declared Content-Length 997 but entity data stream amounts to 164 bytes less
at akka.http.scaladsl.model.InvalidContentLengthException$.apply(ErrorInfo.scala:50)
at akka.http.impl.engine.rendering.RenderSupport$CheckContentLengthTransformer$$anon$2.onUpstreamFinish(RenderSupport.scala:130)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:732)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:616)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:471)
at akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:433)
at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:603)
at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:618)
at akka.actor.Actor$class.aroundReceive(Actor.scala:484)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:529)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
at akka.actor.ActorCell.invoke(ActorCell.scala:495)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
at akka.dispatch.Mailbox.run(Mailbox.scala:224)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
We are running Akka version 2.4.7 and OpenJDK version 1.8.0_101-b13.The error goes away if we restart the Akka HTTP server, but comes back again after a few hours.
Not sure what is causing the issue. Any help would be greatly appreciated.
I think I figured out what was causing it. We had an automated deployment process that deploys HTML/CSS/Javascript files to the Akka server. It seems like the Akka server caches content size and if the static files are updated without restarting, it would give InvalidContentLengthException. We included the restart as part of deployment process and the problem seems to have been resolved.

What happens during Play! controller instantiation?

I experience strange behavior within controllers in Play framework. I am using elastic4s to connect to an Elasticsearch cluster, and depending precise timing of establishing the connection it either works or it doesn't. My minimal-so-far example looks like this:
class EsController extends Controller {
def buildClient() = ElasticClient.transport(Settings.builder
.put("cluster.name", "es").build,
"127.0.0.1:9300")
val eagerClient = buildClient()
lazy val lazyClient = buildClient()
object ElasticConnection extends ElasticDsl {
def eagerStats = eagerClient.execute(get cluster stats)
def lazyStats = lazyClient.execute(get cluster stats)
}
// accessible via GET /eagerStats
def eagerStats = Action.async {
ElasticConnection.eagerStats map (s => Ok(s.toString))
}
// accessible via GET /lazyStats
def lazyStats = Action.async {
ElasticConnection.lazyStats map (s => Ok(s.toString))
}
}
I start the app via sbt run. Then I can try getting the two endpoints. curl localhost:9000/lazyStats/ works fine, talks to my ES node and returns proper stats. curl localhost:9000/eagerStats/ throws an exception from ES transport layer (stack trace at the end). Since my code is identical in both cases (the only difference being val vs lazy val) I suppose the constructor is instantiated in a weird fashion. Can anyone confirm or deny that?
As a sidenote, I could create a separate class that handles the ES connection and #Inject it (probably making it also a #Singleton) - and that would probably be the preferred solution. I find the described behavior weird, though, and I'd be glad to see an explanation.
The elastic4s is a small wrapper around the official ES Java driver, and I'm quite confident there is no magic happening there in this scenario.
UPDATE:
I'm running a single-node ES cluster on the same machine as a standalone process. It's configured properly, it even has a kopf plugin up and running. REST interface works fine; transport interface works too, provided that I use the lazily initalized connection.
I'm using ES 2.2.0 (both client- and server-side), Play 2.4.6, scala 2.11.7 and SBT 0.13.8.
The stack trace from the eager connection:
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{127.0.0.1}{127.0.0.1:9300}]]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:265) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:191) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:179) [play_2.11-2.4.6.jar:2.4.6]
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:212) [play_2.11-2.4.6.jar:2.4.6]
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:94) [play_2.11-2.4.6.jar:2.4.6]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:151) [play-netty-server_2.11-2.4.6.jar:2.4.6]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:148) [play-netty-server_2.11-2.4.6.jar:2.4.6]
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.7.jar:na]
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:216) [scala-library-2.11.7.jar:na]
at scala.util.Try$.apply(Try.scala:192) [scala-library-2.11.7.jar:na]
at scala.util.Failure.recover(Try.scala:216) [scala-library-2.11.7.jar:na]
at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.7.jar:na]
at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [scala-library-2.11.7.jar:na]
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) [scala-library-2.11.7.jar:na]
at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109) [play-iteratees_2.11-2.4.6.jar:2.4.6]
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71) [play-iteratees_2.11-2.4.6.jar:2.4.6]
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) [scala-library-2.11.7.jar:na]
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) [scala-library-2.11.7.jar:na]
at scala.concurrent.Promise$class.complete(Promise.scala:55) [scala-library-2.11.7.jar:na]
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) [scala-library-2.11.7.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23) [scala-library-2.11.7.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.7.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.11.7.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.7.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.7.jar:na]
Caused by: org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{127.0.0.1}{127.0.0.1:9300}]
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:290) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:207) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.client.transport.support.TransportProxyClient.execute(TransportProxyClient.java:55) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:286) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:351) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.client.support.AbstractClient$ClusterAdmin.execute(AbstractClient.java:845) ~[elasticsearch-2.2.0.jar:2.2.0]
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:85) ~[elasticsearch-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.admin.ClusterDsl$ClusterStatsExecutable$$anonfun$apply$2.apply(ClusterDsl.scala:24) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.admin.ClusterDsl$ClusterStatsExecutable$$anonfun$apply$2.apply(ClusterDsl.scala:24) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.Executable$class.injectFuture(Executable.scala:30) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.admin.ClusterDsl$ClusterStatsExecutable$.injectFuture(ClusterDsl.scala:21) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.admin.ClusterDsl$ClusterStatsExecutable$.apply(ClusterDsl.scala:24) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.admin.ClusterDsl$ClusterStatsExecutable$.apply(ClusterDsl.scala:21) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at com.sksamuel.elastic4s.ElasticClient.execute(ElasticClient.scala:20) ~[elastic4s-core_2.11-2.2.0.jar:2.2.0]
at controllers.BookController$ElasticConnection$.eagerStats(BookController.scala:35) ~[classes/:na]
at controllers.BookController$$anonfun$eagerStats$1.apply(BookController.scala:41) ~[classes/:na]
at controllers.BookController$$anonfun$eagerStats$1.apply(BookController.scala:41) ~[classes/:na]
at play.api.mvc.ActionBuilder$$anonfun$async$1.apply(Action.scala:456) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.ActionBuilder$$anonfun$async$1.apply(Action.scala:456) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$.invokeBlock(Action.scala:533) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$.invokeBlock(Action.scala:530) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.11-2.4.6.jar:2.4.6]
at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103) ~[play_2.11-2.4.6.jar:2.4.6]
at scala.Option.map(Option.scala:146) ~[scala-library-2.11.7.jar:na]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96) ~[play_2.11-2.4.6.jar:2.4.6]
at play.api.libs.iteratee.DoneIteratee$$anonfun$mapM$2.apply(Iteratee.scala:741) ~[play-iteratees_2.11-2.4.6.jar:2.4.6]
at play.api.libs.iteratee.DoneIteratee$$anonfun$mapM$2.apply(Iteratee.scala:741) ~[play-iteratees_2.11-2.4.6.jar:2.4.6]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [scala-library-2.11.7.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [scala-library-2.11.7.jar:na]
... 6 common frames omitted
It turned out to be a weird race condition, so you might as well stop reading now.
Here is my hypothesis on what happens:
The race condition is caused by the way ES java driver handles connections,
and has nothing to do with Play or elastic4s.
ElasticClient.transport(...) does not block until connection is established; it only initializes the driver with given settings. This causes the driver to try and connect to ES cluster, but the connection attempt is asynchronous under the hood. If the driver manages to establish connection before any API calls are requested, everything works. If, on the other hand, any API call is made right after driver initialization and there is no connection yet, the API call fails with this exact exception. In usual conditions, this all happens very fast and causes no trouble. I suspect that running from interactive sbt session adds complexity because of Play autoreloading - memory is limited (part consumed by SBT itself), and JVM is under heavy load, because the compilation, Play bootstrap and ES connection init are all happening on request.

Strange exception in SBT test

I am facing an issue with SBT (version 0.13.9). One of my ScalaTest tests fails not deterministic with EOFException.
Stack trace:
Exception in thread "Thread-155" Exception in thread "Thread-159" java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2601)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at sbt.React.react(ForkTests.scala:114)
at sbt.ForkTests$$anonfun$mainTestTask$1$Acceptor$2$.run(ForkTests.scala:74)
at java.lang.Thread.run(Thread.java:745)
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2601)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at org.scalatest.tools.Framework$ScalaTestRunner$Skeleton$1$React.react(Framework.scala:953)
at org.scalatest.tools.Framework$ScalaTestRunner$Skeleton$1.run(Framework.scala:942)
at java.lang.Thread.run(Thread.java:745)
sbt.ForkMain 59974 failed with exit code 134
I don't see any JVM logs or thread dumps.
Almost certainly this is related to the Java classpath being too long when invoking sbt.ForkMain in certain linux distros. To avoid this I added
javaOptions in Test ++= Seq("-Xms1G","-XX:+CMSClassUnloadingEnabled","-XX:+UseConcMarkSweepGC")
to the build.sbt file. I reckon CMSClassUnloadingEnabled is where the magic happens.
SBT single thread or multi threaded tests forks the JVM and if the host name is not resolved it just fails with this error message. If you look at the logs in the tests, you might see
Uncaught exception when running tests: java.net.ConnectException: Operation timed out
So the easy way to resolve this is to add your hostname to the /etc/hosts and map it to localhost something like this
::1 localhost blahblah
This should resolve the issue.

Logger log1-Slf4jLogger did not respond within Timeout(5000 milliseconds) to InitializeLogger(bus)

I am running an Akka application under Akka Kernel and the program works fine in other systems.
akka {
loggers = ["akka.event.slf4j.Slf4jLogger"]
loglevel = INFO
}
Which is the correct slf4jLogger configuration. However when I run my application it gives the following stack trace and fails to start.
[WARN] [01/12/2015 15:35:01.953] [main]
[EventStream(akka://ARCWorker)] Logger log1-Slf4jLogger did not
respond within Timeout(5000 milliseconds) to InitializeLogger(bus)
error while starting up loggers akka.ConfigurationException: Logger
specified in config can't be loaded [akka.event.slf4j.Slf4jLogger] due
to [akka.event.Logging$LoggerInitializationException: Logger
log1-Slf4jLogger did not respond with LoggerInitialized, sent instead
[TIMEOUT]] at
akka.event.LoggingBus$$anonfun$4$$anonfun$apply$1.applyOrElse(Logging.scala:116)
There is more to the stack trace which I can paste on demand.
Has anyone seen this error and how to get rid of this?
Thanks
Manas
You have to increase the timeout timer in your application.conf
akka.logger-startup-timeout = 30s
this solved the problem for me.

Slick and bonecp: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already error

Locally when I am developing my application I launch my play2 application using sbt run
I love how I can make code changes, and then reload my browser to see my changes.
After about roughly 10 code changes or so, I get a postgresql too many connection error (see below).
My db connection is using the below DatabaseAccess.scala class.
I'm guessing on each reload it is creating a bunch of connections to postgresql. In my Global am currently doing:
override def onStart(app: Application) {
Logger.info("Global.onStart")
DatabaseAccess.loadConfiguration()
}
In production I am also worried that if I make multiple deploys in a short period of time, or start/stop my service I might run into this problem also.
How can I ensure all connections are destroyed? I know I can either put something in the onStart or OnStop but I'm not really sure how to clear the connections that might have existed previously. (assuming this isn't a bug)
I did create a release() method that I was calling on onStop but that didn't seem to work:
def release() {
configs = Map[String, BoneCPConfig]()
dataSources = Map[String, BoneCPDataSource]()
databases = dataSources.map { case(key, value) => (key, Database.forDataSource(value)) }
}
All I did was re-init the vars so I guess that wasn't really what I needed to do.
My data access pattern is as follows:
def getById(userId: Int): Option[User] = {
db.withSession { implicit session =>
return userDao.getById(userId)
}
}
My database access class looks like:
https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/unfiltered/src/main/scala/DatabaseAccess.scala
My application.conf connection looks like:
#postgresql
db.default.driver="org.postgresql.Driver"
db.default.url = "jdbc:postgresql://localhost/testweb_development"
db.default.user = "testdbuser"
db.default.password = ""
db.default.minConnections = 4
db.default.maxConnections = 24
db.default.maxThreads = 2
Locally when developing after about approximately 10 code changes and sbt doing it's nice partial class reloads I get this error:
play.api.Application$$anon$1: Execution exception[[SQLException: Unable to open a test connection to the given database. JDBC url = jdbc:postgresql://localhost/testweb_development, username = testdbuser. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------
org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:291)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:108)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125)
at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)
at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22)
at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:30)
at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
at org.postgresql.Driver.makeConnection(Driver.java:393)
at org.postgresql.Driver.connect(Driver.java:267)
at java.sql.DriverManager.getConnection(DriverManager.java:582)
at java.sql.DriverManager.getConnection(DriverManager.java:185)
at com.jolbox.bonecp.BoneCP.obtainRawInternalConnection(BoneCP.java:363)
at com.jolbox.bonecp.BoneCP.<init>(BoneCP.java:416)
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:120)
at scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.createConnection(JdbcBackend.scala:47)
at scala.slick.jdbc.JdbcBackend$BaseSession.conn$lzycompute(JdbcBackend.scala:302)
at scala.slick.jdbc.JdbcBackend$BaseSession.conn(JdbcBackend.scala:302)
at scala.slick.jdbc.JdbcBackend$BaseSession.close(JdbcBackend.scala:316)
at scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:31)
at scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.withSession(JdbcBackend.scala:46)
at com.exampleapp.services.UserServiceImpl.getById(UserService.scala:37)
at controllers.UsersController$$anonfun$show$1.apply(UsersController.scala:84)
at controllers.UsersController$$anonfun$show$1.apply(UsersController.scala:76)
at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:221)
at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:220)
at controllers.ActionWithContext$.invokeBlock(BaseController.scala:42)
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:309)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109)
at play.utils.Threads$.withContextClassLoader(Threads.scala:18)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:108)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:107)
at scala.Option.map(Option.scala:145)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:107)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:100)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Environment
I am running scala 2.10.3, play 2.2.3
I am launching my app using sbt run.
Postgresql driver version: 9.1-901.jdbc4
slick version: 2.0.1
bonecp version: 0.8.0.RELEASE
Slick handles session closing automatically. From the documentation:
The Database object’s withSession method creates a Session, passes it to a given function and closes it afterwards. If you use a connection pool, closing the Session returns the connection to the pool.
The problem is the Bonecp's dataSource connections which are not closed, as showed on this gist you need to close them manually using dataSource.close().