{"record":{"id":"729bd3a9616b2e7e","repo":"Activiti/Activiti","slug":"delegate-expression-expression-did-not-resolve-729bd3","errorCode":null,"errorMessage":"Delegate expression ${expression} did not resolve to an implementation of class org.activiti.engine.delegate.TransactionDependentTaskListener","messagePattern":"Delegate expression (.+?) did not resolve to an implementation of class org\\.activiti\\.engine\\.delegate\\.TransactionDependentTaskListener","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTransactionDependentTaskListener.java","lineNumber":57,"sourceCode":"        String executionId,\n        Task task,\n        Map<String, Object> executionVariables,\n        Map<String, Object> customPropertiesMap\n    ) {\n        NoExecutionVariableScope scope = new NoExecutionVariableScope();\n\n        Object delegate = expression.getValue(scope);\n\n        if (delegate instanceof TransactionDependentTaskListener) {\n            ((TransactionDependentTaskListener) delegate).notify(\n                processInstanceId,\n                executionId,\n                task,\n                executionVariables,\n                customPropertiesMap\n            );\n        } else {\n            throw new ActivitiIllegalArgumentException(\n                \"Delegate expression \" +\n                expression +\n                \" did not resolve to an implementation of \" +\n                TransactionDependentTaskListener.class\n            );\n        }\n    }\n\n    /**\n     * returns the expression text for this task listener. Comes in handy if you want to check which listeners you already have.\n     */\n    public String getExpressionText() {\n        return expression.getExpressionText();\n    }\n}\n","sourceCodeStart":39,"sourceCodeEnd":73,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTransactionDependentTaskListener.java#L39-L73","documentation":"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.","triggerScenarios":"activiti:taskListener with transaction-dependent semantics, delegateExpression=\"${bean}\", bean not implementing TransactionDependentTaskListener.","commonSituations":"Reusing a plain TaskListener or JavaDelegate bean in a transaction-dependent task listener; class refactor dropped the interface; wrong bean wiring in Spring config.","solutions":["Implement org.activiti.engine.delegate.TransactionDependentTaskListener (notify(DelegateExecution, DelegateTask, Map, Map)) on the bean","Switch to a regular TaskListener if commit-time-only semantics aren't needed","Verify the bean name/type at runtime before deployment"],"exampleFix":"// before\npublic class MyBean implements TaskListener {...}\n// after\npublic class MyBean implements TransactionDependentTaskListener {\n  @Override public void notify(DelegateExecution e, DelegateTask t, Map<String,Object> vars, Map<String,Object> props) {...}\n}","handlingStrategy":"type-guard","validationCode":"Object bean = applicationContext.getBean(beanName);\nif (!(bean instanceof org.activiti.engine.delegate.TransactionDependentTaskListener))\n  throw new IllegalStateException(beanName + \" must implement TransactionDependentTaskListener\");","typeGuard":"boolean isTxTaskListener(Object o) { return o instanceof org.activiti.engine.delegate.TransactionDependentTaskListener; }","tryCatchPattern":"try {\n  taskService.complete(taskId);\n} catch (ActivitiIllegalArgumentException e) {\n  if (e.getMessage().contains(\"TransactionDependentTaskListener\")) {\n    logger.error(\"Wrong interface for transaction-dependent task listener\", e);\n  }\n}","preventionTips":["Don't reuse plain TaskListener beans for transaction-dependent listeners","Add unit tests that resolve the expression and assert the interface","Keep a naming convention distinguishing tx-dependent listener beans"],"tags":["activiti","task-listener","delegate-expression","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}