0

Context: This is a client server app. At the moment the EJB looks like:

public class ServerSideJob {

    @WebMethod(operationName = "launchJob")
    public String launchJob(@WebParam(name = "idUser") String idUser, @WebParam(name = "name") String name, @WebParam(name = "param") Object param) {

        Runnable controller = new JobController(screenName, fof, mm, job);
        new Thread(controller).start();
        return "job launched";
    }
}

The job is launching several other threads.

At this point, I'd like to add the possibility for the client to interrupt the job. Interrupting a thread from "the outside" is quite a dirty affair (I'd have to add many more calls per op to a db just for that), and this prompts me to switch to Akka for the multithreading.

Problem: I am not sure how / if I can merge the Akka logic with the code of the EJB above. How do I call the top actor of my hierarchy from my launchJob function? (ok, surely a noob question...)

public class ServerSideJob {

    @WebMethod(operationName = "launchJob")
    public String launchJob(@WebParam(name = "idUser") String idUser, @WebParam(name = "name") String name, @WebParam(name = "param") Object param) {

//how do I call my Akka actor here?
        return "job launched";
    }
}
Community
  • 1
  • 1
seinecle
  • 10,118
  • 14
  • 61
  • 120
  • I don't know Akka very well, but i don't think it's any easier to stop an actor than it is to stop a thread. After all, actors are implemented on top of threads. – Tom Anderson Aug 23 '13 at 21:04
  • You can send an actor a message anytime -trigerring their death or anything you'd like to see them to do. – seinecle Aug 24 '13 at 06:30
  • Note: I don't know akka very well either, so I don't pretend to be correct, that is just my understanding. – seinecle Aug 24 '13 at 10:29
  • Sure. But the actor will only act on it next time it picks up a message. You could structure a conventional threaded application in the same way. The only difficult problem is interrupting a thread or actor while it is in the middle of doing something else. – Tom Anderson Aug 24 '13 at 16:31
  • Ok. I think that an actor checking periodically for "has a message of termination arrived" is easier and more straightforward to design than a thread checking for an external variable - stored where? retrieved how? That's my impression at least. – seinecle Aug 24 '13 at 16:38
  • It's hard to answer that without knowing more about what your job actually is. But ultimately, it would consist of doing the same thing Akka does - have the thread or threads run in a loop, picking up work to do, and when they pick up work, check if they should stop. The check is made by consulting a boolean flag in some object which is shared by the controller (which can set the flag) and the workers (which can read it). – Tom Anderson Aug 25 '13 at 12:45
  • An actor will only process one message at a time, this includes "termination messages". So it is not that easy to create an actor that performs a long computation, and that you can send a termination message. Normally actors should only contain very little logic, and process each message they get very fast. If you can split your job in such a way, you should have no problems. – pushy Aug 27 '13 at 06:42
  • I'm _sure_ it's possible. I'm _not_ sure if it's a good idea. I'm pretty sure it IS a _better_ idea to use playframework, which was built from the start with Akka in mind. – Kevin Sep 09 '13 at 22:51
  • I implemented it with the solution described in the answer below and it works as intended: it gives the app a solid, flexible architecture, making the development process a breeze. – seinecle Sep 10 '13 at 05:31

1 Answers1

0

That was indeed a noob question. I did not know how to do that because, following the "hello world" example on akka.io, the app was launched without an ActorSystem so I ignored it. An ActorSystem is simply what you need:

One class for the ActorSystem, to be launched at the start up at the app:

@Singleton
@Startup
// initialize at deployment time instead of first invocation

public class SharedActorSystem {

    ActorSystem system;

    @PostConstruct
    void loadConfiguration() {
        system = ActorSystem.create("systemJobs");
    }

    public ActorSystem getSystem() {
        return system;
    }
}

And the class with the server side job:

    public class ServerSideJob {

    @EJB
    SharedActorSystem sharedActorSystem;

    @WebMethod(operationName = "launchJob")
    public String launchJob(@WebParam(name = "idUser") String idUser) {

    //getting the ActorSystem 
    ActorSystem system = sharedActorSystem.getSystem();

   final ActorRef myActor = system.actorOf(Props.create(MyActor.class));
   MsgLaunchActor msg = new MsgLaunchActor(idUser);
   myActor.tell(msg, ActorRef.noSender());
   return "job launched";
   }
}
seinecle
  • 10,118
  • 14
  • 61
  • 120
  • Right now you are creating a new actor system everytime launch job is called, that is probably not what you are looking for. Normally you should have one ActorSystem per JVM. Same goes for the actor. If you do it this way, you will create a new actor with every call. So subsequent calls will be handled by a different actor. – pushy Aug 27 '13 at 06:38
  • ok... I understand this is bad. I would need to create a single ActorSystem that would be shared as a global variable in my EAR - I don't see where I should put it? – seinecle Aug 27 '13 at 06:48
  • looks like this could be the way? http://stackoverflow.com/questions/16503599/how-do-i-load-and-store-global-variables-in-jersey-glassfish – seinecle Aug 27 '13 at 06:54