{"record":{"id":"65de3627eb507703","repo":"flowable/flowable-engine","slug":"classname-does-not-implement-the-cmmnactivity","errorCode":null,"errorMessage":"${className} does not implement the ${CmmnActivityBehavior.class} nor the ${PlanItemJavaDelegate.class} interface","messagePattern":"(.+?) does not implement the (.+?) nor the (.+?) interface","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":95,"sourceCode":"\n    protected CmmnActivityBehavior getCmmnActivityBehavior(String className) {\n        Object instance = instantiate(className);\n        applyFieldExtensions(fieldExtensions, instance, false);\n\n        if (instance instanceof PlanItemJavaDelegate) {\n            return new PlanItemJavaDelegateActivityBehavior((PlanItemJavaDelegate) instance);\n\n        } else if (instance instanceof PlanItemFutureJavaDelegate) {\n            return new PlanItemFutureJavaDelegateActivityBehavior((PlanItemFutureJavaDelegate) instance);\n\n        } else if (instance instanceof CmmnTriggerableActivityBehavior) {\n            return (CmmnTriggerableActivityBehavior) instance;\n\n        } else if (instance instanceof CmmnActivityBehavior) {\n            return (CmmnActivityBehavior) instance;\n\n        } else {\n            throw new FlowableIllegalArgumentException(className + \" does not implement the \"\n                    + 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 {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delegate/CmmnClassDelegate.java#L77-L113","documentation":"getCmmnActivityBehavior resolves the class named by flowable:class into a CmmnActivityBehavior. If the instantiated object is neither a CmmnTriggerableActivityBehavior, a CmmnActivityBehavior, nor a PlanItemJavaDelegate, this FlowableIllegalArgumentException is thrown. It validates that plan-item behavior classes conform to the CMMN delegate contracts.","triggerScenarios":"Any CMMN plan item execution or trigger that resolves the class delegate: execute() or trigger() call getCmmnActivityBehavior(className), which calls instantiate(className) and type-checks the result. Triggered when the class implements none of the three accepted interfaces (e.g. it is a plain TaskListener, a BPMN JavaDelegate without PlanItemJavaDelegate, or an unrelated POJO).","commonSituations":"Pointing a CMMN task at a BPMN-style org.flowable.engine.delegate.JavaDelegate without adapting it to PlanItemJavaDelegate; configuring a listener class by copy/paste mistake; typo in the class name resolving to the wrong type in a shared package.","solutions":["Implement CmmnActivityBehavior (or PlanItemJavaDelegate for simple variable-returning logic, or CmmnTriggerableActivityBehavior if trigger support is needed) on the referenced class.","For simple cases, replace the class reference with a delegate expression to a Spring/CDI bean implementing PlanItemJavaDelegate.","Verify the fully-qualified class name in the CMMN XML points to the intended class.","Check for duplicate classes on the classpath shadowing the intended implementation."],"exampleFix":"// before\npublic class MyLogic implements org.flowable.engine.delegate.JavaDelegate {\n  public void execute(DelegateExecution execution) { ... }\n}\n// after\npublic class MyLogic implements org.flowable.cmmn.api.delegate.PlanItemJavaDelegate {\n  public Object execute(DelegatePlanItemInstance planItemInstance) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(className);\nboolean ok = org.flowable.cmmn.api.delegate.CmmnActivityBehavior.class.isAssignableFrom(c)\n    || org.flowable.cmmn.api.delegate.PlanItemJavaDelegate.class.isAssignableFrom(c);\nif (!ok) throw new IllegalStateException(className + \" implements no CMMN behavior interface\");","typeGuard":"boolean isValidCmmnBehavior(Object o) {\n    return o instanceof org.flowable.cmmn.api.delegate.CmmnActivityBehavior\n        || o instanceof org.flowable.cmmn.api.delegate.PlanItemJavaDelegate;\n}","tryCatchPattern":"try {\n    planItemExecution.proceed();\n} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"nor the\")) { log.error(\"Class {} is not a CMMN behavior\", className); }\n    throw e;\n}","preventionTips":["Use PlanItemJavaDelegate for simple logic — it is the CMMN counterpart of JavaDelegate.","Keep BPMN and CMMN delegate packages separate to avoid wrong imports.","Write a model-conformance test validating all flowable:class values at deploy time."],"tags":["java","cmmn","delegate","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"}