Malax
Malax

Reputation: 9614

Play! Framework: Reuse of instances over multiple requests

I develop an application using the Play! Framework which makes heavy use of the javax.script Package, including the ScriptEngine. As ScriptEngines are expensive to create and it would make sense to use them across multiple requests (I don't bother to create multiple ScriptEngines, one per Thread - at least i won't create ScriptEngines for each Request over and over).

I think this case is not restriced to ScriptEngines, there might be something in the framework I'm not aware of to handle such cases.

Thank you for any ideas you have! Malax

Upvotes: 2

Views: 1063

Answers (2)

niels
niels

Reputation: 7309

Why don't you implement a Script-Pool? So each request get a instance from the pool the same way as a JDBC-Connection-Pool. But make sure the Script-Engine is stateless.

Upvotes: 0

Pere Villega
Pere Villega

Reputation: 16439

Play is stateless, so there is no "session-like" mechanism to link an object to a user. You may have 2 alternatives:

Use the Cache. Store the ScriptEngine in the cache with a unique ID, and add a method that checks if it's still there. Something like:

public static Engine getScriptEngine(Long userId) {
     String key = "MY_ENGINE" + userId;
     ScriptEngine eng = (ScriptEngine) Cache.get(key);
     if(eng == null) {
        eng = ScriptEngine.create(); 
        Cache.put(key, eng);
     }
     return eng;
}

Or create a singleton object that contains a static instance of the ScriptEngine so it's always there once the server starts.

I would say the Cache one is the best approach.

EDIT: on your comment, this will depend on situation:

  1. If you want to reuse a Engine across multiple request of a unique user (that is, each user has his own ScriptEngine to work with) the cache method works as the cache links the Engine to the user id. This would solve any threading issue too.
  2. Otherwise, if you want to reuse it across multiple requests of multiple users, the static method is a better approach. But as you mention the access won't be thread safe, in Play or in any system.

I'm thinking your best bet is to work asynchronously with them. I don't know how you will use the ScriptEngines, but try to do something like this:

  • On request, store an entry in a table from the db marking a ScriptEngine processing request
  • In the same request, launch an asynchronous job (or have on running every 30 seconds)
  • The job will read the first entry of the table, remove it, do the task, return answer to the user. The job may have a pool of ScriptEngine to work with.
  • As jobs are not launched again while a current job is working, if you have enought requests the job will never cease working. If it does it means that you don't need engines at that time, and they will be recreated on demand.

This way you work linearly with a pool, ignoring threading issues. If you can't do this, then you need to fix the thread-safety of your ScriptEngine, as you can't pretend to share an object that it's not thread safe in a server environemnt which spawns multiple threads :)

Upvotes: 2

Related Questions