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
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 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)
I'm working on the design of an with RAP/RWT, working under Tomcat. I'm learning RAP now, and a couple of questions come to my mind.
My application has a backend that works continuously gathering data from certain sources. On the other hand I want to create a frontend (RWT standalone application, or RAP with workbench functionality, not decided yet) running as a webapp.
First question: should I keep the backend as a separate process, and let the frontend RAP application communicate somehow with it? Or can I integrate everything together in the RAP application? Integrating everything together leads to the second question.
Second question: how can I detect from within the RAP application, when is the browser window/tab holding my app, closed? I would like to do some resource cleanup when the user closes the graphical interface (i.e. closes the browser). I cannot find anything equivalent to ApplicationWorkbenchWindowAdvisor#preWindowShellClose in RWT standalone applications. Same to dected when the application is started. In general, are there callbacks to follow the webapp lifecycle in RWT standalone applications?
Thanks a lot for your help!
Regarding your first point: When you use EJBs, please be aware that you can only directly access Java EE contexts from the request thread. This is not a problem when you run in JEE_COMPATIBILITY mode, but in SWT_COMPATIBILITY mode you may need to access your EJBs through RWT.requestThreadExec( Runnable );.
As for your second question, the RAP server is currently not informed on browser closes. This issue is discussed in bug 284273 - Session kill mechanism on browser close. It is not yet implemented because IIRC we couldn't find a reliable method of doing so that works in all browsers.
You could implement your own solution using a) the JSExecutor to put some JavaScript on the client that sends a request on browser close, and b) a PhaseListener that listens to these requests and terminates the session.
(*) First: decoupling is always the best practice. I use RMI stubs for receive notifications from backend application (another RMI object or EJB beans).
MyEJBListener stub = UnicastRemoteObject.exportObject(new MyEJBListener(display, page,
manager, handlermanager), 0)
MyEJBClient client1 = MyEJBLocator.findEJBClient("abc");
client1.addListener(stub);
In the stub use something like
public void notify(Event event){
UICallBack.activate("stubthread");
Display..asyncExec(new Runnable() {
// update event info
});
}
(*) Second:the method WorkbenchWindowAdvisor#postWindowClose can help you?, and call somethig method form backend app.
I take Akka 2.0 and want to use it inside my web application. For this i create Filter to run an ActorSystem on filter inits.
Filter loads, starts Akka kernel Bootable implementation.
Now i create an Actor (for user authentication) and want to send a message to it at other part of application outside of scope my akka filter. Is any way to do this (i see only making some object to hold system val)? Maybe my logic to use Akka in this way is wrong?
Thanks.
Use a ServletContextListener to create and destroy the ActorSystem and set it as an attribute on your ServletContext (make a small façade to get it and set it perhaps?) Then just obtain it from the ServletContext within your Filter.
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...