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

  1. Pass a Class object (e.g. MyUtils.class) or a fully qualified class name String as the function-import value.
  2. Check the configured value for typos or missing initialization that left it null.
  3. Log/inspect the offending value type before calling importFunctions and fail with a clearer message.
  4. 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

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


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)