Scala Dependency Injection in Play Framework - scala

I am new to Scala, the PlayFramework, and Dependency Injection. I downloaded the sample scala play framework code. Can someone explain to me why we need to inject the Clock and the appLifeCycle? It is referenced above, so there is no need to inject it right? What is going on here? Why do we need to do this for Web Frameworks in general?
package services
import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future
/**
* This class demonstrates how to run code when the
* application starts and stops. It starts a timer when the
* application starts. When the application stops it prints out how
* long the application was running for.
*
* This class is registered for Guice dependency injection in the
* [[Module]] class. We want the class to start when the application
* starts, so it is registered as an "eager singleton". See the code
* in the [[Module]] class to see how this happens.
*
* This class needs to run code when the server stops. It uses the
* application's [[ApplicationLifecycle]] to register a stop hook.
*/
#Singleton
class ApplicationTimer #Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {
// This code is called when the application starts.
private val start: Instant = clock.instant
Logger.info(s"ApplicationTimer demo: Starting application at $start.")
// When the application starts, register a stop hook with the
// ApplicationLifecycle object. The code inside the stop hook will
// be run when the application stops.
appLifecycle.addStopHook { () =>
val stop: Instant = clock.instant
val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
Future.successful(())
}
}

I assume you're using Lightbend's Play Scala Seed, which contains the code sample that you posted.
If you look at the documentation for java.time.Clock, you'll notice it says (emphasis mine):
Best practice for applications is to pass a Clock into any method that requires the current instant. A dependency injection framework is one way to achieve this. {.. code sample omitted .. } This approach allows an alternate clock, such as fixed or offset to be used during testing.
Ultimately theĀ purpose of dependency injection is to allow you to define the interface that you want to inject into a class or an object, and configure the implementation of that interface in just one spot. The alternative is having to update a hardcoded dependency in multiple files, which can be messy and error prone. In the Play Scala Seed project, you'll notice a file called app/Module.scala. This file is one place where you can configure the bindings and they'll automatically be bound on application start. Notice the line where we bind the Clock implementation:
class Module extends AbstractModule {
override def configure() = {
// Use the system clock as the default implementation of Clock
bind(classOf[Clock]).toInstance(Clock.systemDefaultZone)
// Ask Guice to create an instance of ApplicationTimer when the
// application starts.
bind(classOf[ApplicationTimer]).asEagerSingleton()
// Set AtomicCounter as the implementation for Counter.
bind(classOf[Counter]).to(classOf[AtomicCounter])
}
}
This configuration is saying "when my application starts up, wherever I've injected a Clock should use Clock.systemDefaultZone." If you want ApplicationTimer to use a different clock during tests, you might do something like this:
import play.api.{Environment, Mode}
// Notice that we include the environment
class Module(environment: Environment) extends AbstractModule {
override def configure() = {
// Use the system clock as the default implementation of Clock
environment.mode match {
case Mode.Prod | Mode.Dev => {
bind(classOf[Clock]).toInstance(Clock.systemDefaultZone)
}
case Mode.Test => {
// Specifically use UTC clock in tests, because maybe it's easier to write assertions that way
// You could inject anything here and the ApplicationTimer would use it during tests
bind(classOf[Clock]).toInstance(Clock.systemUTC())
}
}
bind(classOf[ApplicationTimer]).asEagerSingleton()
bind(classOf[Counter]).to(classOf[AtomicCounter])
}
}
You can define modules in other places in the root package (i.e. no package com.example.whatever declaration at the top of the file) and they'll be automatically loaded, too. Otherwise, you'll need to add a binding in conf/application.conf that adds your module's name to the play.modules.enabled key. You can see a commented-out example of that in the Play Scala Seed. I also go into more depth in another answer that I've written here.
As for ApplicationLifecycle, this is a special module provided by Play that you could override with your own binding, but I'm not sure why you'd want to. It's there to give you access to hooks that execute before the application shuts down. Again, this component is injected because it would be simple to swap it out. Imagine having 100 modules that all depend on the application lifecycle. By default, it's bound to DefaultApplicationLifecycle (you can see it being bound here). If you had hardcoded DefaultApplicationLifecycle in all 100 modules, you'd have to update each one if you wanted to switch to a different lifecycle. With dependency injection, you just need to configure the binding to use a different lifecycle and the 100 modules will automatically use it.

