{"record":{"id":"4970a79e46df7772","repo":"flowable/flowable-engine","slug":"classname-does-not-implement-the-cmmntriggera","errorCode":null,"errorMessage":"${className} does not implement the ${CmmnTriggerableActivityBehavior.class} interface","messagePattern":"(.+?) does not implement 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":71,"sourceCode":"        this.fieldExtensions = fieldExtensions;\n    }\n\n    @Override\n    public void execute(DelegatePlanItemInstance planItemInstance) {\n        if (activityBehaviorInstance == null) {\n            activityBehaviorInstance = getCmmnActivityBehavior(className);\n        }\n        activityBehaviorInstance.execute(planItemInstance);\n    }\n\n    @Override\n    public void trigger(DelegatePlanItemInstance planItemInstance) {\n        if (activityBehaviorInstance == null) {\n            activityBehaviorInstance = getCmmnActivityBehavior(className);\n        }\n\n        if (!(activityBehaviorInstance instanceof CmmnTriggerableActivityBehavior)) {\n            throw new FlowableIllegalArgumentException(className + \" does not implement the \"\n                + CmmnTriggerableActivityBehavior.class + \" interface\");\n        }\n\n        ((CmmnTriggerableActivityBehavior) activityBehaviorInstance).trigger(planItemInstance);\n    }\n\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;","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delegate/CmmnClassDelegate.java#L53-L89","documentation":"Flowable's CMMN engine instantiates a custom class-delegate for a plan item and needs to call trigger() on it, which requires the class to implement CmmnTriggerableActivityBehavior. When the configured className instantiates fine but does not implement that interface, Flowable refuses to cast it and throws this FlowableIllegalArgumentException. It exists to give a clear message instead of a ClassCastException deep inside the engine.","triggerScenarios":"A plan item (e.g. a task/human task/mail task custom behavior) is configured with flowable:class pointing to a class that implements CmmnActivityBehavior or nothing relevant, but not CmmnTriggerableActivityBehavior, and the engine calls trigger(DelegatePlanItemInstance) on the delegate (typically when a plan item is triggered, e.g. a repeat or reaction to another plan item completing).","commonSituations":"Developers reuse a non-triggerable behavior class (or a plain JavaDelegate from the BPMN engine) in a CMMN case that later gets triggered; renaming/refactoring a class so it no longer implements the triggerable interface; copying a BPMN listener class into CMMN config.","solutions":["Make the configured class implement CmmnTriggerableActivityBehavior (add trigger(DelegatePlanItemInstance) plus execute).","If triggering is not needed, change the case definition so the plan item is never triggered with this class, or use a delegate that only needs execute.","Check the CMMN model XML: the flowable:class attribute of the task/plan item must reference the fully-qualified triggerable class.","Ensure the classpath resolves the intended class, not a stale/old version without the interface."],"exampleFix":"// before\npublic class MyTaskBehavior implements CmmnActivityBehavior {\n  public void execute(CmmnActivityExecutionContext context) { ... }\n}\n// after\npublic class MyTaskBehavior implements CmmnTriggerableActivityBehavior {\n  public void execute(CmmnActivityExecutionContext context) { ... }\n  public void trigger(DelegatePlanItemInstance planItemInstance) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(className);\nif (!org.flowable.cmmn.api.delegate.CmmnTriggerableActivityBehavior.class.isAssignableFrom(c)) {\n    throw new IllegalStateException(className + \" must implement CmmnTriggerableActivityBehavior\");\n}","typeGuard":"boolean isTriggerable(Object b) { return b instanceof org.flowable.cmmn.api.delegate.CmmnTriggerableActivityBehavior; }","tryCatchPattern":"try {\n    behavior.trigger(planItemInstance);\n} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"does not implement\")) { log.error(\"Bad delegate class: {}\", e.getMessage()); }\n    throw e;\n}","preventionTips":["Add a startup test that instantiates every flowable:class referenced in your CMMN models and asserts its interfaces.","Never reuse BPMN JavaDelegates as CMMN plan item classes.","If the plan item can be triggered, always implement the triggerable interface up front."],"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"}