How to do database initialization when using DI in Play 2.4?

1.8k Views Asked by At

Play 2.4 discourages using GlobalSettings.onStart and whole Global object.

I'm using play-slick and it has great DI sample in GitHub, but it is missing a example how to do database initialization.

How does one implement the database initialization when using DI and when GlobalSettings.onStart is not available?

Common cases for database initialization is: If in DEV mode, add these rows, if PROD do these. Examples wanted.

1

There are 1 best solutions below

0
bjfletcher On BEST ANSWER

The trick is to place the initialisation in the constructor of the injected class. Here's an example:

Add app/modules/Database.scala:

package modules

import com.google.inject.AbstractModule
import com.google.inject.name.Names

trait Database {
  def create(): Unit
  def drop(): Unit
}

class TestDatabase extends Database {
  initialize() // running initialization in constructor
  def initialize() = {
    println("Setup database with test data here")
  }
  def create() = ()
  def drop() = ()
}

class ProdDatabase extends Database {
  // similar to above
}

class DatabaseModule extends AbstractModule {
  def configure() = {
    bind(classOf[Database])
      .annotatedWith(Names.named("development"))
      .to(classOf[TestDatabase]).asEagerSingleton
    bind(classOf[Database])
      .annotatedWith(Names.named("production"))
      .to(classOf[TestDatabase])
  }
}

Add in conf/application.conf:

play.modules.enabled += "DatabaseModule"

That's to start with. The .asEagerSingleton will run the constructor code without needing you to inject it. When you want to choose which one to inject, then you'd need to remove the .asEagerSingleton and load the appropriate database implementation either:

  • based on configuration in the bindings (see link for example); or
  • in the service/controller, for example:

    @Inject @Named("development") Database database