flowable/flowable-engine · error · de.odysseus.el.tree.impl.el.ELException
Class or class name is missing
Error message
Class or class name is missing
What it means
JuelScriptEngine.importFunctions registers static methods of a class as EL functions. It accepts either a Class object or a class name String in the passed map/argument; if the value is neither (e.g. null or another type) it throws an ELException stating the class or class name is missing.
Solutions
- Pass a Class object (e.g. MyUtils.class) or a fully qualified class name String as the function-import value.
- Check the configured value for typos or missing initialization that left it null.
- Log/inspect the offending value type before calling importFunctions and fail with a clearer message.
- If the class name String is failing due to loadClass, note that failure surfaces as ELException wrapping ActivitiException — fix the classpath instead.
Example fix
// before
functions.put("math", null);
engine.importFunctions(functions);
// after
functions.put("math", java.lang.Math.class);
engine.importFunctions(functions); Defensive patterns
Strategy: type-guard
Validate before calling
Object val = functions.get("math");
if (!(val instanceof Class) && !(val instanceof String)) {
throw new IllegalArgumentException("function import needs Class or class-name String");
} Type guard
boolean isValidFunctionTarget(Object v) {
return v instanceof Class || (v instanceof String && !((String) v).isEmpty());
} Try / catch
try {
engine.importFunctions(functions);
} catch (ELException e) {
throw new ScriptConfigException("bad function import entry", e);
} Prevention
- Always register function imports with Class literals, not reflection results that may be null.
- Log the map contents when configuring scripting function imports.
When it happens
Trigger: Calling JuelScriptEngine.importFunctions with a functions map entry whose value is not a Class and not a String class name (null, Integer, etc.), so neither ReflectUtil.loadClass path nor the Class branch is taken.
Common situations: Custom scripting bindings configured with a wrong type, reflection-based registration where the class constant failed to resolve to null, copying a function-import configuration from another engine that used a different value format.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Class does not implement
- Class or class name is missing
- condition script returns non-Boolean: () for
- condition script returns non-Boolean
- Error evaluating juel script
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/0e99d1e7546410d5.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/scripting/JuelScriptEngine.java:230
return JuelScriptEngine.class.getMethod("importFunctions", new Class[] { ScriptContext.class, String.class, Object.class });
} catch (Exception exp) {
// Will never occur
return null;
}
}
public static void importFunctions(ScriptContext ctx, String namespace, Object obj) {
Class<?> clazz = null;
if (obj instanceof Class) {
clazz = (Class<?>) obj;
} else if (obj instanceof String) {
try {
clazz = ReflectUtil.loadClass((String) obj);
} catch (ActivitiException ae) {
throw new ELException(ae);
}
} else {
throw new ELException("Class or class name is missing");
}
Method[] methods = clazz.getMethods();
for (Method m : methods) {
int mod = m.getModifiers();
if (Modifier.isStatic(mod) && Modifier.isPublic(mod)) {
String name = namespace + ":" + m.getName();
ctx.setAttribute(name, m, ScriptContext.ENGINE_SCOPE);
}
}
}
/**
* Class representing a compiled script using JUEL.
*
* @author Frederik Heremans
*/
private class JuelCompiledScript extends CompiledScript {
View on GitHub (pinned to d6d39ce1c6)