Play 2.5.10 & HikariCP & initializationFailFast

542 views
Skip to first unread message

Nathan Levin-Greenhaw

unread,
Jan 11, 2017, 3:20:28 PM1/11/17
to Play Framework
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=01-mysql-pc.envnxs.net)(port=3306)(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=01-mysql-pc.envnxs.net)(port=3306)(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.initializationFailFast=false but that didn't seem to help either.

Is this possible? 

Nathan Levin-Greenhaw

unread,
Jan 18, 2017, 6:09:17 PM1/18/17
to Play Framework
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.

Will Sargent

unread,
Jan 19, 2017, 5:32:25 PM1/19/17
to play-fr...@googlegroups.com
Hi Nathan,

Also check out Christopher Hunt's dynamic data source: https://github.com/typesafehub/dynamic-data-source

--
Will Sargent
Engineer, Lightbend, Inc.


--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/8b46435f-97be-4830-8125-44a97bdb9220%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Will Sargent

unread,
Jan 19, 2017, 5:34:04 PM1/19/17
to play-fr...@googlegroups.com
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, Inc.


Nathan Levin-Greenhaw

unread,
Jan 30, 2017, 11:41:36 AM1/30/17
to Play Framework
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
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages