{"record":{"id":"5c3447623dcd2c45","repo":"flowable/flowable-engine","slug":"delegateinstance-getclass-getname-doesn-t-i-5c3447","errorCode":null,"errorMessage":"${delegateInstance.getClass().getName()} doesn't implement ${TaskListener.class}","messagePattern":"(.+?) doesn't implement (.+?)","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delegate/CmmnClassDelegate.java","lineNumber":114,"sourceCode":"                    + CmmnActivityBehavior.class + \" nor the \" + PlanItemJavaDelegate.class + \" interface\");\n\n        }\n    }\n\n    @Override\n    public void notify(DelegateTask delegateTask) {\n        TaskListener taskListenerInstance = getTaskListenerInstance(delegateTask);\n        taskListenerInstance.notify(delegateTask);\n    }\n\n    protected TaskListener getTaskListenerInstance(DelegateTask delegateTask) {\n        Object delegateInstance = instantiate(className);\n        applyFieldExtensions(fieldExtensions, delegateInstance, false);\n\n        if (delegateInstance instanceof TaskListener) {\n            return (TaskListener) delegateInstance;\n        } else {\n            throw new FlowableIllegalArgumentException(delegateInstance.getClass().getName() + \" doesn't implement \" + TaskListener.class);\n        }\n    }\n\n    @Override\n    public void stateChanged(DelegatePlanItemInstance planItemInstance, String oldState, String newState) {\n        PlanItemInstanceLifecycleListener planItemLifeCycleListenerInstance = getPlanItemLifeCycleListenerInstance();\n        planItemLifeCycleListenerInstance.stateChanged(planItemInstance, oldState, newState);\n    }\n\n    @Override\n    public void stateChanged(CaseInstance caseInstance, String oldState, String newState) {\n        CaseInstanceLifecycleListener caseLifeCycleListenerInstance = getCaseLifeCycleListenerInstance();\n        caseLifeCycleListenerInstance.stateChanged(caseInstance, oldState, newState);\n    }\n\n    protected PlanItemInstanceLifecycleListener getPlanItemLifeCycleListenerInstance() {\n        Object delegateInstance = instantiate(className);\n        applyFieldExtensions(fieldExtensions, delegateInstance, false);","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delegate/CmmnClassDelegate.java#L96-L132","documentation":"When a CMMN case element declares a task listener via flowable:class, CmmnClassDelegate.getTaskListenerInstance instantiates the class, applies field extensions, and requires it to implement the TaskListener interface. If it does not, this FlowableIllegalArgumentException is thrown with the actual class name and the missing interface.","triggerScenarios":"A plan item (typically human task) declares <flowable:task-listener flowable:class=\"...\"/>, and the listener is first requested via taskListenerInstance(); the instantiated class does not implement Cmmn TaskListener.","commonSituations":"Using the BPMN engine TaskListener (org.flowable.engine.delegate.TaskListener) instead of the CMMN one; implementing the wrong listener type (lifecycle listener) in the class attribute; after a Flowable version migration the TaskListener package changed.","solutions":["Make the class implement org.flowable.task.api.TaskListener (the interface referenced in the message) and add notify(DelegateTask).","Check imports: use the TaskListener type shown in the error message, not a similarly named one from another module.","If you intended a plan-item lifecycle listener or variable aggregator, move the class to the corresponding element/attribute instead of a task listener.","Rebuild/redeploy so the deployed class actually implements the interface."],"exampleFix":"// before\nimport org.flowable.engine.delegate.TaskListener;\npublic class MyListener implements TaskListener { ... }\n// after\nimport org.flowable.task.api.TaskListener;\npublic class MyListener implements TaskListener {\n  public void notify(DelegateTask delegateTask) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(className);\nif (!org.flowable.task.api.TaskListener.class.isAssignableFrom(c)) {\n    throw new IllegalStateException(className + \" must implement TaskListener\");\n}","typeGuard":"boolean isTaskListener(Object o) { return o instanceof org.flowable.task.api.TaskListener; }","tryCatchPattern":"try {\n    taskListener.notify(delegateTask);\n} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"doesn't implement\")) { log.error(\"Not a TaskListener: {}\", e.getMessage()); }\n    throw e;\n}","preventionTips":["Import TaskListener from the package shown in the error message — engine modules have similarly named interfaces.","Add a unit test asserting each configured listener class implements TaskListener.","After Flowable version upgrades, recheck listener imports."],"tags":["java","cmmn","task-listener","flowable"],"backgroundTag":"type-mismatch","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"}