Related

In Play framework, how would I replace executing a method in Global settings?

I'm using Play framework for a Scala application and will need to migrate to 2.6.x from 2.5.x
The Global settings class will be removed and I currently rely on it to set the joda DateTimeZone default like so: DateTimeZone.setDefault(DateTimeZone.forID("Europe/London"))
How would I replace this? It says dependency injection on the migration guide, but I thought dependency injection was for getting access to classes/variables, not for executing a method
You can add:
class Module extends AbstractModule with ScalaModule {
override def configure():Unit = {
// do your default worf here
}
}
You can use this in place of Global Settings. This is the first thing to get executed bydefault when your application runs.

Why use #Singleton over Scala's object in Play Framework?

I have been using Play! Framework for Scala for nearly a year now. I am currently using version 2.5.x.
I am aware of the evolution of controllers in Play and how developers have been forced away from static object routes.
I am also aware of the Guice usage in play.
If you download activator and run:
activator new my-test-app play-scala
Activator will produce a template project for you.
My question is specifically around this file of that template.
my-test-app/app/services/Counter.scala
package services
import java.util.concurrent.atomic.AtomicInteger
import javax.inject._
/**
* This trait demonstrates how to create a component that is injected
* into a controller. The trait represents a counter that returns a
* incremented number each time it is called.
*/
trait Counter {
def nextCount(): Int
}
/**
* This class is a concrete implementation of the [[Counter]] trait.
* It is configured for Guice dependency injection in the [[Module]]
* class.
*
* This class has a `Singleton` annotation because we need to make
* sure we only use one counter per application. Without this
* annotation we would get a new instance every time a [[Counter]] is
* injected.
*/
#Singleton
class AtomicCounter extends Counter {
private val atomicCounter = new AtomicInteger()
override def nextCount(): Int = atomicCounter.getAndIncrement()
}
You can also see its usage in this file:
my-test-app/app/controllers/CountController.scala
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import services.Counter
/**
* This controller demonstrates how to use dependency injection to
* bind a component into a controller class. The class creates an
* `Action` that shows an incrementing count to users. The [[Counter]]
* object is injected by the Guice dependency injection system.
*/
#Singleton
class CountController #Inject() (counter: Counter) extends Controller {
/**
* Create an action that responds with the [[Counter]]'s current
* count. The result is plain text. This `Action` is mapped to
* `GET /count` requests by an entry in the `routes` config file.
*/
def count = Action { Ok(counter.nextCount().toString) }
}
This means every controller which has the constructor of #Inject() (counter: Counter) will receive the same instance of Counter.
So my question is:
Why use #Singleton and then #Inject it into a controller, when for this example you could just use a Scala object?
Its a lot less code.
Example:
my-test-app/app/services/Counter.scala
package services
trait ACounter {
def nextCount: Int
}
object Counter with ACounter {
private val atomicCounter = new AtomicInteger()
def nextCount(): Int = atomicCounter.getAndIncrement()
}
Use it like so:
my-test-app/app/controllers/CountController.scala
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import services.{Counter, ACounter}
/**
* This controller demonstrates how to use dependency injection to
* bind a component into a controller class. The class creates an
* `Action` that shows an incrementing count to users. The [[Counter]]
* object is injected by the Guice dependency injection system.
*/
#Singleton
class CountController extends Controller {
//depend on abstractions
val counter: ACounter = Counter
def count = Action { Ok(counter.nextCount().toString) }
}
What is the difference? Is injection the preferred, and why?
Is injection the preferred way? Generally yes
A couple advantages of using dependency injection:
Decouple controller from the concrete implementation of Counter.
If you were to use an object, you would have to change your controller to point to the different implementation. EG Counter2.nextCount().toString
You can vary the implementation during testing using Guice custom bindings
Lets say that inside of Counter you are doing a WS call. This could cause some difficulty unit testing. If you are using dependency injection with Guice, you can override the binding between Counter and AtomicCounter to point to an offline version of Counter that you have written specifically for your tests. See here for more info on using Guice for Play tests.
Also see the motivations that Play had for migrating to DI.
I say generally because I've seen dependency injection go horribly wrong using Spring and other Java frameworks. I'd say you should use your own judgement but err on the side of using DI for Play.
Maybe because Scala's singleton object can't have parameters? For example, if you have a service class that has a DAO injected, and you want to use service in controller, you have to inject it. The easiest way(IMO) is DI with Guice... Also, you can have your dependencies in one place(module) etc...
I am not sure, if I understand your question, but injection is preferred because:
different parts of your application are less coupled
it is easier to replace your dependency with different class providing the same functionality (in case you would need to do that in future) - you will need to change few lines of code and not look for all occurrences of your object
it is simpler to test (especially when you need to mock something)
Shortly speaking: D from SOLID principles: "Depend upon Abstractions. Do not depend upon concretions".

