{"record":{"id":"34a4f30c56187890","repo":"Activiti/Activiti","slug":"delegate-expression-expression-did-not-resolve-34a4f3","errorCode":null,"errorMessage":"Delegate expression ${expression} did not resolve to an implementation of class org.activiti.engine.delegate.TransactionDependentExecutionListener","messagePattern":"Delegate expression (.+?) did not resolve to an implementation of class org\\.activiti\\.engine\\.delegate\\.TransactionDependentExecutionListener","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTransactionDependentExecutionListener.java","lineNumber":57,"sourceCode":"        String executionId,\n        FlowElement flowElement,\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 TransactionDependentExecutionListener) {\n            ((TransactionDependentExecutionListener) delegate).notify(\n                processInstanceId,\n                executionId,\n                flowElement,\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                TransactionDependentExecutionListener.class\n            );\n        }\n    }\n\n    /**\n     * returns the expression text for this execution 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/DelegateExpressionTransactionDependentExecutionListener.java#L39-L73","documentation":"Thrown when a delegateExpression for a transaction-dependent execution listener resolves to an object that does not implement TransactionDependentExecutionListener. Transaction-dependent listeners run only on successful transaction commit, so Activiti validates the resolved type before invoking.","triggerScenarios":"BPMN <activiti:executionListener event=\"end\"> (transaction-dependent variant) with delegateExpression=\"${bean}\" where bean is not a TransactionDependentExecutionListener.","commonSituations":"Reusing a plain ExecutionListener or JavaDelegate bean in a transaction-dependent listener slot; refactoring removed the interface; wrong bean name.","solutions":["Implement org.activiti.engine.delegate.TransactionDependentExecutionListener (notify(DelegateExecution, FlowElement, Map, Map)) on the target bean","Use a standard ExecutionListener instead if commit-time semantics are not required","Confirm the expression resolves to the intended bean at runtime"],"exampleFix":"// before\npublic class MyBean implements ExecutionListener {...}\n// used in transaction-dependent listener\n\n// after\npublic class MyBean implements TransactionDependentExecutionListener {\n  @Override public void notify(DelegateExecution e, FlowElement fe, 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.TransactionDependentExecutionListener))\n  throw new IllegalStateException(beanName + \" must implement TransactionDependentExecutionListener\");","typeGuard":"boolean isTxExecListener(Object o) { return o instanceof org.activiti.engine.delegate.TransactionDependentExecutionListener; }","tryCatchPattern":"try {\n  runtimeService.startProcessInstanceByKey(key);\n} catch (ActivitiIllegalArgumentException e) {\n  if (e.getMessage().contains(\"TransactionDependentExecutionListener\")) {\n    logger.error(\"Delegate bean implements wrong interface\", e);\n  }\n}","preventionTips":["Match the interface to the listener kind: plain vs transaction-dependent listeners use different interfaces","Document bean types next to BPMN references","Add integration tests that exercise the listener path before deployment"],"tags":["activiti","execution-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"}