The project is written using Play framework and Scala language.
I have implemented compile time dependency.
I have followed this example from Play:
https://github.com/playframework/play-scala-compile-di-example
Looking at the MyApplicationLoader.scala:
import play.api._
import play.api.routing.Router
class MyApplicationLoader extends ApplicationLoader {
private var components: MyComponents = _
def load(context: ApplicationLoader.Context): Application = {
components = new MyComponents(context)
components.application
}
}
class MyComponents(context: ApplicationLoader.Context)
extends BuiltInComponentsFromContext(context)
with play.filters.HttpFiltersComponents
with _root_.controllers.AssetsComponents {
lazy val homeController = new _root_.controllers.HomeController(controllerComponents)
lazy val router: Router = new _root_.router.Routes(httpErrorHandler, homeController, assets)
}
and the following line of code:
lazy val homeController = new _root_.controllers.HomeController(controllerComponents)
my understanding is that there is only one instance of HomeController created the first time HomeController is called.
And that instance lives as long as the application lives. Are these statements correct?
The HomeController in my application looks like that:
class HomeController{
val request = // some code here
val workflowExecutionResult = Workflow.execute(request)
}
So Workflow is of type object and not class.
The Workflow looks like that:
object Workflow {
def execute(request: Request) = {
val retrieveCustomersResult = RetrieveCustomers.retrieve()
// some code here
val createRequestResult = CreateRequest.create(request)
// some code here
workflowExecutionResult
}
}
So Workflow calls a few domain services and each domain service is of type object and not class.
All values inside the domain services are immutable, I am using vals everywhere.
Is this enough to ensure thread safety?
I am asking as I'm used to writing C# Web APIs where a HomeController would look like that:
class HomeControllerInSeeSharpProject{
// some code here
var request = new Request() // more code here
var workflow = new WorkflowInSeeSharpProject()
var workflowExecutionResult = workflow.execute(request)
}
and a Workflow would look like that:
public class WorkflowInSeeSharpProject {
public execute(Request request) {
var retrieveCustomers = new RetrieveCustomers()
var retrieveCustomersResult = retrieveCustomers.retrieve()
// some code here
var createRequest = new CreateRequest()
var createRequestResult = createRequest.create(request)
// some code here
return workflowExecutionResult
}
}
So in a C# project every time a HomeControllerInSeeSharpProject is called a new instance of WorkflowInSeeSharpProject is created and all the domain services
are also newed-up and then I can be sure that state cannot be shared between separate threads. So I am afraid that because my Scala Workflow
and domain services are of type object and not class that there could be a situation where two requests are sent into the HomeController
and state is shared between those two threads.
Can this be the case? Is my application not thread safe?
I have read that objects in Scala are not thread safe since there is only single instance of them. However I have also read that although
they are not thread safe using vals will make the application thread safe...
Or maybe Play itself has a way to deal with that problem?