cancel
Showing results for 
Search instead for 
Did you mean: 

Activiti Workflow and Project Architecture

fritz128
Champ in-the-making
Champ in-the-making
I start to integrate Activiti in my application, and I faced architecture problems.

My bussiness logic looks like:

  //this handler proceed ALL logic, and call needed activiti to do the final actions
  public void handle(org.eclipse.jetty.websocket.api.Session clientSession) {
    //I. Create and Save to database
    Session session = openHibernateSession();
    MyObject obj = new MyObject();
    session.save(obj);
    ….

    //II. Notify client
    clientSession.getRemote().sendString(Utils.objectToJson(obj));

    //III. Start activiti
    runtimeService.signalEventReceived("signal", executionId);   //only proceed some minor logic, like saving history!!!
  }


Problem:
I use WebSockets in my application, so I can't serialize clientSession and pass it to activiti's tasks. As a result, I can't proceed II-section of code (Notify Client) in activiti scope. As a result, I can't proceed in activiti scope all logic that  goes before II-section of code.
As I understand, the problem is that Activiti should wrap the  whole application logic, and provide more flexibility and clearance to my workflow!

What  I want:
Something like next architecture:


  //this handler only start the needed activity, and nothing else
  public void handle(org.eclipse.jetty.websocket.api.Session clientSession) {
     //I. Kick needed Activiti
     runtimeService.signalEventReceived("signal", executionId);   //proceeed ALL logic like I, II & III-code sections in example above
  }


Bad way to solve the problem:
I can't pass websocket session to the activiti's tasks, but I can ask it from task (for example save all sessions in static collection).

Disadvantage:
If I move Activiti to the separate machine, I can't pull static session list!

Question:
What is the right architecture for this case?
7 REPLIES 7

trademak
Star Contributor
Star Contributor
Maybe you can use a ThreadLocal to store the session and retrieve it from a service task. But that only works if you don't have asynchronous parts in your process.

Best regards,

jbarrez
Star Contributor
Star Contributor
The right architecture for this case is *NOT* to serialize something like a session, that's always a bad idea.
The right architecture would inject the current session into a JavaDelegate of Activiti, which is managed by a container such as Spring or CDI.

jbarrez
Star Contributor
Star Contributor
(and they will probably use thread local behind the scenes, as Tijs suggested)

fritz128
Champ in-the-making
Champ in-the-making
First of all, thank you for reply!

I get you the more detail disclosure of my subprocess, and try to explain why Injection & ThreadLocal seems not appropriate in my case.

My workflow:
I have some global process, for example, car lottery. This process starts when manager push "Start Lottery" button. He can start many loterries simultaneously.
To participate in this lottery user should go throught several stages of registration, attend on lottery, take a price (big or small, little price gives to all participants), and so on. So this task need to be moved to separate subprocess.
Workflow diagram:
[img=http://s2.postimg.org/ioq6jynp1/Process.jpg]

Problems:
I don't say that that are bad approaches, I only want to know if it is possible to solve the problems below
Why not inject:
1. As I understand, serviceTask creates only once for all subprocesses. If yes, it is not a good approach in my case, beacause I want to launch subprocess each time for different client (ass a result, each time for different session).
Why not thread local
2. Thread local is a good thing. But as I understand I should intialize my ThreadLocal session in the first task of the subprocess. This means that I should retrieve session from some getSession() method. But again, what about remote machine & serialization? 

jbarrez
Star Contributor
Star Contributor
1. In the regular Activiti way, yes. However, when integrating with a dependency container things change a bit. If you reference a bean that has a certain scope (eg session-scoped) in that container, the actual service task is not static for all processes. I didn't say that in my original post, correct, it shouln't be the session that it injected, rather the bean acting as the service task.

2. No, the session should be managed by a container and let the container manage the storage and all that. I was just saying that typically, frameworks such as Spring use thread local to do exactly that.

dmifs
Champ in-the-making
Champ in-the-making
Hi this is basically the same problem that I am facing. I want to start an activiti process and then send a message through a web socket when some event occurs in activiti ( such as end of process). I still cannot figure out how would I be able to inject the web socket sessions in a Java Delegate class or  an ExecutionListener class (such as end of process). An example would help a lot maybe using CDI.

thanks 

frederikherema1
Star Contributor
Star Contributor
Using CDI in a tasklistener is quite easy. Just inject everything you want in the TaskListener implementations. Next, configure activiti to use CDI (see userguide) and finally in your process, you reference the CDI-bean from within the task-listener, using activiti:delegateExpression="myAwsomeBean". Hope this helps…