i have a little problem. I have to create a scala application. This application have to do some stuff. Create threads and other stuff. That isnt important for this question.
But to interact with this application it is neccessary to create a webinterface. I would like to create this interface by play.
The problem is, i have to integrate the play application inside my normal application. As component. And in the same moment as the application is runnig, he has to start also the play component. And if this worker is fail sometime, to restart it.
Is that possible? And if yes which way you would suggest.
You can invoke your normal application when play framework is starting. (http://www.playframework.com/documentation/2.2.x/ScalaGlobal) More specifically, onStart method in global object may be right place where you call your normal codes.
import play.api._
object Global extends GlobalSettings {
val yourInstance = new YourInstance()
override def onStart(app: Application) {
yourInstance.start()
}
}
Additionally, you can change your thread model to actor model. (http://www.playframework.com/documentation/2.2.x/ScalaAkka)
Related
I have a Scala-Play 2.5.x application that is actually a "Services Container" meaning under some service specification the user can hot-deploy services and they can be executed etc. Some of the services need common functionality like e.g. connection to a time-series database e.g. KDB.
I'd like to define in my Play application components that will know when the application starts and ends so they can do initialization and shutdown of their resources. I also need their "state" for example KDB connections to be made accessible to the deployed services in a seamless way i.e.
A request to execute a service is intercepted
The service "requirements" are inspected e.g. service X needs access to specific KDB connections
The service is generically instantiated and executed injecting the KDB connection required using IoC.
I have everything described above except this concept of "Component". I checked out Play books that talk about a previous play.api.Plugin trait that was a good start i.e. it had onStart onEnd etc. but it seems that this interface is gone in 2.5.x. Then I checked out how to create application Modules but all I see is an subclass of Module that overrides def bindings that does a bunch of IoC but nothing else. How can I cover my use-case of an application Component that has access to play web application lifecycle events and that can provide some state to specific requests?
From the manual: ScalaDependencyInjection could this help:
import scala.concurrent.Future
import javax.inject._
import play.api.inject.ApplicationLifecycle
#Singleton
class MessageQueueConnection #Inject() (lifecycle: ApplicationLifecycle) {
val connection = connectToMessageQueue()
lifecycle.addStopHook { () =>
Future.successful(connection.stop())
}
//...
}
This is the way for Play 2.5 and 2.6.
I am reading that the playframework is removing global state that is in older 2.4.x versions.
Can someone explain where the global state currently is and what are the benefits of removing global state?
What is the global state?
There is an object play.api.Play with the following field:
#volatile private[play] var _currentApp: Application = _
Where is it used?
Whenever you do Play.current you refer to that single mutable global field. This is used all across the framework to access things such as:
play.api.Play.configuration takes an implicit app
play.api.libs.concurrent.Execution.defaultContext calls the internal context, which uses the currently running app to get the actor system
play.api.libs.concurrent.Akka.system takes an implicit app
play.api.libs.ws.WS.url takes an implicit app
and many more places..
Why is that bad?
A number of functions just take an implicit app, so that's not really global state, right? I mean, you could just pass in that app. However where do you get it from? Typically, people would import play.api.Play.current.
Another example: Let's say you want to develop a component that calls a webservice. What are the dependencies of such a class? The WSClient. Now if you want to get an instance of that, you need to call play.api.libs.ws.WS.client and pass in an application. So your pretty little component that logically only relies on a webservice client, now relies on the entire application.
Another big factor and a direct consequence of the previous point is testing. Let's say you want to test your webservice component. In theory, you'd only need to mock (or provide some dummy implementation of) the webservice client. However now that somewhere in your code you're calling play.api.Play.current, you need to make sure that that field is set at the time it is called. And the easiest way to ensure that is to start the play application. So you're starting an entire application just to test your little component.
I am starting a project which is supposed to provide both:
simple http API and
some other functionality (including some low-level networking).
This is why I would like to integrate the "other functionality" with a (new) Play framework project and make use of it's on-the fly compilation and other benefits. The majority of the application (both in terms of business logic and server load) will be in the non-web part of the project.
So my question is: how do I go about packing both those modules into one Scala application?
The best approach I think I found is treating the non-web part as a plugin for the Play project. I am not sure however if this is the right approach, considering the majority of the application might end up in such a "plugin".
I thought about deploying the two parts as separate applications, but I doubt it would work for me: I would like the applications to share (among others) cache, config and db connections, and I shouldn't really separate them.
I'm not yet experienced with either Scala or Play, so I will very much appreciate your input.
I would recommend using Akka actor systems to integrate your existing business logic and networking services. You can easily add multiple Akka actor systems and integrate them into a complete system in your Play application. Play also comes with an internal actor system that you can take advantage of.
So, you can wrap your existing logic into an actor system in itself or you can build small actor systems that takes care of the integration with the existing systems and start up those connectors as actor systems when the Play application loads.
Here is an example how you can load the internal actor system when the Play application loads.
object Global extends GlobalSettings {
override def onStart(app: Application) {
Logger.info("Application starting...")
lazy val enabled = Play.configuration.getString("external-service").filter(_ == "enabled").isDefined
// Start External service
enabled match {
case true => {
Logger.info("External service is enabled.")
Akka.system.actorOf(Props[ExternalServiceClient], name = "serviceClient")
}
case false => {
Logger.info("External service is disabled.")
}
}
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
}
You can also load new actor systems within the application if needed, doing something like this.
import akka.actor.ActorSystem
val eventSystem = ActorSystem("events")
// Start a service using the ActorSystem
val eventService = EventService(eventSystem)
// Create an Actor in the ActorSystem
val eventActor = eventSystem.actorOf(Props[EventActor], name = "eventactor")
You can read more about Play Akka integration here. Play also has built in functionality where you can take advantage of the built in actor system with features such as the ScalaAsync etc. So if your external services are mainly HTTP based services that approach might work best for you. If you build actor systems for your external services you can access then as remote actors as explained here Akka Remoting
I write an Android application. I have a lot of Activities in my application with a large number of transitions between Activities. I decided to realize a state machine, which will switch my activities.
I hoped to realize a State Machine in my Application class or its subclass, but I can't start any Activity from it.
public class MainAppClass extends Application {}
the code like this is failing:
Intent intent = new Intent();
intent.setClass(this.MyActivity, Screen2Activity.class);
StartActivity(intent);
Maybe, is it unreal? Are there other methods for such tasks?
Thanks for your answers!
Here's another question: Why are you trying to start an activity from a subclass of Application?
Read this (from the documentation) and you'll see why what you are trying to do doesn't make any sense.
The Application class is the base class for those who need to maintain global application state. There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
If you edit your original post, clarifying why you are trying to do this, perhaps I can point you to a more suitable means of launching your Screen2Activity.
Imagine I have an application written using Play 2. Imagine that application needs to grab hold of some things on startup (read a config file, grab some resources from JNDI, that kind of thing). Play handily gives us the GlobalSettings object that we can use to hook into start and stop events:
import play.api._
object Global extends GlobalSettings {
var someResource: Resource = _
override def onStart(app: Application) {
// might throw an exception if the path doesn't exist
resource = JNDI.grabThing("/some/path").asInstanceOf[Resource]
}
}
The problem is - what can we do if the initialisation fails? It seems that this is only executed when Play receives the first request for the application. If we throw an exception, that causes that request to fail, but the application keeps on running.
Ideally, what I'd like is to stop the application from starting at all if this block doesn't complete successfully. Unfortunately, calling Play.stop() doesn't actually seem to, well, stop Play. I can see that the Server trait defines def stop(), which looks promising but I can't figure out a way to get hold of the Server instance from inside my application.
Perhaps I'm looking at this the wrong way, and I'm not supposed to be able to stop Play (or even just my app) from inside my application, so suggestions for other approaches are welcome.
What's the best way to handle these errors?
It seems I'm lying. Play only continues to serve requests after an exception in onStart if you're running in dev mode (play run). If started with play start (i.e. production mode) an exception here will terminate the server, which is exactly what I wanted.
It does appear to leave the RUNNING_PID file lying around, which is irritating, but that's a separate issue...