elarib
elarib

Reputation: 674

How to get application.conf variable in an object using Scala and Play 2.5.x?

I used to get the application.conf variable in Play 2.4.x with Play.current.configuration.getString('NAME_HERE'), and it was working good in class, object and companion object too.

Now, I'm using Play 2.5.4 with Scala in a new project, and I won't use this Play.current, because it's deprecated, but there is an alternative using DI, like this :

class HomeController @Inject() (configuration: play.api.Configuration) extends Controller {
  def config = Action {
    Ok(configuration.underlying.getString("db.driver"))
  }
}

This DI Injection works like a charm in class, but in this project, I need to get the variable db.driver in a object? And as far I know, with an object I can't use DI.

Maybe using Guice would help?

Upvotes: 3

Views: 2361

Answers (3)

nir
nir

Reputation: 3868

Have you tried

import com.typesafe.config.ConfigFactory
val myConfig = ConfigFactory.load().getString("myConfig.key")

Above approach doesn't require you to convert your object to singleton class.

Upvotes: 1

suish
suish

Reputation: 3353

You can use @Singleton annotated class instead of object

trait Foo {}

@Singleton
class FooImpl @Inject()(configuration: play.api.Configuration)) extends Foo {
  //do whatever you want
}

@Singleton makes the class singleton.It feels bit awkward because Scala itself natively have syntax object to create a singleton, But this is the easiest and probably best solution to DI into a singleton.

You also may create the singleton eagerly like the code below.

bind(classOf[Foo]).to(classOf[FooImpl])asEagerSingleton()

for more detail Info, You can look up Google Guice Wiki and Playframework site

EDIT

How you call it is exactly the same as how you DI in Playframework2.5.

class BarController @Inject()(foo: Foo) extends Controller {
  //Do whatever you want with Foo
}

Guice basically generates new instance every time you DI, Once you put @Singleton, Guice use only one instance instead.

DI is for anti-high coupling.So when you want to use a class you defined from another class,You need to DI otherwise the classes are highly coupled which end up making it harder to code your unit test.

FYI, You can use them outside of Play with this technique.

Create an Instance of class which does DI via Playframework Guice Independently in Scala

Upvotes: 1

rethab
rethab

Reputation: 8443

You can do

Play.current.configuration

however that will (probably) no longer be possible with Play 2.6.

Ideally, however, you would pass the configuration in as a parameter to that method of the object or, use a class instead of an object.

What I somtimes do to migrate 'from object to class':

class MyComponent @Inject() (config: Configuration) {
  // here goes everything nice
  def doStuff = ???
}

object MyComponent {
  @deprecated("Inject MyComponent")
  def doStuff = {
    val instance = Play.current.injector.instanceOf[MyComponent]
    instance.doStuff
  }
}

This way, you're not breaking existing code while all users of your methods can slowly migrate to using classes.

Upvotes: -1

Related Questions