cancel
Showing results for 
Search instead for 
Did you mean: 

BusinessRuleTask // icon + implementation

skay
Champ in-the-making
Champ in-the-making
Hi,

This topic is actually for both forums : designer and engine.

I would like to keep the bpm icon semantic of BusinessRuleTask, but we have our own RuleEngine implementation / not a drools 5.5 lib directly in the classpath, but rather a kind of remote executor.

This is currently possible / User Guide / Business Rule Task [Experimental]:

"
As mentioned earlier another option is to hook in the implementation of the BusinessRuleTask yourself:

<businessRuleTask id="businessRuleTask" activiti:class="${MyRuleServiceDelegate}" />
                         
Now the BusinessRuleTask behaves exactly like a ServiceTask, but still keeps the BusinessRuleTask icon to visualize that we do business rule processing here.
"

I'm facing  2 problem

#1 designer
Activiti designer currently does not provide the field "activiti:class";  Curiously, this field is available in Activiti Modeler.
I can edit manually in the XML, but could you add this field in a future release of the designer ? would be great !

#2 engine
Currently, a businessRuleTaskActivityBehaviour is tightly coupled with drools.
See here below :
——

import org.activiti.engine.impl.rules.RulesHelper;
import org.drools.KnowledgeBase;
import org.drools.runtime.StatefulKnowledgeSession;


/**
* activity implementation of the BPMN 2.0 business rule task.
*
* @author Tijs Rademakers
*/
public class BusinessRuleTaskActivityBehavior extends TaskActivityBehavior {
 
  protected Set<Expression> variablesInputExpressions = new HashSet<Expression>();
  protected Set<Expression> rulesExpressions = new HashSet<Expression>();
  protected boolean exclude = false;
  protected String resultVariable;

  public BusinessRuleTaskActivityBehavior() {}

——

Conclusion :
I need to put the drools library within my classpath just for having the visual representation of "BusinessRuleTask" BPMN component in my process / better than just "ServiceTask" / the understanding of my bosses Smiley Happy

On a technical point of view, you are not providing any param to control if the user re-use a stateful ruleEngine session or if he just need a statelessSession.
Furethermore, the usage of the RulesHelper is a little bit static and not clearly open to any customization.

A purist would say that we should rely on e.g. JSR-94 spec rather than KnowledegeBase Drools impl and custom factories.

So 2 different pieces of solutions.

a)
We could modify the implementation of the current BusinessRuleTaskActivityBehavior into something a little more abstract.
Actually we don't need Drools at this stage / we could delegate this job to a Drooly / Custom specific implementation of the BusinessRuleTask.

b)
A new feature of the designer/modeler would be to let the user link the freedom of bpmn tasks icons (why not custom icon?!).
E.G a new "Custom ActivityTask" / same as "serviceTask" but referencing an ActivityBehavior java class implementation as main parameter ?
, and the BPMN icon as second main parameter.

Do you see other/simpler solutions ?

I'll be glad to contribute to the small change proposed here (a) and stage the current [experimental] feature of BusinessRuleTask to a definive one.

Best Regards
10 REPLIES 10

jbarrez
Star Contributor
Star Contributor
* I need to put the drools library within my classpath just for having the visual representation of "BusinessRuleTask" BPMN component in my process

I don't get that. It shouldn't be needed.

All behaviours are instantiated by the org.activiti.engine.impl.bpmn.parser.factory.ActivityBehaviorFactory. You can extends the default one and return your own implementation for the business rule task.

* A new feature of the designer/modeler would be to let the user link the freedom of bpmn tasks icons (why not custom icon?!).

That is possible with custom elements in the designer. See http://activiti.org/userguide/index.html#eclipseDesignerCustomizingPalette

skay
Champ in-the-making
Champ in-the-making
OK, this is the exercpt of my bpmn
<businessRuleTask id="businessruletask1" name="Business rule task" activiti:class="messagein.RuleEngineDelegate"></businessRuleTask>

Works OK if serviceTask instead of businessRuleTask.

Here is the ClassNotFound stack trace :

java.lang.NoClassDefFoundError: org/drools/runtime/rule/AgendaFilter
at org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory.createBusinessRuleTaskActivityBehavior(DefaultActivityBehaviorFactory.java:232)
at org.activiti.engine.test.TestActivityBehaviorFactory.createBusinessRuleTaskActivityBehavior(TestActivityBehaviorFactory.java:239)
at org.activiti.engine.impl.bpmn.parser.handler.BusinessRuleParseHandler.executeParse(BusinessRuleParseHandler.java:37)


