66import io .ebean .datasource .DataSourceInitialiseException ;
77import io .ebean .datasource .DataSourcePool ;
88import io .ebean .datasource .DataSourcePoolListener ;
9+ import io .ebean .datasource .InitDatabase ;
910import io .ebean .datasource .PoolStatistics ;
1011import io .ebean .datasource .PoolStatus ;
1112import org .slf4j .Logger ;
@@ -48,6 +49,8 @@ public class ConnectionPool implements DataSourcePool {
4849 */
4950 private final String name ;
5051
52+ private final DataSourceConfig config ;
53+
5154 /**
5255 * Used to notify of changes to the DataSource status.
5356 */
@@ -189,7 +192,7 @@ public class ConnectionPool implements DataSourcePool {
189192 private long leakTimeMinutes ;
190193
191194 public ConnectionPool (String name , DataSourceConfig params ) {
192-
195+ this . config = params ;
193196 this .name = name ;
194197 this .notify = params .getAlert ();
195198 this .poolListener = params .getListener ();
@@ -290,6 +293,10 @@ private void initialise() throws SQLException {
290293
291294 logger .info (sb .toString ());
292295
296+ if (config .useInitDatabase ()) {
297+ initialiseDatabase ();
298+ }
299+
293300 try {
294301 queue .ensureMinimumConnections ();
295302 } catch (SQLException e ) {
@@ -300,6 +307,27 @@ private void initialise() throws SQLException {
300307 }
301308 }
302309
310+ /**
311+ * Initialise the database using the owner credentials if we can't connect using the normal credentials.
312+ * <p>
313+ * That is, if we think the username doesn't exist in the DB, initialise the DB using the owner credentials.
314+ * </p>
315+ */
316+ private void initialiseDatabase () throws SQLException {
317+ try (Connection connection = createUnpooledConnection (connectionProps , false )) {
318+ // successfully obtained a connection so skip initDatabase
319+ connection .clearWarnings ();
320+ } catch (SQLException e ) {
321+ // expected when user does not exists, obtain a connection using owner credentials
322+ try (Connection connection = createUnpooledConnection (config .getOwnerUsername (), config .getOwnerPassword ())) {
323+ // initialise the DB (typically create the user/role using the owner credentials etc)
324+ InitDatabase initDatabase = config .getInitDatabase ();
325+ initDatabase .run (connection , config );
326+ connection .commit ();
327+ }
328+ }
329+ }
330+
303331 /**
304332 * Returns false.
305333 */
@@ -476,26 +504,33 @@ private void initConnection(Connection conn) throws SQLException {
476504 }
477505
478506 /**
479- * Create a Connection that will not be part of the connection pool.
480- * <p>
481- * <p>
482- * When this connection is closed it will not go back into the pool.
483- * </p>
484- * <p>
485- * <p>
486- * If withDefaults is true then the Connection will have the autoCommit and
487- * transaction isolation set to the defaults for the pool.
488- * </p>
507+ * Create an un-pooled connection with the given username and password.
508+ */
509+ public Connection createUnpooledConnection (String username , String password ) throws SQLException {
510+
511+ Properties properties = new Properties (connectionProps );
512+ properties .setProperty ("user" , username );
513+ properties .setProperty ("password" , password );
514+ return createUnpooledConnection (properties , true );
515+ }
516+
517+ /**
518+ * Create an un-pooled connection.
489519 */
490520 public Connection createUnpooledConnection () throws SQLException {
521+ return createUnpooledConnection (connectionProps , true );
522+ }
491523
524+ private Connection createUnpooledConnection (Properties properties , boolean notifyIsDown ) throws SQLException {
492525 try {
493- Connection conn = DriverManager .getConnection (databaseUrl , connectionProps );
526+ Connection conn = DriverManager .getConnection (databaseUrl , properties );
494527 initConnection (conn );
495528 return conn ;
496529
497530 } catch (SQLException ex ) {
498- notifyDataSourceIsDown (null );
531+ if (notifyIsDown ) {
532+ notifyDataSourceIsDown (null );
533+ }
499534 throw ex ;
500535 }
501536 }
0 commit comments