Skip to content

Commit

Permalink
[playframework#621] Destroy the datasource when needed
Browse files Browse the repository at this point in the history
In PROD mode, the datasource should be destroyed on application stop.
In DEV mode, it should be destroyed before a new one is created.

Also, for JNDI datasources, a new property "db.destroyMethod" is added
to let decide if the application should destroy the datasource or not,
and how (By default, the datasource is not destroyed).
  • Loading branch information
Cyril Bonté committed Mar 29, 2011
1 parent 0173c09 commit a01437a
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
25 changes: 25 additions & 0 deletions framework/src/play/db/DB.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package play.db;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import play.db.jpa.JPA;
import play.exceptions.DatabaseException;
import play.Logger;

/**
* Database connection utilities.
Expand All @@ -17,6 +19,11 @@ public class DB {
*/
public static DataSource datasource = null;

/**
* The method used to destroy the datasource
*/
public static String destroyMethod = "";

/**
* Close the connection opened for the current thread.
*/
Expand Down Expand Up @@ -84,4 +91,22 @@ public static ResultSet executeQuery(String SQL) {
throw new DatabaseException(ex.getMessage(), ex);
}
}

/**
* Destroy the datasource
*/
public static void destroy() {
try {
if (DB.datasource != null && DB.destroyMethod != null && !DB.destroyMethod.equals("")) {
Method close = DB.datasource.getClass().getMethod(DB.destroyMethod, new Class[] {});
if (close != null) {
close.invoke(DB.datasource, new Object[] {});
DB.datasource = null;
Logger.info("Datasource destroyed");
}
}
} catch (Throwable t) {
Logger.error("Couldn't destroy the datasource", t);
}
}
}
22 changes: 22 additions & 0 deletions framework/src/play/db/DBPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public void onApplicationStart() {

Properties p = Play.configuration;

if (DB.datasource != null) {
DB.destroy();
}

if (p.getProperty("db", "").startsWith("java:")) {

Context ctx = new InitialContext();
Expand Down Expand Up @@ -117,6 +121,8 @@ public void onApplicationStart() {

}

DB.destroyMethod = p.getProperty("db.destroyMethod", "");

} catch (Exception e) {
DB.datasource = null;
Logger.error(e, "Cannot connected to the database : %s", e.getMessage());
Expand All @@ -128,6 +134,12 @@ public void onApplicationStart() {
}
}

public void onApplicationStop() {
if (Play.mode.isProd()) {
DB.destroy();
}
}

@Override
public String getStatus() {
StringWriter sw = new StringWriter();
Expand Down Expand Up @@ -192,6 +204,11 @@ private static boolean changed() {
if (DB.datasource == null) {
return true;
}
} else {
// Internal pool is c3p0, we should call the close() method to destroy it.
check(p, "internal pool", "db.destroyMethod");

p.put("db.destroyMethod", "close");
}

Matcher m = new jregex.Pattern("^mysql:(({user}[\\w]+)(:({pwd}[^@]+))?@)?({name}[\\w]+)$").matcher(p.getProperty("db", ""));
Expand Down Expand Up @@ -229,6 +246,11 @@ private static boolean changed() {
return true;
}
}

if (!p.getProperty("db.destroyMethod", "").equals(DB.destroyMethod)) {
return true;
}

return false;
}

Expand Down
5 changes: 5 additions & 0 deletions resources/application-skel/conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ date.format=yyyy-MM-dd
#
# If you want to reuse an existing Datasource from your application server, use:
# db=java:/comp/env/jdbc/myDatasource
#
# When using an existing Datasource, it's sometimes needed to destroy it when
# the application is stopped. Depending on the datasource, you can define a
# generic "destroy" method :
# db.destroyMethod=close

# JPA Configuration (Hibernate)
# ~~~~~
Expand Down

0 comments on commit a01437a

Please sign in to comment.