flowable/flowable-engine · error · ActivitiException

Could not instantiate businessRuleTask

Error message

Could not instantiate businessRuleTask (id:${businessRuleTask.getId()}) class: ${businessRuleTask.getClassName()}

What it means

For a businessRuleTask that specifies a custom className, DefaultActivityBehaviorFactory loads the class reflectively and instantiates it as a BusinessRuleTaskDelegate. Any failure (ClassNotFoundException, instantiation errors, ClassCastException) is wrapped in this ActivitiException naming the task id and class.

Solutions

  1. Verify the className is fully qualified and present on the runtime classpath
  2. Ensure the class has a public no-arg constructor and implements BusinessRuleTaskDelegate
  3. Remove the className attribute to fall back to the built-in BusinessRuleTaskActivityBehavior
  4. Check the exception cause to distinguish NotFound vs Instantiation vs Cast failures

Example fix

// before
public class MyRuleTask { private MyRuleTask() {} } // no accessible ctor
// after
public class MyRuleTask implements BusinessRuleTaskDelegate {
  public MyRuleTask() {}
  // evaluateRules()/execute implementation
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify class before deploy
try {
  Class<?> c = Class.forName("com.acme.MyRuleTask");
  c.getDeclaredConstructor().setAccessible(true);
  if (!BusinessRuleTaskDelegate.class.isAssignableFrom(c))
    throw new IllegalStateException("Must implement BusinessRuleTaskDelegate");
} catch (Exception e) { throw new IllegalStateException("businessRuleTask class invalid: " + e.getMessage()); }

Type guard

static boolean isValidBusinessRuleClass(String className) {
  try {
    Class<?> c = Class.forName(className);
    return BusinessRuleTaskDelegate.class.isAssignableFrom(c) &&
           java.lang.reflect.Modifier.isPublic(c.getModifiers());
  } catch (Throwable t) { return false; }
}

Try / catch

try {
  repositoryService.createDeployment().addClasspathResource(processXml).deploy();
} catch (ActivitiException e) {
  if (e.getMessage().startsWith("Could not instantiate businessRuleTask")) {
    log.error("bad class/ctor for task; cause:", e.getCause());
  }
}

Prevention

When it happens

Trigger: A businessRuleTask in BPMN XML declares <flowable:class>my.RuleTask</flowable:class> but the class is missing, has no public no-arg constructor, is abstract, or does not implement BusinessRuleTaskDelegate.

Common situations: Typos or refactors in the class name in XML; the rules task class lives in a jar not deployed with the app; class implements the wrong interface after an engine upgrade.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/099fcb999352d9f0. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/factory/DefaultActivityBehaviorFactory.java:276

        fieldDeclarations.add(exceptionMapsFieldDeclaration);

    }

    @Override
    public ShellActivityBehavior createShellActivityBehavior(ServiceTask serviceTask) {
        List<FieldDeclaration> fieldDeclarations = createFieldDeclarations(serviceTask.getFieldExtensions());
        return (ShellActivityBehavior) ClassDelegate.defaultInstantiateDelegate(ShellActivityBehavior.class, fieldDeclarations);
    }

    @Override
    public ActivityBehavior createBusinessRuleTaskActivityBehavior(BusinessRuleTask businessRuleTask) {
        BusinessRuleTaskDelegate ruleActivity = null;
        if (StringUtils.isNotEmpty(businessRuleTask.getClassName())) {
            try {
                Class<?> clazz = Class.forName(businessRuleTask.getClassName());
                ruleActivity = (BusinessRuleTaskDelegate) clazz.newInstance();
            } catch (Exception e) {
                throw new ActivitiException("Could not instantiate businessRuleTask (id:" + businessRuleTask.getId() + ") class: " +
                        businessRuleTask.getClassName(), e);
            }
        } else {
            ruleActivity = new BusinessRuleTaskActivityBehavior();
        }

        for (String ruleVariableInputObject : businessRuleTask.getInputVariables()) {
            ruleActivity.addRuleVariableInputIdExpression(expressionManager.createExpression(ruleVariableInputObject.trim()));
        }

        for (String rule : businessRuleTask.getRuleNames()) {
            ruleActivity.addRuleIdExpression(expressionManager.createExpression(rule.trim()));
        }

        ruleActivity.setExclude(businessRuleTask.isExclude());

        if (businessRuleTask.getResultVariableName() != null && businessRuleTask.getResultVariableName().length() > 0) {
            ruleActivity.setResultVariable(businessRuleTask.getResultVariableName());

View on GitHub (pinned to d6d39ce1c6)