I am using play-slick with slick evolutions to create my db.
I have the following config
slick.dbs.default.profile="slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
This works fine when I want to use slick itself to operate on the db. However, I want to access the underlying javax.sql.Datasource instance (which I need to pass in to another library, namely pac4js DbProfileService).
I tried to add a config for the db name as dbName="play", and then add
@Provides
def dbProfileService(dbApi: DBApi): DbProfileService = {
new DbProfileService(dbApi.database(configuration.get[String]("dbName")).dataSource)
}
however, it seems that the injection happens before the evolution script has a chance to run, which causes an exception saying that the play database isn't able to be found.
Is there a better approach for this problem?
Here is the stack trace
aused by: java.lang.IllegalArgumentException: Could not find database for play
at play.api.db.slick.evolutions.internal.DBApiAdapter.$anonfun$database$1(DBApiAdapter.scala:32)
at scala.collection.immutable.Map$Map1.getOrElse(Map.scala:248)
at play.api.db.slick.evolutions.internal.DBApiAdapter.database(DBApiAdapter.scala:32)
at modules.SecurityModule.dbProfileService(SecurityModule.scala:53)
at modules.SecurityModule$$FastClassByGuice$$153731.GUICE$TRAMPOLINE(<generated>)
at modules.SecurityModule$$FastClassByGuice$$153731.apply(<generated>)
at com.google.inject.internal.ProviderMethod$FastClassProviderMethod.doProvision(ProviderMethod.java:260)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:40)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:60)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:40)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:60)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:50)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:146)
at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:101)
at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:245)
at com.google.inject.internal.Initializer.injectAll(Initializer.java:140)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180)
I also added a breakpoint, and sure enough, there was only the default db there, not the play db as I would expect.
The problem is with the value of the key
dbName. When you are doingYou are looking up for the value of the key named
dbNamethat is in your config files. In the provided example, the value isplay. Now, looking at the complete line you have thisYou are calling the
databasemethod fromDBApi. There are two classes that are mixing this trait. One is DBApiAdapter fromplay-slick-evolutionsand the other one is DefaultDBApi fromplay-jdbc. I think in your case is using the one that belongs to the evolution module. If you look at the implementaiton of the methoddatabasethat you are calling, both classes have the same logic (so, it doesn't matter which implementation is being used).This means that it will look for a key with the prefix
slick.dbs.<db name>. Based on the error message you gotyou tried to look for a db config with the prefix
slick.dbs.playand the stracktrace shows that in this case the implementation from evolutino module is being used.To solve the issue you have two options:
playof the keydbNametodefaultslick.dbs.defaulttoslick.dbs.play