{"record":{"id":"4f53a0a18808d5c4","repo":"apache/beam","slug":"subclass-of-simplefunction-must-override-apply-method-or","errorCode":null,"errorMessage":"Subclass of SimpleFunction must override 'apply' method or pass a SerializableFunction to the constructor, usually via a lambda or method reference.","messagePattern":"Subclass of SimpleFunction must override 'apply' method or pass a SerializableFunction to the constructor, usually via a lambda or method reference\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/SimpleFunction.java","lineNumber":47,"sourceCode":"@SuppressWarnings({\n  \"nullness\" // TODO(https://github.com/apache/beam/issues/20497)\n})\npublic abstract class SimpleFunction<InputT, OutputT> extends InferableFunction<InputT, OutputT>\n    implements SerializableFunction<InputT, OutputT> {\n\n  private final @Nullable SerializableFunction<InputT, OutputT> fn;\n\n  protected SimpleFunction() {\n    this.fn = null;\n    // A subclass must override apply if using this constructor. Check that via\n    // reflection.\n    try {\n      Method methodThatMustBeOverridden =\n          SimpleFunction.class.getDeclaredMethod(\"apply\", Object.class);\n      Method methodOnSubclass = getClass().getMethod(\"apply\", Object.class);\n\n      if (methodOnSubclass.equals(methodThatMustBeOverridden)) {\n        throw new IllegalStateException(\n            \"Subclass of SimpleFunction must override 'apply' method\"\n                + \" or pass a SerializableFunction to the constructor,\"\n                + \" usually via a lambda or method reference.\");\n      }\n\n    } catch (NoSuchMethodException exc) {\n      throw new RuntimeException(\"Impossible state: missing 'apply' method entirely\", exc);\n    }\n  }\n\n  protected SimpleFunction(SerializableFunction<InputT, OutputT> fn) {\n    this.fn = fn;\n  }\n\n  @Override\n  public OutputT apply(InputT input) {\n    return fn.apply(input);\n  }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/SimpleFunction.java#L29-L65","documentation":"SimpleFunction is a convenience subclass of DoFn that expects the subclass to override the typed 'apply(InputT)' method (or supply a SerializableFunction via constructor). In its constructor, reflection checks whether 'apply' is still the abstract base method; if so, the subclass is useless and Beam throws IllegalStateException.","triggerScenarios":"Declaring an anonymous or named subclass of SimpleFunction without overriding apply, e.g. new SimpleFunction<String, Integer>() {} with no body and no SerializableFunction argument.","commonSituations":"Copy-pasted anonymous class stubs left unimplemented; refactor removed an apply override; IDE-generated anonymous class body left empty; generics erasure confusing the developer into overriding processElement instead of apply.","solutions":["Override the apply method in the subclass","Pass a lambda/method reference to a MapElements.into(...).via(...) instead of subclassing SimpleFunction","Use the SimpleFunction constructor that accepts a SerializableFunction"],"exampleFix":"// before\nMapElements<String, Integer> len = MapElements.via(new SimpleFunction<String, Integer>() {});\n// after\nMapElements<String, Integer> len = MapElements.via(new SimpleFunction<String, Integer>() {\n  @Override\n  public Integer apply(String s) { return s.length(); }\n});\n// or simply:\nMapElements<String, Integer> len = MapElements.into(TypeDescriptors.integers()).via(String::length);","handlingStrategy":"type-guard","validationCode":"// Prefer lambdas: MapElements.into(t).via(MyClass::apply) avoids subclassing entirely","typeGuard":"boolean isUsableSimpleFunction(SimpleFunction<?,?> f) {\n  try { return !SimpleFunction.class.getDeclaredMethod(\"apply\", Object.class).equals(f.getClass().getMethod(\"apply\", Object.class)); }\n  catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":null,"preventionTips":["Prefer MapElements.into(...).via(lambda) over subclassing SimpleFunction","Never leave anonymous SimpleFunction bodies empty","If subclassing, always override apply(InputT), not processElement"],"tags":["java","apache-beam","pipeline-construction","abstract-method"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}