{"record":{"id":"3533b96078e585db","repo":"flowable/flowable-engine","slug":"delegate-getclass-getname-doesn-t-impl","errorCode":null,"errorMessage":"\" + delegate.getClass().getName() + \" doesn't implement \" + ExecutionListener.class + \" nor \" + JavaDelegate.class","messagePattern":"\" \\+ delegate\\.getClass\\(\\)\\.getName\\(\\) \\+ \" doesn't implement \" \\+ ExecutionListener\\.class \\+ \" nor \" \\+ JavaDelegate\\.class","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/listener/DelegateExecutionListener.java","lineNumber":46,"sourceCode":" */\npublic class DelegateExecutionListener implements ExecutionListener {\n\n    protected Object delegate;\n\n    public DelegateExecutionListener(Object delegate) {\n        this.delegate = delegate;\n    }\n\n    @Override\n    public void notify(DelegateExecution execution) {\n        if (delegate instanceof ExecutionListener) {\n            CommandContextUtil.getProcessEngineConfiguration().getDelegateInterceptor()\n                    .handleInvocation(new ExecutionListenerInvocation((ExecutionListener) delegate, execution));\n        } else if (delegate instanceof JavaDelegate) {\n            CommandContextUtil.getProcessEngineConfiguration().getDelegateInterceptor()\n                    .handleInvocation(new JavaDelegateInvocation((JavaDelegate) delegate, execution));\n        } else {\n            throw new FlowableIllegalArgumentException(\n                    delegate.getClass().getName() + \" doesn't implement \" + ExecutionListener.class + \" nor \" + JavaDelegate.class);\n        }\n    }\n}\n","sourceCodeStart":28,"sourceCodeEnd":51,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/listener/DelegateExecutionListener.java#L28-L51","documentation":"Thrown as FlowableIllegalArgumentException when a delegate resolved by DelegateExecutionListener.notify implements neither ExecutionListener nor JavaDelegate. A delegateExecutionListener's delegateExpression must resolve to one of these two types so Flowable can wrap it in the corresponding invocation (ExecutionListenerInvocation or JavaDelegateInvocation). Any other object type is rejected at event-dispatch time.","triggerScenarios":"A BPMN element defines flowable:executionListener with flowable:delegateExpression; when the associated event (start/end/take) fires, DelegateExecutionListener.notify resolves the expression and the object fails both instanceof checks.","commonSituations":"Expression pointing at a bean that is neither a listener nor a delegate (e.g. a service class, a String, or null after a refactor); Spring EL resolving to a property/return value rather than the bean itself; migrating configs where the listener class was changed to a non-listener; copy-paste of delegateExpression from an HTTP handler config.","solutions":["Make the target class implement org.flowable.engine.delegate.ExecutionListener (or JavaDelegate).","Verify the delegateExpression EL resolves to the bean itself (e.g. ${myListenerBean}, not ${myBean.someProperty}).","If the resolved object is null, check bean availability/registration in the Spring context.","Add a deployment-time or startup check asserting each referenced listener bean implements ExecutionListener or JavaDelegate."],"exampleFix":"// before\npublic class MyListener { public void react(DelegateExecution e) { ... } }\n\n// after\nimport org.flowable.engine.delegate.ExecutionListener;\npublic class MyListener implements ExecutionListener {\n    public void notify(DelegateExecution execution) { ... }\n}","handlingStrategy":"type-guard","validationCode":"Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, execution);\nif (!(delegate instanceof ExecutionListener) && !(delegate instanceof JavaDelegate)) {\n    throw new IllegalStateException(\"Bean for \" + expression + \" must implement ExecutionListener or JavaDelegate\");\n}","typeGuard":"boolean isValidExecutionListenerDelegate(Object o) {\n    return o instanceof org.flowable.engine.delegate.ExecutionListener\n        || o instanceof org.flowable.engine.delegate.JavaDelegate;\n}","tryCatchPattern":"try {\n    listener.notify(execution);\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"doesn't implement\")) {\n        logger.error(\"executionListener delegateExpression misconfigured: \" + e.getMessage());\n    } else { throw e; }\n}","preventionTips":["Implement ExecutionListener or JavaDelegate on every bean used as a delegateExecutionListener.","Reference beans directly (${beanName}) rather than via property expressions that can return other types.","Check for null resolutions caused by missing Spring bean registration.","Validate listener delegate types during application startup or CI."],"tags":["delegate-expression","execution-listener","type-mismatch","bpmn-config"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}