{"record":{"id":"2cbb0e409ae2386f","repo":"flowable/flowable-engine","slug":"delegateclassname-doesn-t-implement-javadelegate","errorCode":null,"errorMessage":"<delegateClassName> doesn't implement JavaDelegate, FutureJavaDelegate nor ActivityBehavior","messagePattern":"<delegateClassName> doesn't implement JavaDelegate, FutureJavaDelegate nor ActivityBehavior","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ClassDelegate.java","lineNumber":283,"sourceCode":"\n        if (activityBehaviorInstance instanceof SubProcessActivityBehavior) {\n            ((SubProcessActivityBehavior) activityBehaviorInstance).completed(execution);\n        } else {\n            throw new FlowableException(\"completed() can only be called on a \" + SubProcessActivityBehavior.class.getName() + \" instance for \" + execution);\n        }\n    }\n\n    protected ActivityBehavior getActivityBehaviorInstance() {\n        Object delegateInstance = instantiateDelegate(className, fieldDeclarations);\n\n        if (delegateInstance instanceof ActivityBehavior) {\n            return determineBehaviour((ActivityBehavior) delegateInstance);\n        } else if (delegateInstance instanceof JavaDelegate) {\n            return determineBehaviour(new ServiceTaskJavaDelegateActivityBehavior((JavaDelegate) delegateInstance, triggerable, skipExpression));\n        } else if (delegateInstance instanceof FutureJavaDelegate) {\n            return determineBehaviour(new ServiceTaskFutureJavaDelegateActivityBehavior((FutureJavaDelegate<?>) delegateInstance, triggerable, skipExpression, mapExceptions));\n        } else {\n            throw new FlowableIllegalArgumentException(delegateInstance.getClass().getName() + \" doesn't implement \" + JavaDelegate.class.getName() + \", \" + FutureJavaDelegate.class.getName() + \" nor \" + ActivityBehavior.class.getName());\n        }\n    }\n\n    // Adds properties to the given delegation instance (eg multi instance) if needed\n    protected ActivityBehavior determineBehaviour(ActivityBehavior delegateInstance) {\n        if (hasMultiInstanceCharacteristics()) {\n            multiInstanceActivityBehavior.setInnerActivityBehavior((AbstractBpmnActivityBehavior) delegateInstance);\n            return multiInstanceActivityBehavior;\n        }\n        return delegateInstance;\n    }\n\n}\n","sourceCodeStart":265,"sourceCodeEnd":297,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ClassDelegate.java#L265-L297","documentation":"ClassDelegate.getActivityBehaviorInstance() instantiates the delegate class and only accepts instances of ActivityBehavior, JavaDelegate, or FutureJavaDelegate, wrapping JavaDelegates in service-task behaviors. Anything else yields a FlowableIllegalArgumentException stating the class implements neither JavaDelegate, FutureJavaDelegate nor ActivityBehavior. This is the central contract check for class-based service task delegates.","triggerScenarios":"A service task (or other behavior-backed element) declares flowable:class='<delegateClassName>' and the class implements none of ActivityBehavior, JavaDelegate (execute(DelegateExecution)), or FutureJavaDelegate; also fired by execute/trigger/completing/completed when the behavior instance is first resolved.","commonSituations":"Pointing flowable:class at an arbitrary helper bean; missing import so the class implements org.activiti.engine.impl.pvm.delegate.ActivityBehavior or wrong package; the class implements only a listener interface; wrong fully qualified name resolving to an unrelated class.","solutions":["Make the class implement org.flowable.engine.delegate.JavaDelegate (execute(DelegateExecution)) — the most common fix for service tasks.","Alternatively implement FutureJavaDelegate or extend a Flowable ActivityBehavior for custom control flow.","Verify the class attribute and imports reference Flowable types, not Activiti ones.","Rebuild and redeploy so the engine loads the corrected class."],"exampleFix":"// before\npublic class MyTask { public void run() { ... } }\n<!-- flowable:class=\"com.acme.MyTask\" -->\n// after\npublic class MyTask implements JavaDelegate {\n    @Override public void execute(DelegateExecution execution) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(serviceTaskClass);\nboolean ok = ActivityBehavior.class.isAssignableFrom(c)\n        || JavaDelegate.class.isAssignableFrom(c)\n        || FutureJavaDelegate.class.isAssignableFrom(c);\nif (!ok) throw new IllegalStateException(\"Service task class must implement JavaDelegate/FutureJavaDelegate/ActivityBehavior\");","typeGuard":"boolean isValidDelegate(Object o) {\n    return o instanceof ActivityBehavior || o instanceof JavaDelegate || o instanceof FutureJavaDelegate;\n}","tryCatchPattern":"try {\n    runtimeService.startProcessInstanceByKey(\"proc\");\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"JavaDelegate\")) { /* fix service task class */ }\n    throw e;\n}","preventionTips":["Default to implementing JavaDelegate for service tasks.","Never point flowable:class at arbitrary beans.","Add an engine test executing every service task path before release."],"tags":["flowable","delegate","java-delegate","type-mismatch"],"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"}