So it breaks out when parsing bpmn.
Seems like  activiti:class="messagein.RuleEngineDelegate" is ignored ?

Finally, I tried those solutions :

<businessRuleTask id="businessruletask1" activiti:class="messagein.RuleEngineDelegate"></businessRuleTask>

<businessRuleTask id="businessruletask1" activiti:class="${messagein.RuleEngineDelegate"}></businessRuleTask>

<businessRuleTask id="businessruletask1" activiti:delegateExpression="${ruleEngineDelegate}" ></businessRuleTask>

But all are throwing the ClassNotFound ..

skay
Champ in-the-making
Champ in-the-making
I can fix the problem tweaking the source :

public class BusinessRuleParseHandler extends
  AbstractActivityBpmnParseHandler<BusinessRuleTask> {

public Class<? extends BaseElement> getHandledType() {
  return BusinessRuleTask.class;
}

@Override
protected void executeParse(BpmnParse bpmnParse,
   BusinessRuleTask businessRuleTask) {

  ActivityImpl activity = createActivityOnCurrentScope(bpmnParse,
    businessRuleTask, BpmnXMLConstants.ELEMENT_TASK_BUSINESSRULE);
  activity.setAsync(businessRuleTask.isAsynchronous());
  activity.setExclusive(!businessRuleTask.isNotExclusive());
//FIXXX
  if (businessRuleTask.getClassName()!=null) {
   ClassDelegate cd= new ClassDelegate(businessRuleTask.getClassName(), null);
   activity.setActivityBehavior(cd);
  } else {
///ORIG
   activity.setActivityBehavior(bpmnParse.getActivityBehaviorFactory()
     .createBusinessRuleTaskActivityBehavior(businessRuleTask));
  }
}

}

jbarrez
Star Contributor
Star Contributor
Which is why I said you need to change  org.activiti.engine.impl.bpmn.parser.factory.ActivityBehaviorFactory implementation and indeed probably the handler. If you want to change the default behaviour (and keep using the businessRuleTask xml), it's the only way

skay
Champ in-the-making
Champ in-the-making
Hi,

This is the reason of the classCast :

<code>

<name>Activiti - Engine</name>
  <artifactId>activiti-engine</artifactId>

  <parent>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-root</artifactId>
    <relativePath>../..</relativePath>
    <version>5.17.0-SNAPSHOT</version>
  </parent>

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-core</artifactId>
      <scope>provided</scope>
    </dependency>
<dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-compiler</artifactId>
      <scope>provided</scope>
    </dependency>

</code>

… And actually this lib is not present in activiti.explorer's distribution // supposed to be in the classpath

jbarrez
Star Contributor
Star Contributor
No, because the scope is 'provided'. Meaning, if you need it, you need to put it on the classpath yourself.

But in your case, it shouldn't be if you need Drools and replace the existing business rule logic yourself.

skay
Champ in-the-making
Champ in-the-making
" it shouldn't be if you need Drools and replace the existing business rule logic yourself"
-> This is the intention of the code / and User Guide notice :
http://www.activiti.org/userguide/#bpmnBusinessRuleTask

<code>
<businessRuleTask id="businessRuleTask" activiti:class="ch.ectropy.MyBusinessRule" />
</code>

Unfortunately, a hook over BusinessRuleTaskActivityBehavior is not working the because activiti:class value is not handled properly.
  (no usage of BusinessRuleTask.getClassName() in the code !)

DefaultActivityBehaviourFactory is *always* creating a new instance of the BusinessRuleTaskActivityBehavior :

<code>
  public BusinessRuleTaskActivityBehavior createBusinessRuleTaskActivityBehavior(BusinessRuleTask businessRuleTask) {
    BusinessRuleTaskActivityBehavior ruleActivity = new BusinessRuleTaskActivityBehavior();
</code>

see pull request #427 for a simple fix proposal.
But maybe a harder refactoring is required here…

jbarrez
Star Contributor
Star Contributor
I'm not following here:

> DefaultActivityBehaviourFactory is *always* creating a new instance of the BusinessRuleTaskActivityBehavior :

Which is why you need to swap out the activityBehaviour so it doesn't do that, right?

To help this discussion: can you put your work in a unit test that demonstrates what you are tying to do?

skay
Champ in-the-making
Champ in-the-making
Yes, thats right;
Finally, the followings should be a good solution for a refactoring.
-> Camel task, mule task, and even mail task are built upon a Service Task pattern.
I think that the BusinessRule Task should move to that pattern / should be unified in order to inherit from the delegate expression, etc.
And the ServiceLocator-like parttern used for Camel Task should be applied the same for the BusinessRule Task.