How to plug into the play lifecycle with a module instead of a Plugin?

I see the Plugin class is now deprecated (as of 2.4.x version of play)... In the api documentation it says I should use modules instead... so that's my question.
How do I write a module, and how do I plug that module into the play lifecycle of the main app?
You don't specify which language you're using, so I'll quickly cover both. I'm basing both answers on the following repositories:
https://github.com/schaloner/deadbolt-2-java
https://github.com/schaloner/deadbolt-2-scala
Java
Write your functionality any way you want - there are no specific classes to extend. If you have dependencies on Play components such as Configuration, you should inject them.
#Singleton
public class MyModuleCode {
private final boolean enableWidgets;
#javax.inject.Inject
public MyModuleCode(final Configuration configuration) {
this.enableWidgets = configuration.getBoolean("widgets.enabled", false);
}
}
Note that dependency injection is used in place of static reference. Also, note that I've given this example a #Singleton annotation, but it's also possible to have, for example, per-request scope.
See the Play DI docs for more information
Expose the components of your module. To do this, extend the play.api.inject.Module class and implement public Seq<Binding<?>> bindings(final Environment environment, final Configuration configuration).
package com.example.module;
public class MyModule extends Module
{
#Override
public Seq<Binding<?>> bindings(final Environment environment,
final Configuration configuration)
{
return seq(bind(MyModuleCode.class).toSelf().in(Singleton.class));
}
}
Here, you can also bind implementations to interfaces, configure instance providers and so on.
If it's something you're publicly releasing the module, let's assume you do this here - it's out of scope of the question. Let's also assume you've added a dependency for the module in whichever project you're working on.
Enable the module in application.conf.
play {
modules {
enabled += com.example.module.MyModule
}
}
The components exposed via your module - just MyModuleCode in this example - is now available for injection into your controllers, actions, etc.
If you need a shutdown hook, just inject ApplicationLifecycle into the component and register the hook; see https://playframework.com/documentation/2.4.x/JavaDependencyInjection#Stopping/cleaning-up for details.
Scala
Write your functionality any way you want - there are no specific classes to extend. If you have dependencies on Play components such as CacheApi, you should inject them.
#Singleton
class DefaultPatternCache #Inject() (cache: CacheApi) extends PatternCache {
override def apply(value: String): Option[Pattern] = cache.getOrElse[Option[Pattern]](key = s"Deadbolt.pattern.$value") { Some(Pattern.compile(value)) }
}
Note that dependency injection is used in place of static reference. Also, note that I've given this example a #Singleton annotation, but it's also possible to have, for example, per-request scope.
See the Play DI docs for more information
Expose the components of your module. To do this, extend the play.api.inject.Module class and implement def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]].
package com.example.module
import com.example.module.cache.{DefaultPatternCache, PatternCache}
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}
class MyModule extends Module {
override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(bind[PatternCache].to[DefaultPatternCache])
}
Here, you can also bind implementations to traits, configure instance providers and so on.
If it's something you're publicly releasing the module, let's assume you do this here - it's out of scope of the question. Let's also assume you've added a dependency for the module in whichever project you're working on.
Enable the module in application.conf.
play {
modules {
enabled += com.example.module.MyModule
}
}
The components exposed via your module - just MyModuleCode in this example - is now available for injection into your controllers, actions, etc.
If you need a shutdown hook, just inject ApplicationLifecycle into the component and register the hook; see https://playframework.com/documentation/2.4.x/ScalaDependencyInjection#Stopping/cleaning-up for details.
Summary
Modules are no longer anything special - they're just a way of grouping injectable components.

