Implementation:Apache Paimon FactoryUtil
| Knowledge Sources | |
|---|---|
| Domains | Plugin System, Service Discovery |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
FactoryUtil provides utility methods for discovering and loading Factory implementations using Java's Service Provider Interface.
Description
FactoryUtil is the central component of Paimon's plugin discovery mechanism. It uses Java's ServiceLoader to dynamically discover and instantiate Factory implementations at runtime, enabling a highly extensible architecture without compile-time dependencies.
The class maintains a soft-reference cache of discovered factories per ClassLoader, improving performance by avoiding repeated classpath scanning. The cache uses Caffeine with a maximum size of 100 entries and executes cache operations synchronously to ensure thread safety. Soft references allow the JVM to garbage collect cached entries under memory pressure.
FactoryUtil provides three main discovery patterns: finding a specific factory by identifier and type, discovering all identifiers for a given factory type, and discovering a singleton factory when only one implementation should exist. Each pattern includes comprehensive error handling with clear messages when factories are missing, ambiguous, or multiple implementations exist when only one is expected.
The utility gracefully handles NoClassDefFoundError exceptions during service loading, which commonly occur when optional dependencies are not present on the classpath. This allows Paimon to support many plugin types without requiring all dependencies to be available.
Usage
Use FactoryUtil when you need to discover and instantiate plugin implementations at runtime. This is typically done in framework code that needs to create instances of user-configured components like catalogs, file formats, or connectors. The utility handles all aspects of SPI discovery, validation, and error reporting.
Code Reference
Source Location
- Repository: Apache_Paimon
- File: paimon-api/src/main/java/org/apache/paimon/factories/FactoryUtil.java
Signature
public class FactoryUtil {
private static final Cache<ClassLoader, List<Factory>> FACTORIES;
public static <T extends Factory> T discoverFactory(
ClassLoader classLoader,
Class<T> factoryClass,
String identifier)
public static <T extends Factory> List<String> discoverIdentifiers(
ClassLoader classLoader,
Class<T> factoryClass)
public static <T> List<T> discoverFactories(
ClassLoader classLoader,
Class<T> klass)
public static <T> Optional<T> discoverSingletonFactory(
ClassLoader classLoader,
Class<T> klass)
}
Import
import org.apache.paimon.factories.FactoryUtil;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| classLoader | ClassLoader | Yes | ClassLoader to use for SPI discovery |
| factoryClass | Class<T> | Yes | The factory interface class to search for |
| identifier | String | Yes | The factory identifier to match (for discoverFactory) |
| klass | Class<T> | Yes | The class to discover instances of |
Outputs
| Name | Type | Description |
|---|---|---|
| factory | T extends Factory | The discovered factory instance matching the criteria |
| identifiers | List<String> | List of all available factory identifiers for the given type |
| factories | List<T> | All discovered instances of the given class |
| singletonFactory | Optional<T> | Single factory instance if exactly one exists |
Usage Examples
// Discover a specific catalog factory by identifier
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
CatalogFactory catalogFactory = FactoryUtil.discoverFactory(
classLoader,
CatalogFactory.class,
"hive"
);
// Discover all available catalog types
List<String> catalogTypes = FactoryUtil.discoverIdentifiers(
classLoader,
CatalogFactory.class
);
System.out.println("Available catalogs: " + catalogTypes);
// Output: [filesystem, hive, jdbc]
// Discover all factories of a given type
List<FileFormatFactory> formatFactories = FactoryUtil.discoverFactories(
classLoader,
FileFormatFactory.class
);
// Discover singleton factory (when only one should exist)
Optional<MetricsReporter> reporter = FactoryUtil.discoverSingletonFactory(
classLoader,
MetricsReporter.class
);
// Using discovered factory to create instances
String catalogType = options.get("metastore");
CatalogFactory factory = FactoryUtil.discoverFactory(
classLoader,
CatalogFactory.class,
catalogType
);
Catalog catalog = factory.createCatalog(catalogContext);
// Error handling - factory not found
try {
FactoryUtil.discoverFactory(
classLoader,
CatalogFactory.class,
"nonexistent"
);
} catch (FactoryException e) {
// Exception message lists available factory identifiers
System.err.println(e.getMessage());
}
// Error handling - multiple factories found
try {
FactoryUtil.discoverSingletonFactory(
classLoader,
MetricsReporter.class
);
} catch (FactoryException e) {
// Exception message lists ambiguous factory classes
System.err.println(e.getMessage());
}
// Using with custom classloader
ClassLoader pluginClassLoader = new URLClassLoader(pluginJars);
CustomFactory factory = FactoryUtil.discoverFactory(
pluginClassLoader,
CustomFactory.class,
"custom-implementation"
);