Activiti/Activiti · error · ActivitiIllegalArgumentException

Delegate expression did not resolve to an implementation of…

Error message

Delegate expression ${expression} did not resolve to an implementation of class org.activiti.engine.delegate.TransactionDependentTaskListener

What it means

Thrown when a delegateExpression for a transaction-dependent task listener resolves to an object that does not implement TransactionDependentTaskListener. Type check happens in notify() before dispatching the event.

Solutions

  1. Implement org.activiti.engine.delegate.TransactionDependentTaskListener (notify(DelegateExecution, DelegateTask, Map, Map)) on the bean
  2. Switch to a regular TaskListener if commit-time-only semantics aren't needed
  3. Verify the bean name/type at runtime before deployment

Example fix

// before
public class MyBean implements TaskListener {...}
// after
public class MyBean implements TransactionDependentTaskListener {
  @Override public void notify(DelegateExecution e, DelegateTask t, Map<String,Object> vars, Map<String,Object> props) {...}
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object bean = applicationContext.getBean(beanName);
if (!(bean instanceof org.activiti.engine.delegate.TransactionDependentTaskListener))
  throw new IllegalStateException(beanName + " must implement TransactionDependentTaskListener");

Type guard

boolean isTxTaskListener(Object o) { return o instanceof org.activiti.engine.delegate.TransactionDependentTaskListener; }

Try / catch

try {
  taskService.complete(taskId);
} catch (ActivitiIllegalArgumentException e) {
  if (e.getMessage().contains("TransactionDependentTaskListener")) {
    logger.error("Wrong interface for transaction-dependent task listener", e);
  }
}

Prevention

When it happens

Trigger: activiti:taskListener with transaction-dependent semantics, delegateExpression="${bean}", bean not implementing TransactionDependentTaskListener.

Common situations: Reusing a plain TaskListener or JavaDelegate bean in a transaction-dependent task listener; class refactor dropped the interface; wrong bean wiring in Spring config.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/729bd3a9616b2e7e. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTransactionDependentTaskListener.java:57

        String executionId,
        Task task,
        Map<String, Object> executionVariables,
        Map<String, Object> customPropertiesMap
    ) {
        NoExecutionVariableScope scope = new NoExecutionVariableScope();

        Object delegate = expression.getValue(scope);

        if (delegate instanceof TransactionDependentTaskListener) {
            ((TransactionDependentTaskListener) delegate).notify(
                processInstanceId,
                executionId,
                task,
                executionVariables,
                customPropertiesMap
            );
        } else {
            throw new ActivitiIllegalArgumentException(
                "Delegate expression " +
                expression +
                " did not resolve to an implementation of " +
                TransactionDependentTaskListener.class
            );
        }
    }

    /**
     * returns the expression text for this task listener. Comes in handy if you want to check which listeners you already have.
     */
    public String getExpressionText() {
        return expression.getExpressionText();
    }
}

View on GitHub (pinned to 56435b1a97)