How do I give global access to an object in Scala without making it a singleton or passing it to everything?

I have a Logger class that logs events in my application. While I only need one instance of the logger in this application, I want this class to be reusable, so I don't want to make it a singleton and couple it with my specific needs for this application.
I want to be able to access this Logger instance from anywhere in the application without having to create a new one every time or pass it around to every class that might need to log something. What I currently do is have an ApplicationUtils singleton that I use as the point of access for the application's Logger:
object ApplicationUtils {
lazy val log : Logger = new Logger()
}
Then I have a Loggable trait that I add to classes that need the Logger:
trait Loggable {
protected[this] lazy val log = ApplicationUtils.log
}
Is this a valid approach for what I am trying to accomplish? It feels a little hack-y. Is there a better approach I could be using? I'm pretty new to Scala.
Be careful when putting functionality in objects. That functionality is easily testable, but if you need to test clients of that code to make sure they interact with it correctly (via mocks and spies), you're stuck 'cause objects compile to final classes and thus cannot be mocked.
Instead, use this pattern:
trait T { /* code goes here */ }
object T extends T /* pass this to client code from main sources */
Now you can create Mockito mocks / spies for trait T in your test code, pass that in and confirm that the interactions of the code under test with the trait T code are what they should be.
If you have code that's a client of T and whose interactions with it don't require testing, you can directly reference object T.
To address what you're trying to do (rather than what you're asking), take a look at TypeSafe's scalalogging package. It provides a Logging trait that you can use like so:
class MyClass extends Logging {
logger.debug("This is very convenient ;-)")
}
It's a macro-based wrapper for SLF4J, so something like logger.debug(...) gets compiled as if (logger.isDebugEnabled) logger.debug(...).

Handling container stop/reload event

A have lift app starting ssh daemon in Boot.scala.
Here is the problem: when i run container:restart / in sbt session I get Address alread in use exception.
Now two questions:
Is it right way to start dependent service in Boot.scala?
Anyway how is it possible to handle container:stop event?
I think the Lift-y way to do it is with LiftRules.unloadHooks.
It's not well-documented (AFAIK), but if you look in the Lift source code, you'll see that when the LiftServlet is destroy()ed, the functions defined in LiftRules.unloadHooks are executed.
You can add functions to the unloadHooks RulesSeq with the append or prepend method, depending on what order you want them executed in. So, in your bootstrap.liftweb.Boot.boot method, you might do something like this:
sshDaemon.start()
LiftRules.unloadHooks.append( () => sshDaemon.stop() )
(Assuming that was how you started and stopped your SSH daemon.)
I'm not 100% certain the LiftServlet.destroy() method gets invoked when the sbt web-plugin's container:restart command is run - that's determined by the plugin and its interaction with Jetty, not by Lift - but the container:stop command should definitely do the trick.
I'm not familiar with Lift, but this advice should work for any Servlet based web application.
Register a ServletContextListener in your web.xml, and release any resources in the contextDestroyed method. (The startup should be done in the contextCreated method.)
You can use setAttribute / getAttribute to store and later retrieve the server.
Putting this all together:
import javax.servlet.{ServletContextEvent, ServletContextListener}
final class SshListener extends ServletContextListener{
val attributeKey = "sshServer"
def contextInitialized(sce: ServletContextEvent) {
val server = new Server()
server.start()
sce.getServletContext.setAttribute(attributeKey, server)
}
def contextDestroyed(sce: ServletContextEvent) {
Option(sce.getServletContext.getAttribute(attributeKey)).foreach(_.asInstanceOf[Server].stop())
}
}
class Server {
def start()
def stop()
}