{"record":{"id":"c91cb5b094664c07","repo":"apache/shenyu","slug":"if-the-prematch-method-was-implemented-the-preparse-method","errorCode":null,"errorMessage":"If the preMatch method was implemented ,the preParse method should be implemented.","messagePattern":"If the preMatch method was implemented ,the preParse method should be implemented\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/AbstractApiRegistrar.java","lineNumber":51,"sourceCode":"\n    /**\n     * Determines whether the apiBean can be registered in advance.\n     *\n     * @param apiBean apiBean to be registered\n     * @return true or false\n     */\n    protected Boolean preMatch(final ApiBean apiBean) {\n        return false;\n    }\n\n    /**\n     * Parses the apiBean as a registrable object.\n     *\n     * @param apiBean apiBean to be parsed\n     * @return registrable object\n     */\n    protected D preParse(final ApiBean apiBean) {\n        throw new UnsupportedOperationException(\"If the preMatch method was implemented ,the preParse method should be implemented.\");\n    }\n\n    /**\n     * Determines whether apiDefinitions of apiBean can be filtered.\n     *\n     * @param apiBean apiBean to be registered\n     * @return true or false\n     */\n    protected abstract Boolean match(ApiBean apiBean);\n\n    /**\n     * Determines whether the apiDefinition can be registered.\n     *\n     * @param apiDefinition apiDefinition to be registered\n     * @return true or false\n     */\n    protected abstract Boolean match(ApiBean.ApiDefinition apiDefinition);\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/AbstractApiRegistrar.java#L33-L69","documentation":"AbstractApiRegistrar lets subclasses override preMatch to filter APIs before parsing; the default preParse hook throws UnsupportedOperationException as a contract guard: if a subclass (or its caller path) relies on pre-parsing but only preMatch was overridden, the framework deliberately fails fast instead of silently mis-registering APIs.","triggerScenarios":"A custom ApiRegistrar subclass overrides preMatch (or invokes the preParse contract) but does not override preParse, and the generic register() flow reaches preParse(apiBean) on an apiBean whose definitions cannot be parsed by the base implementation.","commonSituations":"Writing a custom client registrar (e.g. for a new framework) and implementing only half of the parse/match contract; upgrading Shenyu where a base class previously handled parsing internally.","solutions":["Override preParse(ApiBean) in your registrar subclass and return the registrable DTO built from the apiBean.","Alternatively remove your preMatch override if you did not intend custom filtering, letting the default pipeline handle parse+match.","Check the sibling registrar implementations (e.g. SpringMvcApiRegistrar) for the expected preParse pattern and mirror it."],"exampleFix":"// before\n@Override\nprotected boolean preMatch(final ApiBean apiBean) {\n    return super.preMatch(apiBean);\n}\n// after\n@Override\nprotected boolean preMatch(final ApiBean apiBean) {\n    return super.preMatch(apiBean);\n}\n\n@Override\nprotected D preParse(final ApiBean apiBean) {\n    return buildApiDefinition(apiBean);\n}","handlingStrategy":"type-guard","validationCode":"// before registering, assert the contract\nif (registrarOverridesPreMatch(registrar) && !registrarOverridesPreParse(registrar)) {\n    throw new IllegalStateException(\"registrar must implement preParse alongside preMatch\");\n}","typeGuard":"// reflection guard\nboolean overridesPreParse(AbstractApiRegistrar<?> r) {\n    try {\n        return !AbstractApiRegistrar.class\n            .getDeclaredMethod(\"preParse\", ApiBean.class)\n            .equals(r.getClass().getDeclaredMethod(\"preParse\", ApiBean.class));\n    } catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    registrar.register(apiBean);\n} catch (UnsupportedOperationException e) {\n    LOGGER.error(\"registrar parse contract violated: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["When overriding preMatch, always override preParse in the same subclass.","Mirror an existing registrar implementation when writing new ones.","Add a unit test that exercises register() on your registrar."],"tags":["spi","extension","client-registration"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}