#2139 new
Tobin Stelling

Play's play.db.DBPlugin.changed() exits prematurely resulting in a ERROR when play exits

Reported by Tobin Stelling | September 27th, 2017 @ 08:30 PM

Framework version: play-1.4.3
Platform you're using: linux

Reproduction steps:
1 Create a new Play! application
2 Edit the application.conf file and create two postgresql database connections. For example

db.default.url=jdbc:postgresql://server:5432/database1
db.default.driver=org.postgresql.Driver
db.default.user=user
db.default.pass=secret

db.other.url=jdbc:postgresql://server:5432/database2
db.other.driver=org.postgresql.Driver
db.other.user=user
db.other.pass=secret

3 Set the application mode to "prod"
4 Start your Play! application
5 Stop your Play! application

Play logs the error:

ERROR ~ Couldn't destroy the datasource

Details:
The changed() function in play.db.DBPlugin loops through each configured database. It performs a variety of checks to see if underlying properties have changed and returns when a change is detected. The function returns from within the loop, so if a change is detected, subsequent databases are not checked. Normally this would be fine (except in the "false" case) but changed() has quite a number of state-changing responsibilities. One in particular has the side-effect of ultimately generating the error above:

if ((datasourceName.startsWith("java:")) && dbConfig.getProperty("db.url") == null) {
   ...
} else {
    // Internal pool is c3p0, we should call the close() method to destroy it.
   check(dbConfig, "internal pool", "db.destroyMethod");

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

The code calls dbConfig.put() to set the destroyMethod. This in turn modifies Play.configuration:

public Object put(String key, String value) {
    if (key != null) {
        return Play.configuration.put(generateKey(key), value);
    }
    return null;
}

Because DBPlugin.changed() returns on the first iteration of the loop (in my sample app, it returned at line 351, where it checks if ds==null), your second database will never receive a destroyMethod, which in turn logs an error when play exits and tries to destroy the datasource. You can work around this by specifying a destroyMethod manually in your application.conf file but this seems wrong, as the code intentionally checks for and logs a warning if destroyMethod is set:

WARN  ~ Ignoring db.destroyMethod because running the in internal pool db.

For the moment I am setting a destroyMethod in application.conf for only the second database which silences both the warning on start up and the error on exit.

No comments found

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2>Play framework</h2>

Play makes it easier to build Web applications with Java. It is a clean alternative to bloated Enterprise Java stacks. It focuses on developer productivity and targets RESTful architectures. Learn more on the <a href="http://www.playframework.org">http://www.playframework.org</a> website.<br><br>

<h2>Source code is hosted on github</h2>Check out our repository at <a href="http://github.com/playframework/play">http://github.com/playframework/play</a><br><br>

<h2>Contributing, creating a patch</h2> Please read the <a href="http://play.lighthouseapp.com/projects/57987/contributor-guide">contributor guide</a><br><br>

<h2>Reporting Security Vulnerabilities</h2> Since all bug reports are public, please report any security vulnerability directly to <em>guillaume dot bort at gmail dot com</em>.<br><br>

<h2>Creating a bug report</h2> Bug reports are incredibly helpful, so take time to report bugs and request features in our ticket tracker. We’re always grateful for patches to Play’s code. Indeed, bug reports with attached patches will get fixed far quickly than those without any.<br><br>

Please include as much relevant information as possible including the exact framework version you're using and a code snippet that reproduces the problem.<br><br>

Don't have too much expectations. Unless the bug is really a serious "everything is broken" thing, you're creating a ticket to start a discussion. Having a patch (or a branch on Github we can pull from) is better, but then again we'll only pull high quality branches that make sense to be in the core of Play.

Pages