{"record":{"id":"335ac4440dc775e5","repo":"Tencent/APIJSON","slug":"lang-apijsonfu","errorCode":null,"errorMessage":"找不到脚本语言 \" + lang + \" 对应的执行引擎！请先依赖相关库并在后端 APIJSONFunctionParser<T, M, L> 中注册！","messagePattern":"找不到脚本语言 \" \\+ lang \\+ \" 对应的执行引擎！请先依赖相关库并在后端 APIJSONFunctionParser<T, M, L> 中注册！","errorType":"exception","errorClass":"ClassNotFoundException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java","lineNumber":424,"sourceCode":"        }\n\n\t\tFunctionBean fb = parseFunction(function, current, false, containRaw);\n\n\t\tMap<String, Object> row = FUNCTION_MAP.get(fb.getMethod()); //FIXME  fb.getSchema() + \".\" + fb.getMethod()\n\t\tif (row == null) {\n\t\t\tthrow new UnsupportedOperationException(\"不允许调用远程函数 \" + fb.getMethod() + \" !\");\n\t\t}\n\n        String language = (String) row.get(\"language\");\n        String lang = \"java\".equalsIgnoreCase(language) ? null : language;\n\n        if (ENABLE_SCRIPT_FUNCTION == false && lang != null) {\n            throw new UnsupportedOperationException(\"language = \" + language + \" 不合法！AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION\" +\n                    \" == false 时不支持远程函数中的脚本形式！如需支持则设置 AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION = true ！\");\n        }\n\n\t\tif (lang != null && SCRIPT_EXECUTOR_MAP.get(lang) == null) {\n\t\t\tthrow new ClassNotFoundException(\"找不到脚本语言 \" + lang + \" 对应的执行引擎！请先依赖相关库并在后端 APIJSONFunctionParser<T, M, L> 中注册！\");\n\t\t}\n\n\t\tint version = row.get(\"version\") != null ? Integer.parseInt(row.get(\"version\").toString()) : 0;\n\t\tif (parser.getVersion() < version) {\n\t\t\tthrow new UnsupportedOperationException(\"不允许 version = \" + parser.getVersion() + \" 的请求调用远程函数 \" + fb.getMethod() + \" ! 必须满足 version >= \" + version + \" !\");\n\t\t}\n\t\tString tag = (String) row.get(\"tag\");  // TODO 改为 tags，类似 methods 支持多个 tag。或者干脆不要？因为目前非开放请求全都只能后端指定\n\t\tif (tag != null && tag.equals(parser.getTag()) == false) {\n\t\t\tthrow new UnsupportedOperationException(\"不允许 tag = \" + parser.getTag() + \" 的请求调用远程函数 \" + fb.getMethod() + \" ! 必须满足 tag = \" + tag + \" !\");\n\t\t}\n\t\tString[] methods = StringUtil.split((String) row.get(\"methods\"));\n\t\tList<String> ml = methods == null || methods.length <= 0 ? null : Arrays.asList(methods);\n\t\tif (ml != null && ml.contains(parser.getMethod().toString()) == false) {\n\t\t\tthrow new UnsupportedOperationException(\"不允许 method = \" + parser.getMethod() + \" 的请求调用远程函数 \" + fb.getMethod() + \" ! 必须满足 method 在 \" + Arrays.toString(methods) + \"内 !\");\n\t\t}\n\n\t\ttry {\n            return invoke(parser, fb.getMethod(), fb.getTypes(), fb.getValues(), (String) row.get(\"returnType\"), current, SCRIPT_EXECUTOR_MAP.get(lang));","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java#L406-L442","documentation":"The Function row declares a script language, script functions are enabled, but no ScriptExecutor for that language was registered in SCRIPT_EXECUTOR_MAP. APIJSON throws ClassNotFoundException telling you to add the language's library dependency and register its executor in the backend's APIJSONFunctionParser subclass.","triggerScenarios":"Function row language='python' (for example) and no putScriptExecutor('python', ...) call exists; or the executor registration code lives in a demo class that was not ported to the real backend.","commonSituations":"Migrating from the APIJSON demo project but omitting the executor registration init; upgrading removed an optional script-engine dependency (e.g. GraalJS) from the classpath.","solutions":["Add the script engine dependency (e.g. org.graalvm.js:js) to the backend build.","Register an executor at startup: AbstractFunctionParser.putScriptExecutor(\"javascript\", new JavaScriptExecutor()).","Or change the Function row's language to 'java' and implement it as a Java remote function.","Verify the language string matches exactly (case) what you registered."],"exampleFix":"// before: language='javascript' row, no executor\n\n// after\nstatic {\n    AbstractFunctionParser.putScriptExecutor(\"javascript\", new JavaScriptExecutor());\n}","handlingStrategy":"validation","validationCode":"String lang = (String) functionRow.get(\"language\");\nif (lang != null && !\"java\".equalsIgnoreCase(lang)\n        && AbstractFunctionParser.SCRIPT_EXECUTOR_MAP.get(\"java\".equalsIgnoreCase(lang) ? null : lang) == null) {\n    // missing executor: register one or change the row language\n}","typeGuard":null,"tryCatchPattern":"try { parser.invoke(fn, current); } catch (ClassNotFoundException e) { if (e.getMessage().contains(\"执行引擎\")) { /* register ScriptExecutor + dependency */ } throw e; }","preventionTips":["Register all script executors in the same startup init block, keyed exactly to the language strings used in Function rows.","Pin script engine dependencies in the build file and verify them in a startup self-test.","Keep a checklist mapping language string -> dependency -> executor class."],"tags":["apijson","scripting","dependency","registration"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}