jd-opensource/joyagent-jdgenie · error · JdbcBizException

Could not load service provider for Catalog factory.

Error message

Could not load service provider for Catalog factory.

What it means

discoverFactories iterates ServiceLoader.load(JdbcCatalogFactory.class, classLoader); if the SPI machinery itself fails (ServiceConfigurationError — e.g., a provider class listed in META-INF/services cannot be instantiated), it logs and rethrows as JdbcBizException('Could not load service provider for Catalog factory.'). Unlike error 16, providers ARE registered but broken/unloadable.

Solutions

  1. Inspect the wrapped ServiceConfigurationError cause — it names the failing provider class and reason.
  2. Fix the META-INF/services entry to match the provider class's actual fully-qualified name.
  3. Add the missing dependency the provider needs at initialization time.
  4. Rebuild/redeploy the jar so service files and implementation classes are consistent.

Example fix

// before (META-INF/services/com.jd.genie.data.jdbc.catalog.JdbcCatalogFactory)
com.jd.genie.data.jdbc.catalog.MySqlCatalogFactory  // class renamed in refactor
// after
com.jd.genie.data.jdbc.catalog.mysql.MySqlJdbcCatalogFactory
Defensive patterns

Strategy: try-catch

Validate before calling

// verify provider class is loadable before iteration
for (String cls : readServiceProviderLines(cl)) {
    try { Class.forName(cls, false, cl); }
    catch (Throwable t) { throw new IllegalStateException("Unloadable SPI provider: " + cls, t); }
}

Try / catch

try {
    JdbcCatalog catalog = JdbcCatalogLoader.load(dialect);
} catch (JdbcBizException e) {
    if (e.getMessage().contains("Could not load service provider")) {
        // inspect e.getCause() (ServiceConfigurationError) for the broken provider class
    } else throw e;
}

Prevention

When it happens

Trigger: A META-INF/services entry names a class that is missing, fails static initialization, or whose constructor throws — ServiceLoader iteration raises ServiceConfigurationError, caught and wrapped by discoverFactories.

Common situations: Partial deployments where the service file exists but the implementation class was relocated/renamed in a refactor; provider class depends on an optional dependency not on the classpath (NoClassDefFoundError during init); shaded jars mangling provider class names.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/00af6db234ef6ec1. Report an issue: GitHub.

Appendix: source

Thrown at genie-backend/src/main/java/com/jd/genie/data/jdbc/catalog/JdbcCatalogLoader.java:51

        }
        if (matchingFactories.size() > 1) {
            throw new JdbcBizException("Multiple jdbc dialect factories can handle");
        }

        return matchingFactories.get(0).createCatalog();
    }


    private static List<JdbcCatalogFactory> discoverFactories(ClassLoader classLoader) {
        try {
            final List<JdbcCatalogFactory> result = new LinkedList<>();
            ServiceLoader.load(JdbcCatalogFactory.class, classLoader)
                    .iterator()
                    .forEachRemaining(result::add);
            return result;
        } catch (ServiceConfigurationError e) {
            log.error("Could not load service provider for Catalog factory.", e);
            throw new JdbcBizException(
                    "Could not load service provider for Catalog factory.", e);
        }
    }
}

View on GitHub (pinned to 2417e0b8b6)