Hydration currently constructs records through Constructor.newInstance. Since #252 the surrounding reflective metadata (parameter arrays, non-null flags, accessibility) is precomputed per constructor, so the reflective call itself is the only remaining reflection on the row mapping hot path. After JIT warmup it costs single-digit nanoseconds per construction; performance is explicitly not the motivation for this issue.
Motivation
- GraalVM native-image: reflective construction requires every entity record to be registered in reflection configuration. Generator-emitted factories work with zero configuration, which would make Storm applications native-image friendly out of the box.
- JPMS encapsulation:
setAccessible(true) requires user modules to opens their model packages to storm.core. A generated factory lives in the user's own module and needs no opens.
Sketch
- The annotation processor and KSP generator already visit every entity and projection; they additionally emit an instantiation factory per record (for example a static
(Object[] args) -> new Owner(...) alongside the metamodel).
- The record mapper consults a factory registry before falling back to reflective construction, so models compiled without the generators keep working unchanged.
- Null diagnostics (the descriptive non-nullable and primitive error messages) must be preserved on the generated path.
Non-goals
- Fusing column decoding into generated code (typed reads straight into constructor parameters). That is a redesign of the mapping pipeline with real complexity, and current measurements show no performance case for it.
Hydration currently constructs records through
Constructor.newInstance. Since #252 the surrounding reflective metadata (parameter arrays, non-null flags, accessibility) is precomputed per constructor, so the reflective call itself is the only remaining reflection on the row mapping hot path. After JIT warmup it costs single-digit nanoseconds per construction; performance is explicitly not the motivation for this issue.Motivation
setAccessible(true)requires user modules toopenstheir model packages tostorm.core. A generated factory lives in the user's own module and needs no opens.Sketch
(Object[] args) -> new Owner(...)alongside the metamodel).Non-goals