This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/juneau.git
commit d8e855681b0444b8cb6a6ba783a1e67bcbbe687e Author: James Bognar <[email protected]> AuthorDate: Fri May 8 10:30:10 2026 -0400 refactor(inject): TODO-15 phase-3 batch 3 — drop vestigial casts, migrate transient stores Two complementary cleanups in `RestContext.java` and `RestOpContext.java`. Build + unit tests + jetty-ftest verified green. (1) Vestigial `(BasicBeanStore) bs` casts dropped — 16 in `RestContext` (lines 494, 515, 584, 676, 753, 768, 914, 937, 957, 987, 1008, 1029, 1064, 1110, 1125) and 1 in `RestOpContext` (line 437). Each was a leftover from before the cascade-builder migration widened the utility-class `create(...)` factories (`FileFinder`, `EncoderSet`, `MethodExecStore`, `ParserSet`, `SerializerSet`, `ThrownStore`, `RestOperations`, `RestChildren`, `ResponseProcessorList`, `RestOpArgList`) to accept `WritableBeanStore`, and before `BeanCreator.of(Class, BeanStore)` was added. The casts were no-ops on the legacy `BasicBeanStore` instance — and they would have started failing once any caller passed a `BasicBeanStore2` through. Drop now to unblock that next step. (2) Five transient internal-bean-store sites migrated from `BasicBeanStore.of((BasicBeanStore) beanStore())` to `new BasicBeanStore2(beanStore())`: * `RestOpContext.java:216` — `beanContext` lambda * `RestOpContext.java:546` — `jsonSchemaGenerator` lambda * `RestOpContext.java:664` — `partParser` lambda * `RestOpContext.java:680` — `partSerializer` lambda * `RestContext.java:2670` — `findRestOperationArgs` Each site builds a one-shot child store, adds 2 beans, and calls `createBeanFromMethod(...)` for `@RestInject` discovery. The result never escapes the method, so flipping the implementation is purely internal — no field or public-API changes. NOT migrated (see TODO-15 §"Residual casts in `RestContext` / `RestOpContext`" item 4 for the full reasoning): * `RestContext.java:348` — `BasicBeanStore.create().overridingParent(...).type(...).impl(...)` — fluent Builder chain needs an equivalent on the v2 side first. * `RestContext.java:1206` — per-resource store exposed via public `RestContext.getBeanStore()`; `RestSession.java:240` and `VarResolver.java:260` still downcast that result to legacy `BasicBeanStore` to call the legacy `BasicBeanStore.of(...)` static. Migrating them requires field/return-type widening or porting `of(...)` to v2. * `RestOpContext.java:1097` — registers the bean store under `BasicBeanStore.class` so user-facing `@RestPostCall void hook(BasicBeanStore bs)` parameter resolution keeps working. Cannot migrate without breaking that user contract until the legacy class is removed in Phase 4. Net effect: 16 vestigial casts gone, 5 transient stores on v2. The remaining 4 legacy-API sites in `RestContext`/`RestOpContext`/`RestSession`/`VarResolver` are documented and gated by Phase 4 cutover. TODO-15 plan updated with batch-3 entry and revised residual table. Co-authored-by: Cursor <[email protected]> --- .../java/org/apache/juneau/rest/RestContext.java | 39 +++++++++++++--------- .../java/org/apache/juneau/rest/RestOpContext.java | 11 +++--- todo/TODO-15-replace-basicbeanstore-with-v2.md | 23 ++++++++----- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java index c6fb104835..698777119f 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java @@ -17,6 +17,7 @@ package org.apache.juneau.rest; import org.apache.juneau.commons.http.MediaType; +import org.apache.juneau.commons.inject.BasicBeanStore2; import org.apache.juneau.commons.inject.WritableBeanStore; import static jakarta.servlet.http.HttpServletResponse.*; @@ -490,7 +491,7 @@ public class RestContext extends Context { RequestSwaggerVar.class, SerializedRequestAttrVar.class, ServletInitParamVar.class, SwaggerVar.class, UrlVar.class, UrlEncodeVar.class, HtmlWidgetVar.class ).addDefault()) - .bean(FileFinder.class, FileFinder.create((BasicBeanStore) bs).cp(resourceClass(), null, true).build()) + .bean(FileFinder.class, FileFinder.create(bs).cp(resourceClass(), null, true).build()) .build() ); bs.createBeanFromMethod(VarResolver.class, resource().get(), x -> isRestInjectMethod(x, PROP_bootstrapVarResolver)).ifPresent(v::set); @@ -511,7 +512,7 @@ public class RestContext extends Context { // bean store's entries deque and are returned by bs.getBean(CallLogger.class) before falling // through to this memoizer's default supplier (which is what the @Rest(callLogger) chain // produces). The memoizer therefore only needs to produce the framework default. - var creator = BeanCreator.of(CallLogger.class, (BasicBeanStore) bs).type(BasicCallLogger.class); + var creator = BeanCreator.of(CallLogger.class, bs).type(BasicCallLogger.class); bs.getBeanType(CallLogger.class).ifPresent(creator::type); // @Rest(callLogger=X) — most-derived non-Void wins. // getRestAnnotationsForProperty(...) yields parent-to-child order (rstream reversal); reduce-last @@ -580,7 +581,7 @@ public class RestContext extends Context { bs.addBean(Enablement.class, resolvedDebugDefault); else if (bs.getBean(Enablement.class).isEmpty()) bs.addBean(Enablement.class, isDebug() ? Enablement.ALWAYS : Enablement.NEVER); - var creator = BeanCreator.of(DebugEnablement.class, (BasicBeanStore) bs).type(BasicDebugEnablement.class); + var creator = BeanCreator.of(DebugEnablement.class, bs).type(BasicDebugEnablement.class); bs.getBeanType(DebugEnablement.class).ifPresent(creator::type); // @Rest(debugEnablement=X) — most-derived non-Void wins. See callLogger for the reduce-last rationale. getRestAnnotationsForProperty(PROPERTY_debugEnablement) @@ -672,7 +673,7 @@ public class RestContext extends Context { */ private final Memoizer<EncoderSet.Builder> encodersBuilder = memoizer(() -> { var bs = beanStore(); - var v = Value.of(EncoderSet.create((BasicBeanStore) bs)); + var v = Value.of(EncoderSet.create(bs)); getRestAnnotationsForProperty(PROPERTY_encoders).forEach(ai -> v.get().add(ai.inner().encoders())); bs.createBeanFromMethod(EncoderSet.class, resource().get(), RestContext::isRestInjectMethod, v.get()).ifPresent(x -> v.get().impl(x)); return v.get(); @@ -749,7 +750,7 @@ public class RestContext extends Context { */ private final Memoizer<MethodExecStore> methodExecStore = memoizer(() -> { var bs = beanStore(); - var b = MethodExecStore.create((BasicBeanStore) bs).thrownStoreOnce(getThrownStore()); + var b = MethodExecStore.create(bs).thrownStoreOnce(getThrownStore()); bs.createBeanFromMethod(MethodExecStore.class, resource().get(), RestContext::isRestInjectMethod, b).ifPresent(b::impl); return b.build(); }); @@ -764,7 +765,7 @@ public class RestContext extends Context { */ private final Memoizer<ParserSet.Builder> parsersBuilder = memoizer(() -> { var bs = beanStore(); - var v = Value.of(ParserSet.create((BasicBeanStore) bs)); + var v = Value.of(ParserSet.create(bs)); getRestAnnotationsForProperty(PROPERTY_parsers).forEach(ai -> v.get().add(ai.inner().parsers())); bs.createBeanFromMethod(ParserSet.class, resource().get(), RestContext::isRestInjectMethod, v.get()).ifPresent(x -> v.get().impl(x)); return v.get(); @@ -910,7 +911,7 @@ public class RestContext extends Context { // DefaultConfig contributes the framework defaults at the top of the chain; resource-class entries append. // ResponseProcessorList.Builder.add(...) uses addAll (append) — final order: [DefaultConfig, parent, child]. var bs = beanStore(); - var v = Value.of(ResponseProcessorList.create((BasicBeanStore) bs)); + var v = Value.of(ResponseProcessorList.create(bs)); getRestAnnotationsForProperty(PROPERTY_responseProcessors) .forEach(ai -> v.get().add(ai.inner().responseProcessors())); // Bean-store override REPLACES the entire annotation-derived list. @@ -933,7 +934,7 @@ public class RestContext extends Context { // RestOpArgList.Builder.add(...) uses prependAll — applying per-annotation in chain order yields // final order: [child, parent, DefaultConfig], matching the legacy apply-pass behavior. var bs = beanStore(); - var v = Value.of(RestOpArgList.create((BasicBeanStore) bs)); + var v = Value.of(RestOpArgList.create(bs)); getRestAnnotationsForProperty(PROPERTY_restOpArgs) .forEach(ai -> v.get().add(ai.inner().restOpArgs())); // Bean-store override REPLACES the entire annotation-derived list. @@ -953,7 +954,7 @@ public class RestContext extends Context { */ private final Memoizer<SerializerSet.Builder> serializersBuilder = memoizer(() -> { var bs = beanStore(); - var v = Value.of(SerializerSet.create((BasicBeanStore) bs)); + var v = Value.of(SerializerSet.create(bs)); getRestAnnotationsForProperty(PROPERTY_serializers).forEach(ai -> v.get().add(ai.inner().serializers())); bs.createBeanFromMethod(SerializerSet.class, resource().get(), RestContext::isRestInjectMethod, v.get()).ifPresent(x -> v.get().impl(x)); return v.get(); @@ -983,7 +984,7 @@ public class RestContext extends Context { */ private final Memoizer<StaticFiles> staticFiles = memoizer(() -> { var bs = beanStore(); - var creator = BeanCreator.of(StaticFiles.class, (BasicBeanStore) bs).type(BasicStaticFiles.class); + var creator = BeanCreator.of(StaticFiles.class, bs).type(BasicStaticFiles.class); bs.getBeanType(StaticFiles.class).ifPresent(creator::type); // @Rest(staticFiles=X) — most-derived non-Void wins. See callLogger for the reduce-last rationale. getRestAnnotationsForProperty(PROPERTY_staticFiles) @@ -1004,7 +1005,7 @@ public class RestContext extends Context { */ private final Memoizer<SwaggerProvider> swaggerProvider = memoizer(() -> { var bs = beanStore(); - var creator = BeanCreator.of(SwaggerProvider.class, (BasicBeanStore) bs).type(BasicSwaggerProvider.class); + var creator = BeanCreator.of(SwaggerProvider.class, bs).type(BasicSwaggerProvider.class); bs.getBeanType(SwaggerProvider.class).ifPresent(creator::type); // @Rest(swaggerProvider=X) — most-derived non-Void wins. See callLogger for the reduce-last rationale. getRestAnnotationsForProperty(PROPERTY_swaggerProvider) @@ -1025,7 +1026,7 @@ public class RestContext extends Context { */ private final Memoizer<ThrownStore> thrownStore = memoizer(() -> { var bs = beanStore(); - var b = ThrownStore.create((BasicBeanStore) bs).impl(parentContext() == null ? null : parentContext().getThrownStore()); + var b = ThrownStore.create(bs).impl(parentContext() == null ? null : parentContext().getThrownStore()); bs.createBeanFromMethod(ThrownStore.class, resource().get(), RestContext::isRestInjectMethod, b).ifPresent(b::impl); return b.build(); }); @@ -1060,7 +1061,7 @@ public class RestContext extends Context { private final Memoizer<RestOperations> restOperations = memoizer(() -> safe(() -> { initializeFrameworkBeansForRestOps(); var bs = beanStore(); - var v = Value.of(RestOperations.create((BasicBeanStore) bs)); + var v = Value.of(RestOperations.create(bs)); var ap = getBeanContext().getAnnotationProvider(); var rci = ClassInfo.of(resource().get()); for (var mi : rci.getPublicMethods()) { @@ -1106,7 +1107,7 @@ public class RestContext extends Context { private final Memoizer<RestChildren> restChildren = memoizer(() -> safe(() -> { var bs = beanStore(); var servletConfig = bs.getBean(ServletConfig.class).orElse(null); - var v = Value.of(RestChildren.create((BasicBeanStore) bs).type(RestChildren.class)); + var v = Value.of(RestChildren.create(bs).type(RestChildren.class)); // Collect child classes from @Rest(children) on the annotation chain (parent-to-child order). // Deduplicate so the same child class registered on both a parent and child annotation @@ -1121,7 +1122,7 @@ public class RestContext extends Context { if (bs.getBean(rc2).isPresent()) { so = () -> bs.getBean(rc2).get(); } else { - Object o2 = BeanCreator.of(rc2, (BasicBeanStore) bs).run(); + Object o2 = BeanCreator.of(rc2, bs).run(); so = () -> o2; } var cc = new RestContext(new Args(rc2, this, servletConfig, so, "", null)); @@ -1194,6 +1195,12 @@ public class RestContext extends Context { // @formatter:on // If no parent store, promote bs to bootstrap and layer a fresh per-resource store on top. + // NOTE: Stays on legacy `BasicBeanStore.create()...` chain (vs `new BasicBeanStore2(null, X)`) + // because downstream consumers (`RestSession.java:240`, `VarResolver.java:260`) still + // downcast `RestContext.getBeanStore()` / `builder.beanStore()` to `BasicBeanStore` to call + // the legacy `BasicBeanStore.of(...)` static. Migrating those sites requires either + // widening the field types of those consumers or porting `BasicBeanStore.of(...)` onto + // `BasicBeanStore2` (Phase 4). if (parentBs == null) { bootstrapBeanStore = bs; bs = BasicBeanStore.create().overridingParent((BasicBeanStore) bootstrapBeanStore).build(); @@ -2667,7 +2674,7 @@ public class RestContext extends Context { var params = mi.getParameters(); var ra = new RestOpArg[params.size()]; - var bs = BasicBeanStore.of((BasicBeanStore) beanStore); + var bs = new BasicBeanStore2(beanStore); var roa = getRestOpArgs(); for (var i = 0; i < params.size(); i++) { diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java index c91bad5c5a..39f9b2d2ba 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java @@ -40,6 +40,7 @@ import org.apache.juneau.*; import org.apache.juneau.commons.annotation.*; import org.apache.juneau.commons.collections.FluentMap; import org.apache.juneau.commons.function.Memoizer; +import org.apache.juneau.commons.inject.BasicBeanStore2; import org.apache.juneau.commons.inject.WritableBeanStore; import org.apache.juneau.commons.lang.*; import org.apache.juneau.commons.reflect.*; @@ -213,7 +214,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext> return restContext().getBeanContext(); Value<BeanContext.Builder> v = Value.of(parent.copy()); v.get().apply(aa); - var bs = BasicBeanStore.of((BasicBeanStore) beanStore()) + var bs = new BasicBeanStore2(beanStore()) .addBean(Method.class, method()) .addBean(BeanContext.Builder.class, v.get()); bs.createBeanFromMethod(BeanContext.class, resource(), this::matchesInjectScope) @@ -433,7 +434,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext> * method scope) REPLACES the result entirely. */ private final Memoizer<EncoderSet> encoders = memoizer(() -> { - var bs = (BasicBeanStore) beanStore(); + var bs = beanStore(); var b = restContext().getEncodersBuilder().copy(); getRestOpAnnotationsForProperty(PROPERTY_encoders).forEach(ai -> { var c = ai.getClassArray("encoders", Encoder.class).orElse(null); @@ -543,7 +544,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext> return restContext().getJsonSchemaGenerator(); Value<JsonSchemaGenerator.Builder> v = Value.of(parent.copy()); v.get().apply(aa); - var bs = BasicBeanStore.of((BasicBeanStore) beanStore()) + var bs = new BasicBeanStore2(beanStore()) .addBean(Method.class, method()) .addBean(JsonSchemaGenerator.Builder.class, v.get()); bs.createBeanFromMethod(JsonSchemaGenerator.class, resource(), this::matchesInjectScope) @@ -661,7 +662,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext> return restContext().getPartParser(); Value<HttpPartParser.Creator> v = Value.of(parent.copy()); v.get().apply(aa); - var bs = BasicBeanStore.of((BasicBeanStore) beanStore()) + var bs = new BasicBeanStore2(beanStore()) .addBean(Method.class, method()) .addBean(HttpPartParser.Creator.class, v.get()); bs.createBeanFromMethod(HttpPartParser.class, resource(), this::matchesInjectScope) @@ -677,7 +678,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext> return restContext().getPartSerializer(); Value<HttpPartSerializer.Creator> v = Value.of(parent.copy()); v.get().apply(aa); - var bs = BasicBeanStore.of((BasicBeanStore) beanStore()) + var bs = new BasicBeanStore2(beanStore()) .addBean(Method.class, method()) .addBean(HttpPartSerializer.Creator.class, v.get()); bs.createBeanFromMethod(HttpPartSerializer.class, resource(), this::matchesInjectScope) diff --git a/todo/TODO-15-replace-basicbeanstore-with-v2.md b/todo/TODO-15-replace-basicbeanstore-with-v2.md index 7242b21c70..55d0a2f5bb 100644 --- a/todo/TODO-15-replace-basicbeanstore-with-v2.md +++ b/todo/TODO-15-replace-basicbeanstore-with-v2.md @@ -13,19 +13,22 @@ Eliminate the legacy injection stack in `org.apache.juneau.cp` (`BasicBeanStore` - ~~`BeanCreator.of(Class, BeanStore)` overload~~ — **DONE (2026-05-08).** Widened `BeanCreator` to accept any `BeanStore` parent (legacy or v2): added `of(Class, BeanStore)` static factory, changed protected ctor to `(Class, BeanStore)` with internal branch (legacy parent → `BasicBeanStore.of(legacy)`; v2 parent → `new BasicBeanStore2(parent)`), widened `store` field to `WritableBeanStore`, replaced `store.add(...)` with `store.addBean(...)`. Legacy `of(Class, BasicBeanStore)` overload [...] - ~~`BeanBuilder<T>` widening to `WritableBeanStore`~~ — **DONE (2026-05-08).** Field, constructor, and public `beanStore()` accessor all flipped from `BasicBeanStore` to `WritableBeanStore` (chosen over read-only `BeanStore` so callers retaining write access — e.g. `VarResolver.Builder.bean(...)` calling `super.beanStore().addBean(...)` — keep working). All 14 cascade-builder `super(X.class, (BasicBeanStore) beanStore)` casts dropped. Two standalone Builders (`SwaggerProvider.Builder.be [...] - ~~Four-memoizer migration to `BeanInstantiator` (Phase 3 sub-task)~~ — **ATTEMPTED + REVERTED (2026-05-08).** `callLogger` / `debugEnablement` / `staticFiles` / `swaggerProvider` were migrated to `BeanInstantiator.of(...).beanSubType(...).run()`; this broke documented `@Rest(callLogger=…)` / `@Rest(debugEnablement=…)` / `@Rest(swaggerProvider=…)` annotation overrides (3 `Rest_BeanCreatorOverrides_Test` failures) plus `juneau-examples-rest-jetty-ftest` (static files no longer served — ` [...] +- ~~Phase 3 batch-3: drop vestigial `(BasicBeanStore)` casts at framework-defaults call sites~~ — **DONE (2026-05-08).** Sixteen `(BasicBeanStore) bs` casts in `RestContext.java` (lines 494, 515, 584, 676, 753, 768, 914, 937, 957, 987, 1008, 1029, 1064, 1110, 1125) and one in `RestOpContext.java` (line 437) dropped. These were vestigial leftovers from before the utility-class `create(...)` factories were widened to `WritableBeanStore` in the cascade-builder work. The cast was no longer r [...] -**Current remaining footprint (as of 2026-05-08, post-`BeanCreator` widening):** +**Current remaining footprint (as of 2026-05-08, post-batch-3):** | Location | Legacy symbol | Nature | |---|---|---| -| `RestContext.java` | `BasicBeanStore`, `BeanCreator` | 6 `BeanCreator.of(...)` call sites (4 memoizers + user-child-resource path + `findRestOperationArgs`) — **all cast-free** thanks to `BeanCreator.of(Class, BeanStore)`; staying on legacy `BeanCreator` until **TODO-25** lands. Plus 3 direct `BasicBeanStore.of(...)` / `BasicBeanStore.create().overridingParent((BasicBeanStore) parentBs)` calls — these are direct legacy-static API and still require the `(BasicBeanStore)` downcast. | -| `RestOpContext.java` | `BasicBeanStore`, `BeanCreator` | 6 `BasicBeanStore.of((BasicBeanStore) beanStore())` patterns (legacy `BasicBeanStore.of(...)` static still requires `BasicBeanStore`) + `BeanCreator.of(HttpPartSerializer.class).type(c)` for `partSerializer` (no cast — uses no-arg overload). | +| `RestContext.java` | `BasicBeanStore`, `BeanCreator` | 6 `BeanCreator.of(...)` call sites (4 memoizers + user-child-resource path + `findRestOperationArgs`) — **all cast-free** thanks to `BeanCreator.of(Class, BeanStore)`; staying on legacy `BeanCreator` until **TODO-25** lands. Plus 2 direct legacy Builder-API calls (`BasicBeanStore.create().overridingParent((BasicBeanStore) X).build()` lines 348, 1206) using the legacy static API. | +| `RestOpContext.java` | `BasicBeanStore`, `BeanCreator` | 1 `BasicBeanStore.of((BasicBeanStore) context.getBootstrapBeanStore())` (line 1097) — registers the result as `BasicBeanStore.class` for user-facing `@RestPostCall`/`@RestStartCall` hook param resolution; cannot migrate without breaking that contract. + `BeanCreator.of(HttpPartSerializer.class).type(c)` for `partSerializer` (no cast — uses no-arg overload). | +| `RestSession.java` | `cp.BasicBeanStore` | 1 `BasicBeanStore.of((BasicBeanStore) context.getBeanStore())` site (line 240); requires widening private `beanStore` field + public `getBeanStore()` return type to migrate. | +| `VarResolver.java` | `cp.BasicBeanStore` | 1 `BasicBeanStore.of((BasicBeanStore) builder.beanStore())` site (line 260); requires widening package-private field + public `createSession(BasicBeanStore)` method. | | ~~`BeanBuilder<T>` cascade builders~~ | ~~`BasicBeanStore` cast in `super(...)`~~ | **RESOLVED (2026-05-08).** All 14 cascade-builder casts dropped after widening `BeanBuilder<T>` to accept `WritableBeanStore`. | -| `RestInject.java`, `RestInit.java` | `cp.BasicBeanStore` | Javadoc only — trivial update | -| `McpPage.java`, `McpTypedHandlers.java`, `McpEndpoint.java`, `McpRestServlet.java` | `cp.BasicBeanStore` | live usage in `rest-server-mcp` | -| `Name.java`, `Named.java` | `cp.BasicBeanStore` | Javadoc / annotation `@see` only | -| `HttpPartParser.java`, `HttpPartSerializer.java` | `BeanCreateMethodFinder` | 1 reference each — likely Javadoc | -| `BeanStore_Test.java` | `BeanCreateMethodFinder` | 2 test references | +| ~~`RestInject.java`, `RestInit.java`~~ | ~~`cp.BasicBeanStore`~~ | **RESOLVED (2026-05-08, batch 2).** Javadoc-only refs flipped to v2 `BeanStore`. | +| ~~`McpPage.java`, `McpTypedHandlers.java`, `McpEndpoint.java`, `McpRestServlet.java`~~ | ~~`cp.BasicBeanStore`~~ | **RESOLVED (2026-05-08, batch 2).** rest-server-mcp module fully migrated to v2 `BeanStore`. | +| ~~`Name.java`, `Named.java`~~ | ~~`cp.BasicBeanStore`~~ | **RESOLVED (2026-05-08, batch 2).** Javadoc / annotation `@see` only — flipped to v2 `BeanStore`. | +| `HttpPartParser.java`, `HttpPartSerializer.java` | `ContextBeanCreator` | `Creator` inner class extends `ContextBeanCreator<...>` — gated by `ContextBeanCreator` migration to v2 (Phase 4). | +| `BeanStore_Test.java` | `BeanCreateMethodFinder` | 2 test references — guards legacy class behavior; stays until removal. | ### Residual casts in `RestContext` / `RestOpContext` — root causes @@ -35,10 +38,12 @@ Eliminate the legacy injection stack in `org.apache.juneau.cp` (`BasicBeanStore` 3. **`BeanInstantiator` four-memoizer migration blocker.** Migrating `callLogger` / `debugEnablement` / `staticFiles` / `swaggerProvider` to `BeanInstantiator` broke documented `@Rest(callLogger=…)` / `@Rest(debugEnablement=…)` / `@Rest(swaggerProvider=…)` annotation overrides plus static-file serving (loose-builder fallthrough still picks empty-default builders for `BasicStaticFiles` etc.; `Basic*.init(BeanStore)` zero-outs builder defaults via `.orElse(null)` when optional beans aren't [...] -4. **Direct `BasicBeanStore.of(...)` / `BasicBeanStore.create().overridingParent(...)` calls.** `RestSession`, `RestOpContext` (4 sites), and `RestContext` (3 sites) construct child bean stores via legacy static API that requires `BasicBeanStore` parents. Eliminating these requires either (a) porting `of(...)` / `create()` / `overridingParent(...)` onto `BasicBeanStore2` / `WritableBeanStore`, or (b) deferring until Phase 4 cutover when `BasicBeanStore2` is renamed to `BasicBeanStore` an [...] +4. **Direct `BasicBeanStore.of(...)` / `BasicBeanStore.create().overridingParent(...)` calls (partially resolved 2026-05-08).** Five transient internal sites in `RestOpContext` (4 lambdas) and `RestContext.findRestOperationArgs` migrated to `new BasicBeanStore2(beanStore())`. Four sites remain blocked: `RestContext.java:348` (Builder fluent chain with `.type(...)`/`.impl(...)` — needs equivalent v2 fluent API), `RestContext.java:1206` (per-resource bean store re-wrap exposed via public ` [...] 5. ~~**`BeanBuilder<T>` parent-ctor signature.**~~ — **RESOLVED (2026-05-08).** `BeanBuilder<T>` field + ctor + public `beanStore()` accessor all flipped to `WritableBeanStore`. All 14 cascade-builder casts dropped. +6. ~~**Vestigial `(BasicBeanStore) bs` casts at framework-defaults call sites.**~~ — **RESOLVED (2026-05-08, batch 3).** Sixteen casts in `RestContext.java` and one in `RestOpContext.java` dropped — utility-class `create(WritableBeanStore)` factories already accept the supertype, casts were leftover from before the cascade-builder migration. + ### v2 API additions made in this PR (already landed) Promoted to the v2 surface so the `RestContext` / `RestOpContext` migration could land without forcing legacy casts inside those files:
