apache/pulsar · error · RuntimeException

Class doesn't have such method

Error message

Class  doesn't have such method

What it means

createInstance() calls theCls.getDeclaredConstructor() for a zero-argument constructor. NoSuchMethodException means no such constructor exists; Pulsar rethrows as RuntimeException("Class X doesn't have such method"). Despite the wording, the actual requirement is a public no-arg constructor.

Source

Thrown at pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java:148

    public static Object createInstance(String userClassName,
                                        ClassLoader classLoader) {
        Class<?> theCls;
        try {
            theCls = Class.forName(userClassName, true, classLoader);
        } catch (ClassNotFoundException | NoClassDefFoundError cnfe) {
            throw new RuntimeException("Class " + userClassName + " must be in class path", cnfe);
        }
        Object result;
        try {
            Constructor<?> meth = theCls.getDeclaredConstructor();
            meth.setAccessible(true);

            result = meth.newInstance();
        } catch (InstantiationException ie) {
            throw new RuntimeException("User class must be concrete", ie);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Class " + userClassName + " doesn't have such method", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Class " + userClassName + " must have a no-arg constructor", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Class " + userClassName + " constructor throws exception", e);
        }
        return result;
    }

    public static ClassLoader loadJar(ClassLoader parent, File[] jars) throws MalformedURLException {
        URL[] urls = new URL[jars.length];
        for (int i = 0; i < jars.length; i++) {
            urls[i] = jars[i].toURI().toURL();
        }
        return new URLClassLoader(urls, parent);
    }

    public static boolean isBlank(String str) {
        int strLen;

View on GitHub (pinned to 820761864e)

Solutions

  1. Add a public no-arg constructor to the function class and move per-instance configuration into the open()/process() methods via FunctionContext/context.
  2. If using Lombok, add @NoArgsConstructor alongside other constructor annotations.
  3. Review the message cause: it may mask a different reflective failure on the same class; check the wrapped NoSuchMethodException stack trace.

Example fix

// before
public MyFunction(String topic) { this.topic = topic; }
// after
public MyFunction() {}
public void initialize(Context ctx) { this.topic = ctx...; }
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(className);
boolean hasNoArgCtor = java.util.Arrays.stream(c.getDeclaredConstructors())
    .anyMatch(k -> k.getParameterCount() == 0);

Type guard

boolean hasNoArgConstructor(String fcn) { try { Class.forName(fcn).getDeclaredConstructor(); return true; } catch (Throwable t) { return false; } }

Try / catch

try { Object f = JavaInstanceMain.createInstance(className, cl); } catch (RuntimeException e) { if (e.getMessage().contains("doesn't have such method")) { System.err.println(className + " needs a public no-arg constructor"); } throw e; }

Prevention

When it happens

Trigger: User function class only has constructors taking arguments (e.g. requires configuration injected), so getDeclaredConstructor() fails; also triggered by similar misuse in the surrounding catch chain.

Common situations: Functions written with constructor-injected dependencies; Lombok @AllArgsConstructor without keeping the default constructor; classes written for frameworks that use DI.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/85c6733ecbb924ac. Report an issue: GitHub.