cancel
Showing results for 
Search instead for 
Did you mean: 

What is the best way to call methods of a Stateless EJB?

mskaesz
Champ in-the-making
Champ in-the-making
Hey guys,

I found four ways to call a method of a Stateless EJB. Which one do you recommend?

My environment: Activiti5.beta1; EJB3; JBoss AS 5.

1.) In the first listing I have an EJB which is already injected via JBoss AS. I'm setting the EJB as variable when the process is started.





@EJB(name="ejb/friends")
private FriendsServiceRemote friendsServiceRemote;



ProcessEngineImpl engine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();

Map<String, Object> variables = new HashMap<String, Object>();
variables.put("friendsServiceRemote", friendsServiceRemote);
             
engine.getRuntimeService().startProcessInstanceByKey("helloWorld", variables);


In the process I call the EJB the following way:


<serviceTask id="javaService" name="javaService" activiti:method-expr="#{friendsServiceRemote.doSomething}" />

doSomething is a method of my EJB. This solution works without any problems. What's happening behind the scenes? Is it a good idea to set the whole EJB as variable?

2.) The second way is to implement ActivityBehavior and to extend BpmnActivityBehavior (like it's described in the user manual).


@Stateless
public class FriendsService extends BpmnActivityBehavior implements FriendsServiceRemote, ActivityBehavior {

     public void execute(ActivityExecution execution) throws Exception {
          System.out.println("huhu");
          performDefaultOutgoingBehavior(execution);
     }
}


In the process I call the EJB the following way:


<serviceTask id="javaService" name="javaService" activiti:class="de.backend.services.friends.impl.FriendsService" />

Works, but I have to implement and extend the Activiti stuff and I can't invoke different methods of the same EJB.

3.) The third one is to call my EJB from a Spring bean. Actually, I have no clue about Spring and so I haven't tested it… I had the idea because of the new chapter(Spring Integration) in the user manual. What exactly does "Integration" mean? Is their a "special" way how Activiti handles the Spring beans? Is it possible to inject EJBs like Spring beans and to use them the same way like you use the Spring beans?

4.) Last but not least the WebServiceTask. I can make all my methods available as Web Services and call them in the WebServiceTask. I hope I can try it out in the next release! What do you think about that?

Thanks in advance.

Cheers,
Marc
15 REPLIES 15

tombaeyens
Champ in-the-making
Champ in-the-making
you should call your ejb just like you would do from a servlet.

in the activiti behavior, you should look up the local home in jndi and perform the invocation on that bean.

bernd_ruecker
Champ in-the-making
Champ in-the-making
In my oppinion implementing the Activiti Behavior is just a temporary solution since EventListeners (like in jBPM) are not available. So I think it is best for now.

Having it as a process variable is too risky in sense of lifecycle I think (you have to make sure, the reference is not persisted, and that it is available all the time you need it).

For 3 I cannot say too much, since I don't know the latest status to be honest, 4 may be an option, but I think technically you should avoid the WebService overhead if you can, even if that maybe makes your BPMN 2.0 process better portable to other BPMN 2.0 engines (theoretically ;-)).

Cheers
Bernd

falko_menge
Champ in-the-making
Champ in-the-making
I agree with Bernd in that a Java class attached to a BPMN Service Task should not be forced to call performDefaultOutgoingBehavior(execution) or execution.take(transition).

Essentially, a Java-based BPMN Service Task should work like a jBPM4 Java Activity and must not be able to influence the execution of the Sequence Flow, as that would violate BPMN's execution semantics. As a shortcut, one could have a ServiceTaskBehavior interface, that allows random access to data objects, but only read access to the execution state.

There might be also a need for custom BPMN Flow Node implementations, which do influence the execution of the Sequence Flow. However, such a custom Flow Node should be called neither Service Task nor Activity, when it can really behave like any Flow Node even Gateway or Event.

tombaeyens
Champ in-the-making
Champ in-the-making
Would it be a solution to split the interface for the 2 different purposes:

1) One interface for service task implementations that does not expose control flow operations.
2) One interface for advanced use cases that does expose control flow operations.

First I want to hear if this is a good solution.   And a subsequent aspect from this is the naming of those interfaces.

For (1) we could leverage the PVM EventListener interface.  Is it necessary to create a BPMN duplicate for this?  Last time we discussed this we said no i think.
For (2) we could just delegate to ActivityBehavior itself for this in similar manner.

falko_menge
Champ in-the-making
Champ in-the-making
For (1) the PVM EventListener interface does not seem suitable, as it doesn't provide read-only access to the state of the process instance and is too much focused on event handling. I'd suggest something like:

public interface ServiceTaskBehavior {
  void execute(ServiceTaskExecution execution) throws Exception;
}
with ServiceTaskExecution being the following subset of ActivityExecution:

public interface ServiceTaskExecution extends DelegateExecution {
  PvmActivity getActivity();
  ActivityExecution getParent();
  List<? extends ActivityExecution> getExecutions();
  boolean isActive();
  boolean isConcurrent();
  boolean isProcessInstance();
  List<ActivityExecution> findInactiveConcurrentExecutions(PvmActivity activity);
}
However, one could argue, whether it is good to have Service Tasks the behave differently, based on their location in a process definition and the execution state of the process instance. If not, a DelegateExecution would be enough. Any opinions on that?

For (2) the ActivityBehavior interface is fine, although in terms of BPMN it is more a FlowNodeBehavior. But, I agree that it doesn't make sense to introduce another interface just for the sake of using BPMN terminology if the rest of the APIs isn't using it anyway.

As a third option I'd suggest the Service Task being able to call an arbitrary method of some Java class with explicit parameter passing as in the jBPM4 Java Activity.

bernd_ruecker
Champ in-the-making
Champ in-the-making
wever, one could argue, whether it is good to have Service Tasks the behave differently, based on their location in a process definition and the execution state of the process instance. If not, a DelegateExecution would be enough. Any opinions on that?

I would like to have these information. If you for example just want to log the current node name or something like that, it make sense. The important thing is, that you cannot influence anything.

falko_menge
Champ in-the-making
Champ in-the-making
The discussion about Java-based BPMN Service Tasks is continued in http://jira.codehaus.org/browse/ACT-156

bernd_ruecker
Champ in-the-making
Champ in-the-making
Hey guys.
I wanted to ping that again. In the current implementation with the DelegateExecution you cannot access enough stuff, so you have to cast for a lot of requirements. We should improve that to avoid the necessity of casting for basic use cases (like seeing in with activity we are at the moment).

jbarrez
Star Contributor
Star Contributor
Bernd, could you describe what you are missing ?

Currently its basically variables only, which is appropiate I think for the typical delegation use cases.
If you want the more powerful stuff, you need to implement the ActivityBehavior interface, which gives you access to the more powerful operations.

From the docs:
To implement a class that can be called during process execution, this class needs to implement the org.activiti.engine.delegate.JavaDelegation interface and provide the required logic in the execute method. When process execution arrives at this particular step, it will execute this logic defined in that method and leave the activity in the default BPMN 2.0 way.

[EXPERIMENTAL] It is also possible to provide a class that implements the org.activiti.engine.impl.pvm.delegate.ActivityBehavior interface. Implementations have then access to the more powerful ActivityExecution that for example also allows to influence the control flow of the process. Note however that this is not a very good practice, and should be avoided as much as possible. So, it is advised to use the ActivityBehavior interface only for advanced use cases and if you know exactly what you're doing.