I have a Play 2.5.10 application with multiple data sources. I would like 
to start the application even if one of the data sources is not available.
HikariCP supports this, but Play does not seem to allow this as it will not
start unless it can get a successful connection to all data sources.
I see that someone filed a bug for this exact thing on Github
(https://github.com/playframework/playframework/issues/6706). The issue was
closed because the developers like this behavior, but some of the comments
seem to imply that it could work. Is that in fact true? I cannot seem to
find any way to configure the app in any way to allow it to start without a
connection.
*applicaiton.conf*
db {
api {
driver: org.mariadb.jdbc.Driver
url: "jdbc:mysql://01-mysql-pc.envnxs.net/api"
username: "mysql"
password: ""
initializationFailFast: false
hikaricp: {
initializationFailFast: false
}
}
report: {
driver: org.mariadb.jdbc.Driver
url: "jdbc:mysql://01-report-pc.envnxs.net/report"
username: "mysql"
password: ""
}
fast_report: {
driver: org.mariadb.jdbc.Driver
url: "jdbc:mysql://01-fast-report-pc.envnxs.net/report"
username: "mysql"
password: ""
}
destination {
driver: org.mariadb.jdbc.Driver
url: "jdbc:mysql://localhost/special"
username: ""
password: ""
}
}
*Output*
[info] application - Creating Pool for datasource 'destination'
[info] p.a.d.DefaultDBApi - Database [destination] connected at
jdbc:mysql://localhost:3306/special
[info] application - Creating Pool for datasource 'report'
[info] p.a.d.DefaultDBApi - Database [report] connected at
jdbc:mysql://01-report-pc.envnxs.net/report
[info] application - Creating Pool for datasource 'fast_report'
[info] p.a.d.DefaultDBApi - Database [fast_report] connected at
jdbc:mysql://01-fast-report-pc.envnxs.net/report
[info] application - Creating Pool for datasource 'api'
[info] application - Creating Pool for datasource 'destination'
[info] p.a.d.DefaultDBApi - Database [destination] connected at
jdbc:mysql://localhost:3306/special
[info] application - Creating Pool for datasource 'report'
[info] p.a.d.DefaultDBApi - Database [report] connected at
jdbc:mysql://01-report-pc.envnxs.net/report
[info] application - Creating Pool for datasource 'fast_report'
[info] p.a.d.DefaultDBApi - Database [fast_report] connected at
jdbc:mysql://01-fast-report-pc.envnxs.net/report
[info] application - Creating Pool for datasource 'api'
[info] application - Creating Pool for datasource 'destination'
[info] p.a.d.DefaultDBApi - Database [destination] connected at
jdbc:mysql://localhost:3306/special
[info] application - Creating Pool for datasource 'report'
[info] application - Creating Pool for datasource 'destination'
[info] p.a.d.DefaultDBApi - Database [destination] connected at
jdbc:mysql://localhost:3306/special
[info] application - Creating Pool for datasource 'report'
Oops, cannot start the server.
Configuration error: Configuration error[Cannot connect to database [api]]
at play.api.Configuration$.configError(Configuration.scala:154)
at play.api.Configuration.reportError(Configuration.scala:806)
at
play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:48)
at
play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:42)
at scala.collection.immutable.List.foreach(List.scala:381)
at play.api.db.DefaultDBApi.connect(DefaultDBApi.scala:42)
at play.api.db.DBApiProvider.get$lzycompute(DBModule.scala:72)
at play.api.db.DBApiProvider.get(DBModule.scala:62)
at play.api.db.DBApiProvider.get(DBModule.scala:58)
at
com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
at
com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72)
at
com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)
at
com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62)
at
com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54)
at
com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
at
com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:93)
at
com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:80)
at
com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
at
com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:80)
at
com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:62)
at
com.google.inject.internal.InjectorImpl.injectMembers(InjectorImpl.java:984)
at
com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
at
com.google.inject.util.Providers$GuicifiedProviderWithDependencies$$FastClassByGuice$$2a7177aa.invoke(<generated>)
at
com.google.inject.internal.cglib.reflect.$FastMethod.invoke(FastMethod.java:53)
at
com.google.inject.internal.SingleMethodInjector$1.invoke(SingleMethodInjector.java:57)
at
com.google.inject.internal.SingleMethodInjector.inject(SingleMethodInjector.java:91)
at
com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
at
com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:93)
at
com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:80)
at
com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
at
com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:80)
at
com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:174)
at
com.google.inject.internal.Initializer.injectAll(Initializer.java:108)
at
com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:174)
at
com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:84)
at
play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
at
play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
at
play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.ProdServerStart$.start(ProdServerStart.scala:47)
at play.core.server.ProdServerStart$.main(ProdServerStart.scala:22)
at play.core.server.ProdServerStart.main(ProdServerStart.scala)
Caused by: java.sql.SQLTransientConnectionException: HikariPool-4 -
Connection is not available, request timed out after 30003ms.
at
com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
at
com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
at play.api.db.DefaultDatabase.getConnection(Databases.scala:142)
at play.api.db.DefaultDatabase.getConnection(Databases.scala:138)
at
play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:44)
... 40 more
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect
to address=(host-mysql-pc.envnxs.net)(port306)(type=master) :
01-mysql-pc.envnxs.net
at
org.mariadb.jdbc.internal.SQLExceptionMapper.get(SQLExceptionMapper.java:136)
at
org.mariadb.jdbc.internal.SQLExceptionMapper.throwException(SQLExceptionMapper.java:106)
at org.mariadb.jdbc.Driver.connect(Driver.java:107)
at
com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
at
com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
at
com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
at
com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
at
com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.mariadb.jdbc.internal.common.QueryException: Could not
connect to address=(host-mysql-pc.envnxs.net)(port306)(type=master) :
01-mysql-pc.envnxs.net
at
org.mariadb.jdbc.internal.mysql.MySQLProtocol.connectWithoutProxy(MySQLProtocol.java:631)
at org.mariadb.jdbc.internal.common.Utils.retrieveProxy(Utils.java:541)
at org.mariadb.jdbc.Driver.connect(Driver.java:102)
... 12 more
Caused by: java.net.UnknownHostException: 01-mysql-pc.envnxs.net
at
java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at
org.mariadb.jdbc.internal.mysql.MySQLProtocol.connect(MySQLProtocol.java:289)
at
org.mariadb.jdbc.internal.mysql.MySQLProtocol.connectWithoutProxy(MySQLProtocol.java:626)
... 14 more
I also tried setting play.db.prototype.hikaricp.initializationFailFastlse
but that didn't seem to help either.
Is this possible?
Nathan Levin-Greenhaw 's gravatar image asked Jan 11 2017 at 12:07 in Play-Framework by Nathan Levin-Greenhaw

4 Answers

Apparently, Play's DB module iterates through the connections defined in
the application.conf during start up and if it cannot get a connection to
any of them it throws an exception.
To work around this I created a new project that can be used to start a
Play application without needing a connection at start up time.
See https://github.com/njlg/playdb.
Nathan Levin-Greenhaw 's gravatar image answered Jan 18 2017 at 15:09 by Nathan Levin-Greenhaw
Hi Nathan,
Also check out Christopher Hunt's dynamic data source:
https://github.com/typesafehub/dynamic-data-source
Will Sargent
*Engineer, Lightbend,
Will Sargent 's gravatar image answered Jan 19 2017 at 14:31 by Will Sargent
Hi Nathan,
It looks like you've really thought this through. Would you consider
contributing this code to Play itself as a pull request?
Will Sargent
*Engineer, Lightbend,
Will Sargent 's gravatar image answered Jan 19 2017 at 14:33 by Will Sargent
Will,
Thanks for the response. Let me look into dynamic data source, because that
sounds similar.
I'd be happy to submit a PR for Play in next couple days.
Nathan
Nathan Levin-Greenhaw 's gravatar image answered Jan 30 2017 at 08:41 by Nathan Levin-Greenhaw