Reputation: 1071
Slick defines here how to connect to a database using JNDI:
val db = Database.forName(jndiName: String)
I use the above to connect to a database in Play for Scala, defining the JNDI connection in application.conf
:
def read (jndi: String, code: Int) = {
val db = Database.forName(jndi)
val records = TableQuery[TableDB]
val action = records.filter(_.code === code).result
val future = db.run(action.asTry)
future.map{
case Success(s) =>
if (s.length>0)
Some(s(0))
else
None
case Failure(e) => throw new Exception ("Failure in read: " + e.getMessage)
}
}
Question is: how to disconnect from the JNDI resource? Simply db.close()
? Is there a way to implicitly close the connection when the read
method ends?
Upvotes: 0
Views: 234
Reputation: 737
You can always use play's shutdown hooks to close the db connection when you app shuts down (which is usually what you would want) and yes db.close is enough to stop the connection, your port will be freed which is all you should care about. I'm not quite sure why you would want the db to close right after the method, but there's a very easy fix to this without polluting the code, you simply inject your database into the method :
def read(db : Database, code: Int) = {
val records = TableQuery[TableDB]
val action = records.filter(_.code === code).result
val future = db.run(action.asTry)
future.map {
case Success(s) =>
if (s.length > 0)
Some(s(0))
else
None
case Failure(e) => throw new Exception("Failure in read: " + e.getMessage)
}
And the caller of this method can close the respective database once you have the results you want. Much safer and easier to change :) On the other hand, you can always go with @SergGr's solution, it also works :)
Upvotes: 1
Reputation: 23788
It is not clear what make you doubt it. If you look at the source of forName
, you may see that it just asks JNDI context to get object by the name you provided and then treat it as javax.sql.DataSource
that can create connections. DataSource
is not Closeable
or anything like this so you don't have to explicitly release it. It is enough to just close the db
.
As for closing when the read
method ends, this is probably not what you really want because you return Future
that might still be not finished and thus might need the connection to be open. So what you probably need is Future.onComplete
def read(jndi: String, code: Int) = {
val records = TableQuery[TableDB]
val action = records.filter(_.code === code).result
val db = Database.forName(jndi)
val future = db.run(action.asTry)
future.onComplete(_ => db.close()) // <-- added line
future.map {
case Success(s) =>
if (s.length > 0)
Some(s(0))
else
None
case Failure(e) => throw new Exception("Failure in read: " + e.getMessage)
}
}
Upvotes: 1