cancel
Showing results for 
Search instead for 
Did you mean: 

ejb service task 'interface'

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
As discussed with Tom in the userforum, we'll be implementing the ejb and jms service tasks. There are many ways the calls can take place. I'd like to propose some things here for the initial implementation of the ejb service task. A similar post will come for the jms service task

First of all there is the local or remote option. Initially I think focussing on local is good enough, but if someone disagrees, feel free to comment.

Secondly, there is the choice to just call an existing ejb with a predefined interface or to have it implement an activiti specific interface kind of like the java delegate. I prefere to initially focus on existing interfaces where context variables are passed on in the method call, but again, if someone disagrees…. So a method name is needed, a list of parameters (order is important)

Thirdly there is the return value. Should it be taken into account? It probably needs to be if it is about existing interfaces where you cannot add variables to the execution (if possible at all).

But most importantly, is it a new service task or is it an addition to the java service task. Personally I'm in favour of the latter. The difference is not that big and it is probably even possible to use juel to resolve ejb's (high om my todo list, cdi?) and call the corresponding methods like in Seam. Using a 'type' like for the mail task is not what I'd do for ejb calls (I would for jms though)

So to summarize and propose element/attribute names
- only local calls (attribute, activiti:jndi-name)
- define a method name (attribute, activiti:method)
- define parameters (extension element, activiti:arg, order is important, should be like the method signature and is comparable to the activiti:field)
- define return value (extension element, optional: activiti:return)

Thoughts?
21 REPLIES 21

tombaeyens
Champ in-the-making
Champ in-the-making
Here's a pointer that I want to share: In order to map the ejb-logical names to the expressions name resolution, you should probably update this section in ExpressionManager

protected ELResolver createElResolver(VariableScope variableScope) {
    CompositeELResolver elResolver = new CompositeELResolver();
    elResolver.add(new VariableScopeElResolver(variableScope));
    elResolver.add(new ArrayELResolver());
    elResolver.add(new ListELResolver());
    elResolver.add(new MapELResolver());
    elResolver.add(new DynamicBeanPropertyELResolver(ItemInstance.class, "getFieldValue", "setFieldValue")); //TODO: needs verification
    elResolver.add(new BeanELResolver());
    return elResolver;
  }


At this point, this list of ELResolvers is not yet configurable (but the expression manager is).  I can help do that if necessary.  But first go ahead and play with it so that we know exact what kind of configurability we need.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Yep, already found that. Initial version already working… testing is more difficult than creating the code. Have added the EJBResolver at the end.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Ok, the real integration is more difficult than I thought compared to the code needed to resolve and call an ejb. The juel stuff is focussed on valueExpressions whereas in this case the method expression is a better fit. But how and when juel decides this is still not clear to me. So this might still take a few days to crystalize, but it will work…

Ronald

jbarrez
Star Contributor
Star Contributor
Ronald, what's the isssue? Frederik is a Juel-expert by now, so he will be able to help you further if needed.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Sorry, already found it…. was VERY easy (once you know it). The getValue() in a new resolver is also used to resolve bean/variable/map/… and thus the ejb to. I missed that part (still had the jBPM way in mind).

So it works. with only

  private final boolean isResolvable(Object base, Object property) {
    return base == null && property != null && property instanceof String;
  }

  @Override
  public Object getValue(ELContext context, Object base, Object property) {
    Object o = null;
    if (isResolvable(base, property)) {
      try {
        // Properties currently read from jndi.properties
        o = InitialContext.doLookup((String) property + "/remote");
      } catch (NamingException e) {
        // TODO logging…
        e.printStackTrace();
      }
      context.setPropertyResolved(true);
      return o;

    }
    return null;
  }

for the resolving. The execution itself is done by the BeanELResolver…. since that is about invoking methods etc…

Some tuning needed for the 'remote' part in names or custom names, but that will be no problem. Beans with complex jndi names will probably be difficult, but there is where the 'full' configuration comes in.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Ok, calling ejbs from an expression works. Currently with the following limitations:
- ejb name should be one that can be used as a 'property', so no /,._ etc
- first tries <name>, then <name>/local
- No access to beans that require authentication

For remote beans some way to provide the initial context should be used
and maybe a way to provide authentication, or accept these limitations and only use this for local beans.

Still, a way to provide a more complex name for local beans would be nice.

jbarrez
Star Contributor
Star Contributor
Ronald, I found my Spring/EJB example, and made a blogpost of it:

http://www.jorambarrez.be/blog/2011/01/13/tutorial-call-an-ejb-in-a-bpmn-2-0-process-using-activiti-...

Probably the approach can be made generically, by looking into the classes that wrap the actual EJB.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Yep, read it, commented and send you something (also attached to http://jira.codehaus.org/browse/ACT-537)

tombaeyens
Champ in-the-making
Champ in-the-making
Ronald, I assume that the EJBResolver had dependencies on some libraries.  Right?
If so, did you make the EJB resolver optionally configurable?

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
No, no dependencies…. All it does is a simple jndi lookup, returns an Object and the BeanResolver can execute methods on the bean. That was really all that was needed for the simple version.

The only thing still needed is to swallow the jndi lookup exception if nothing is configured since the EJBElResolver will always go of if nothing matches. We might try to do something creativly here if the instantiation of the InitialContext fails and we can detect that we do not have  context at all.