fe-foundation Module Design Document
1. Background & Motivation
The existing fe-common module has accumulated heavy dependencies over time (Guava, Hadoop,
ANTLR, Alibaba MaxCompute SDK, etc.), making it unsuitable as a lightweight shared library for the
plugin/SPI ecosystem. When SPI plugin authors depend on fe-common, they are forced to pull in
dozens of transitive dependencies that have nothing to do with their plugin logic.
We need a zero-dependency foundation module that sits below fe-common and fe-extension-spi
in the dependency hierarchy, providing only the most essential, general-purpose utilities that any
module — including SPI plugins — can safely depend on.
2. Naming Decision
| Candidate |
Verdict |
fe-foundation |
Chosen. Clear "below-common" semantics. No ambiguity with existing modules. |
fe-base |
Too generic; widely used in other contexts. |
fe-essentials |
Good semantics but verbose. |
fe-primitives |
Implies primitive types; misleading. |
fe-toolkit |
"Toolkit" implies a heavier helper library rather than a minimal foundation layer. |
fe-kernel |
Conflicts with database "kernel" terminology. |
3. Module Positioning
Key principle: fe-foundation has ZERO compile-scope third-party dependencies. Only JDK.
4. Admission Criteria
A class qualifies for fe-foundation if it meets ALL of:
- Zero third-party runtime dependencies — only
java.* imports
- No coupling to Doris business logic — no references to catalog, optimizer, planner, etc.
- General-purpose — useful across multiple modules (SPI plugins, fe-common, fe-core, etc.)
- Stable API — unlikely to change frequently
5. Package Structure
6. Classes Included (First Iteration)
6.1 Property Framework (from fe-core)
| Class |
Original Location |
External Deps |
Description |
ConnectorProperty |
o.a.d.datasource.property |
None |
Runtime annotation for connector config fields |
ConnectorPropertiesUtils |
o.a.d.datasource.property |
None (Guava/commons-lang3 removed) |
Reflection-based KV→Bean binding |
ParamRules |
o.a.d.datasource.property |
None |
Fluent validation DSL with chained rules |
StoragePropertiesException |
o.a.d.datasource.property.storage.exception |
None |
RuntimeException for property errors |
6.2 Type Utilities (from fe-common)
| Class |
Original Location |
External Deps |
Description |
ResultOr<T,E> |
o.a.d.common |
None |
Success-or-error result type |
6.3 Format Utilities (from fe-common)
| Class |
Original Location |
External Deps |
Description |
FormatOptions |
o.a.d.common |
None |
Immutable formatting configuration |
6.4 General Utilities (from fe-core)
| Class |
Original Location |
External Deps |
Description |
BitUtil |
o.a.d.common.util |
None |
log2, power-of-2 rounding |
ByteBufferUtil |
o.a.d.common.util |
None |
Unsigned byte buffer reads |
SerializationUtils |
o.a.d.common.util |
None |
Deep clone via serialization |
PathUtils |
o.a.d.common.util |
None |
URI path comparison with S3 handling |
7. Classes NOT Included (and Why)
| Class |
Reason |
Pair, Triple |
Depend on @SerializedName (Gson) for persistence. Moving would require adding Gson or breaking persistence compatibility. |
Writable, Codec, CountingDataOutputStream, DataInputBuffer, DataOutputBuffer, etc. |
Deeply embedded in the persistence layer (194+ importers for Writable). High-risk migration better done in a separate phase. |
CloudCredential |
Depends on commons-lang3. Could be migrated after trivial refactoring. |
GZIPUtils, EnvUtils |
Depend on commons-io / Guava. Could be migrated after trivial refactoring. |
8. Serialization Safety Analysis
All 10 classes are SAFE to move (package rename):
- None implement
java.io.Serializable (except StoragePropertiesException via Throwable,
but it is never serialized to disk)
- None are registered in
RuntimeTypeAdapterFactory (no class name stored in JSON)
- None have
serialVersionUID
- All are either annotations, static utility classes, or transient runtime objects
- No class name is stored in any editlog, metadata image, or checkpoint
9. Migration Strategy
Phase 1 (This PR): Backward-Compatible Migration
- Create
fe-foundation module with zero dependencies
- Copy classes to new
org.apache.doris.foundation.* packages
- In original locations, replace class bodies with extends/delegation to the foundation class:
- No existing code needs to change import statements
- New code should prefer importing from
org.apache.doris.foundation.*
Phase 2 (Future): Gradually update imports across the codebase
- Update import statements in fe-core to use foundation packages directly
- Deprecate and eventually remove the re-export shims
- Migrate more classes from fe-common (IO utilities, Pair/Triple after decoupling Gson)
10. Build Configuration
11. Dependency Graph After Migration