ID |
|
|---|---|
Status |
Backlog |
Bucket |
cleanup |
Priority |
7 |
Theme |
legacy-migration |
Short class-name resolution for @service and @externalField (legacy parity)
Motivation
ServiceCatalog.reflectServiceMethod currently calls Class.forName(className) directly, forcing an FQN. Existing schemas carry short class names like className: "PersonService" and rely on the legacy Mojo’s externalReferenceImports list to find them. Without short-name resolution, every legacy schema has to be migrated to FQNs at the same time as it migrates to the rewrite, which is unnecessary friction.
Carved out of the original R31 spec, where it was bundled under "Catalog + classification" but is logically independent of the typed-context-value registry. Also benefits computed-field-with-reference.md (R48), since @externalField’s new `reference: { className: "…" } argument has the same FQN-only constraint today.
Design
Port the lookup from ExternalReferences.getClassFrom (graphitron-codegen-parent/graphitron-java-codegen/src/main/java/no/sikt/graphitron/configuration/externalreferences/ExternalReferences.java:52-85):
-
If the name resolves as-is via
Class.forName(name), use it. -
Otherwise, prepend each entry from a configured
externalReferenceImportslist (Mojo parameter) and load the unique match. -
Reject zero-match and multi-match cases with a classification error.
Apply the same lookup at every consumer:
-
ServiceCatalog.reflectServiceMethod(@service) -
ServiceCatalog.reflectExternalField(@externalField, when R48 ships) -
ServiceCatalog.reflectTableMethod(@tableMethod) -
Any other
Class.forNamesite that loads a developer-supplied class name from a directive argument.
A single helper ExternalClassResolver.resolve(String name) lives next to ServiceCatalog; the Mojo wires the externalReferenceImports list into it at generator startup.
Implementation
Configuration (Mojo)
-
<externalReferenceImports>Mojo parameter (string list of package prefixes; mirrors the legacy plugin’s same-named parameter).
Generator
-
New
ExternalClassResolverhelper, package-private to the classification layer. -
Update each
Class.forNamecall site listed above to delegate to the resolver. -
Classification errors for zero-match and multi-match cases include the searched prefixes for diagnostics.
Tests
-
Unit (L1) ;
ExternalClassResolverTest: FQN resolves directly; short name resolves through prefixes; zero-match rejects with prefixes listed; multi-match rejects with all matches listed. -
Classification (L2) ;
ServiceCatalogTest: extend at least onereflectServiceMethod_*case to assert short-name resolution succeeds with a prefix configured. -
Pipeline (L4) ; fixture-side: at least one schema using a short
classNamefor@serviceand at least one for@externalField(when R48 is in flight).
Open questions
-
Naming of the Mojo parameter.
<externalReferenceImports>matches the legacy plugin and minimises migration friction. Alternative would be a more explicit<classNameSearchPrefixes>but matters less than parity. -
Resolver caching. Resolution runs once per directive site at generate time; caching the lookup is a micro-optimisation. Skip until profiling shows it.
Roadmap entries (siblings / dependencies)
-
Sibling slice of
typed-context-value-registry.md(R45) andservice-multi-tenant-fanout.md(R46). All three carved out of the original R31 spec. -
Benefits
computed-field-with-reference.md(R48): the newreference: { className: … }argument should accept short names once this lands.