This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new 39c8443740 docs: add @Value annotation topic page + 9.5.0 release 
notes for TODO-79
39c8443740 is described below

commit 39c844374081849367283306c7121259d8a29eea
Author: James Bognar <[email protected]>
AuthorDate: Mon May 25 14:51:56 2026 -0400

    docs: add @Value annotation topic page + 9.5.0 release notes for TODO-79
    
    Co-authored-by: Cursor <[email protected]>
---
 pages/release-notes/9.5.0.md                       |  82 ++++++++-
 .../02.21.01.SimpleVariableLanguageBasics.md       |  18 ++
 pages/topics/02.21.06.ValueAnnotationBasics.md     | 185 +++++++++++++++++++++
 pages/topics/05.04.01.VariableBasics.md            |   7 +
 sidebars.ts                                        |   5 +
 5 files changed, 296 insertions(+), 1 deletion(-)

diff --git a/pages/release-notes/9.5.0.md b/pages/release-notes/9.5.0.md
index 36e453e77c..a5cbdfde0e 100644
--- a/pages/release-notes/9.5.0.md
+++ b/pages/release-notes/9.5.0.md
@@ -6,7 +6,7 @@ title: "Release 9.5.0"
 
 **Date:** TBD
 
-Juneau 9.5.0 is a minor release with native OpenAPI 3.1 emission (alongside 
Swagger v2, composed via the new four-class `org.apache.juneau.rest.docs` mixin 
pack — `BasicSwaggerResource` / `BasicSwaggerUiResource` / 
`BasicOpenApiResource` / `BasicRedocResource` — that replaces the 
previously-considered `apiFormat` string knob), native TOML and YAML support, 
BSON (Binary JSON) support for MongoDB-interoperable binary serialization, CBOR 
(Concise Binary Object Representation) per RFC 8949 f [...]
+Juneau 9.5.0 is a minor release with native OpenAPI 3.1 emission (alongside 
Swagger v2, composed via the new four-class `org.apache.juneau.rest.docs` mixin 
pack — `BasicSwaggerResource` / `BasicSwaggerUiResource` / 
`BasicOpenApiResource` / `BasicRedocResource` — that replaces the 
previously-considered `apiFormat` string knob), native TOML and YAML support, 
BSON (Binary JSON) support for MongoDB-interoperable binary serialization, CBOR 
(Concise Binary Object Representation) per RFC 8949 f [...]
 
 ### juneau-marshall
 
@@ -387,8 +387,52 @@ land, parser sessions other than `JsonParserSession` / 
`Json5ParserSession` prod
 
 ### juneau-commons
 
+#### `@Value` annotation + `${xxx}` shortcut (TODO-79)
+
+- Added `org.apache.juneau.commons.inject.Value` annotation for declarative 
injection of configuration
+  values into `BeanInstantiator`-created beans (fields, constructor 
parameters, setter parameters,
+  arbitrary method parameters). Resolves expressions through 
`VarResolver.DEFAULT` and coerces
+  the resolved string to the target type via `Settings.toType(...)`.
+- Extended `JsrSupport` with FQN-based detection of the new Juneau `@Value` 
(`JUNEAU_VALUE`) and
+  Spring's `@Value` (`SPRING_VALUE = 
"org.springframework.beans.factory.annotation.Value"`), keeping
+  `juneau-commons` compile-time clean of Spring. Either annotation is picked 
up by the same
+  injection path.
+- Made `@Value` and `@Inject` mutually exclusive on the same site — applying 
both throws
+  `BeanCreationException` with a clear "site already has @Value / @Inject" 
message.
+- Added the `${xxx}` shortcut in `VarResolverSession` — the tokenizer rewrites 
`${...}` to `$P{...}`
+  before resolution, so it inherits the full `PropertyVar` source stack 
(system properties, env vars,
+  registered `Config`s, Spring `Environment`). The first top-level `:` in the 
expression is
+  translated to `,` so Spring-style `${key:default}` defaulting works without 
further changes.
+- Made `Settings.toType(...)` public and extended it to also recognise `static 
T parse(CharSequence)`
+  methods (in addition to `parse(String)`), so `java.time` types like 
`Instant` coerce cleanly.
+- Added `Settings.removeSource(PropertySource)` for explicit deregistration — 
required so per-context
+  bridges (microservice, `RestContext`, Spring `Environment`) can clean up at 
shutdown without
+  cross-test bleed.
+- `Optional<T>` field/parameter injection collapses `null` and empty-string 
results to
+  `Optional.empty()` — matching the "missing-key" intuition that consumers 
expect.
+
 ### juneau-config
 
+#### Classpath-default `Config` bridge to `Settings` (TODO-79)
+
+- Added `org.apache.juneau.config.ConfigPropertySourceProvider`, a 
`META-INF/services`-discovered
+  `PropertySourceProvider` that bridges `Config.getSystemDefault()` (i.e. the 
classpath
+  `juneau.cfg` / `default.cfg` / `application.cfg` / etc. discovered by
+  `Config.getCandidateSystemDefaultConfigNames()`) into the process-wide 
`Settings` singleton.
+- Resolution is **lazy** — `Config.getSystemDefault()` is invoked on the first 
`Settings.get(name)`
+  lookup rather than at SPI registration time. This avoids a 
static-initialization cycle
+  (`Settings.<clinit>` → `useServiceLoader()` → 
`ConfigPropertySourceProvider.create()` →
+  `Config.<clinit>` → `Cache.create()` → `Utils.env(...)` → 
`Settings.<clinit>`) and a runtime
+  reentrance cycle (`Config.findSystemDefault()` looking up 
`"juneau.configFile"` through every
+  registered source, including this one). A thread-local guard short-circuits 
the reentrant
+  lookup; any throwable while `Config` is mid-initialisation is treated as 
"not yet available"
+  without memoising the failure.
+- The provider is **silent** when no classpath `Config` exists — every lookup 
returns
+  `missing()`, no log noise, no exception.
+- The provider's `order()` is `100`, deliberately low — so any programmatic
+  `Settings.get().addSource(...)` registered later (microservice, 
`RestContext`, Spring) shadows
+  the classpath default at lookup time.
+
 #### YAML config format support (TODO-32)
 
 - Added optional YAML config support to `juneau-config` alongside the existing 
INI/CFG format.
@@ -1986,6 +2030,16 @@ String name
 
 ### juneau-rest-server
 
+#### `RestContext` wires its `Config` into `Settings` (TODO-79)
+
+- `RestContext`'s constructor now installs a `ConfigPropertySource` for the 
resource-scoped `Config`
+  onto the process-wide `Settings.get()` source stack, and `destroy()` removes 
it. This lets
+  `@Value("${section/key}")` injections on resource-scoped beans see the same 
`Config` that
+  `$C{section/key}` resolves against — without any further wiring.
+- Because `Settings` walks sources in reverse insertion order, the 
per-resource `Config` wins over
+  the classpath-default `juneau.cfg` bridge installed by 
`ConfigPropertySourceProvider` and over
+  the JVM-default sources (system properties, env vars).
+
 #### Rest Debug Rethink (TODO-20)
 
 `juneau-rest-server` now resolves debug behavior through a single 
`DebugConfig` model and typed `@Debug` annotation slot, replacing the previous 
split model (`debug`, `debugDefault`, `debugEnablement`, `debugOn`) on `@Rest` 
/ `@RestOp`.
@@ -2795,6 +2849,14 @@ See [REST Server — Conditional-GET / ETag 
Helpers](/docs/topics/RestServerCond
 
 ### juneau-microservice (formerly juneau-microservice-core)
 
+#### Per-microservice `Config` wired into `Settings` (TODO-79)
+
+- `Microservice`'s constructor now installs a `ConfigPropertySource` for the 
microservice's own
+  `Config` onto `Settings.get()`, and `stop()` removes it. Any 
`@Value("${section/key}")`
+  injection — on REST resources mounted under the microservice, on listeners, 
or on any other
+  bean built through `BeanInstantiator` — resolves against the microservice 
config without an
+  explicit lookup call.
+
 #### Module Renamed (TODO-36)
 
 The `juneau-microservice-core` Maven artifact has been **renamed** to 
`juneau-microservice`. The aggregator pom is now
@@ -2869,6 +2931,24 @@ microservices that never call `.configurations(...)` 
behave identically to pre-9
 
 See <a href="/docs/topics/MicroserviceCoreInject">Inject-Aware 
Microservice</a> for the full guide.
 
+### juneau-rest-server-springboot
+
+#### Spring `Environment` bridge — `@Value` reads `application.yaml` (TODO-79)
+
+- Added `org.apache.juneau.rest.springboot.SpringEnvironmentPropertySource` — 
a `PropertySource`
+  that reads from a Spring `Environment` so `@Value("${spring.app.key}")` 
injections on
+  Juneau-instantiated beans resolve against the same property sources Spring 
Boot itself uses
+  (`application.yaml` / `application.properties`, command-line args, env vars, 
`@PropertySource`,
+  etc.).
+- `SpringBeanStore`'s constructor now auto-registers a lazy bridge against the
+  `ApplicationContext`'s `Environment`, and `SpringBeanStore.clear()` removes 
it. The bridge is
+  resolved lazily — the constructor doesn't actually call 
`appContext.getEnvironment()` until the
+  first lookup — so callers that mock the `ApplicationContext` without 
stubbing `getEnvironment()`
+  (e.g. unit tests that only exercise bean-lookup paths) are unaffected.
+- The bridge sits *above* the classpath-default `juneau.cfg` bridge in the 
`Settings` source stack
+  (later insertion wins), so `application.yaml` shadows `juneau.cfg` when both 
define the same
+  key — matching the typical Spring Boot precedence intuition.
+
 ### juneau-microservice-jetty
 
 #### `HealthProbeConfiguration` (TODO-65)
diff --git a/pages/topics/02.21.01.SimpleVariableLanguageBasics.md 
b/pages/topics/02.21.01.SimpleVariableLanguageBasics.md
index 98af55b737..7f240d5816 100644
--- a/pages/topics/02.21.01.SimpleVariableLanguageBasics.md
+++ b/pages/topics/02.21.01.SimpleVariableLanguageBasics.md
@@ -55,3 +55,21 @@ The following shows how variables can be arbitrarily 
nested...
 // 3) 'not found' string if system property not found.
 String property = 
VarResolver.DEFAULT.resolve("$E{MYPROPERTY,$S{my.property,not found}}");
 ```
+
+## The `${xxx}` shortcut (9.5.0)
+
+Starting in 9.5.0 the tokenizer recognises `${xxx}` as a shorthand for 
`$P{xxx}` — the
+<a href="/site/apidocs/org/apache/juneau/commons/svl/vars/PropertyVar.html" 
target="_blank">PropertyVar</a>
+that resolves against the unified `Settings` source stack (system properties, 
env vars,
+classpath `juneau.cfg`, per-microservice `Config`, Spring `Environment`, …). A 
Spring-style
+default after a colon works because the first top-level `:` is rewritten to 
`,` before
+delegation to `PropertyVar`:
+
+```java
+// Equivalent forms:
+VarResolver.DEFAULT.resolve("$P{my.key,fallback}");
+VarResolver.DEFAULT.resolve("${my.key:fallback}");
+```
+
+See [@Value Annotation Basics](./ValueAnnotationBasics.md) for the broader 
picture of how
+`${...}` ties into declarative configuration injection and Spring Boot interop.
diff --git a/pages/topics/02.21.06.ValueAnnotationBasics.md 
b/pages/topics/02.21.06.ValueAnnotationBasics.md
new file mode 100644
index 0000000000..2c062d88b5
--- /dev/null
+++ b/pages/topics/02.21.06.ValueAnnotationBasics.md
@@ -0,0 +1,185 @@
+---
+title: "@Value Annotation Basics"
+slug: ValueAnnotationBasics
+---
+
+The <a href="/site/apidocs/org/apache/juneau/commons/inject/Value.html" 
target="_blank">@Value</a> annotation
+(introduced in 9.5.0, package `org.apache.juneau.commons.inject`) is a 
declarative way to inject configuration
+values into beans created by <a 
href="/site/apidocs/org/apache/juneau/commons/inject/BeanInstantiator.html" 
target="_blank">BeanInstantiator</a> — constructor parameters, setter 
parameters, and fields.
+
+It complements <a 
href="/site/apidocs/org/apache/juneau/commons/inject/Inject.html" 
target="_blank">@Inject</a>:
+
+- `@Inject` requests a *bean* from the bean store by type.
+- `@Value` requests a *configuration value* from <a 
href="/site/apidocs/org/apache/juneau/commons/settings/Settings.html" 
target="_blank">Settings</a> via the
+  <a 
href="/site/apidocs/org/apache/juneau/commons/svl/VarResolver.html#DEFAULT" 
target="_blank">VarResolver.DEFAULT</a> resolver.
+
+The two are mutually exclusive on the same injection site — applying both 
raises
+`BeanCreationException`.
+
+## The `${...}` shortcut
+
+Inside a `@Value` expression (or anywhere you can write SVL), `${key}` is 
shorthand for `$P{key}` —
+the <a 
href="/site/apidocs/org/apache/juneau/commons/svl/vars/PropertyVar.html" 
target="_blank">PropertyVar</a> that
+looks up a unified property by name from `Settings`. The shortcut also accepts 
a Spring-style
+default after a colon:
+
+```text
+${some.key}                — required key, missing → empty string
+${some.key:fallback}       — default-when-missing
+${section/sub.key}         — nested property names (Config sections, etc.)
+${a.b:${other:none}}       — nested expansion (defaults composed)
+```
+
+This is purely surface syntax — the tokenizer rewrites `${...}` to `$P{...}` 
before resolution.
+Everything `$P{...}` does (recursive resolution, default values, env-var 
fallback through chained
+sources) works identically with `${...}`. See
+[Simple Variable Language Basics](./SimpleVariableLanguageBasics.md) and
+[Variable Basics](./VariableBasics.md) for the underlying mechanics.
+
+## Resolution order (precedence)
+
+`Settings.get(name)` walks every registered `PropertySource` in **reverse 
insertion order** — the
+most-recently-added source wins. The default chain (built up at startup) looks 
like:
+
+1. **`PropertySourceProvider` SPI sources** added at process startup (e.g. 
classpath `juneau.cfg`
+   via `ConfigPropertySourceProvider`). These register first and therefore sit 
at the *bottom* of
+   the priority list.
+2. **Per-microservice `Config`** — 
`org.apache.juneau.microservice.Microservice` installs a
+   `ConfigPropertySource` for its own `Config` in its constructor.
+3. **Per-`RestContext` `Config`** — `RestContext` installs one for the 
`@Rest`-resource-scoped
+   `Config` in its constructor.
+4. **Spring `Environment` bridge** — when `juneau-rest-server-springboot`'s 
`SpringBeanStore` is
+   constructed, it installs a `SpringEnvironmentPropertySource` so 
`${spring.app.key}` resolves
+   against `application.yaml`, env vars, command-line args, and any custom 
Spring `PropertySource`.
+5. **Built-in `Settings` sources** — system properties, environment variables, 
`.env` file,
+   argument list, JAR manifest entries.
+
+Because all sources are checked, the same `@Value` expression resolves 
identically under a
+microservice, a Spring Boot app, or a bare REST resource — the *origin* of the 
value changes, the
+expression doesn't.
+
+## Field injection
+
+```java
+import org.apache.juneau.commons.inject.Value;
+
+public class MyResource {
+
+    @Value("${myapp.title:Untitled}")
+    private String title;
+
+    @Value("${myapp.maxPageSize:50}")
+    private int maxPageSize;
+}
+```
+
+`Settings.toType(...)` coerces the resolved string to the target type. 
Coercion supports:
+
+- Primitives and their boxed wrappers.
+- `java.time` types (`Instant`, `Duration`, `Period`, `LocalDate`, etc.) — any 
type with a
+  `parse(CharSequence)` or `parse(String)` static method.
+- `Optional<T>` — `Optional.empty()` is injected when the key resolves to 
`null` or the empty
+  string; otherwise `Optional.of(coerced)`.
+- Any type with a single-string-argument constructor.
+
+## Constructor + setter parameter injection
+
+`@Value` works on constructor parameters and on setter (and any method) 
parameters:
+
+```java
+public class JwtValidator {
+
+    private final Duration ttl;
+
+    public JwtValidator(@Value("${jwt.cache.ttl:PT5M}") Duration ttl) {
+        this.ttl = ttl;
+    }
+
+    @Inject
+    public void setKeyResolver(KeyResolver keys) { ... }   // @Inject path — 
bean lookup
+
+    public void setMaxClock(@Value("${jwt.clock.skew:PT30S}") Duration skew) { 
... }
+}
+```
+
+## Spring `@Value` compatibility
+
+For consumers migrating from Spring Boot, 
`org.springframework.beans.factory.annotation.Value`
+is detected by *fully-qualified name* (`JsrSupport.SPRING_VALUE`) — 
`juneau-commons` doesn't
+declare a compile-time dependency on Spring. The same resolution chain 
applies, so the following
+two beans are functionally identical inside a Juneau bean store:
+
+```java
+public class A {
+    @org.apache.juneau.commons.inject.Value("${jwt.cache.ttl:PT5M}")
+    Duration ttl;
+}
+
+public class B {
+    
@org.springframework.beans.factory.annotation.Value("${jwt.cache.ttl:PT5M}")
+    Duration ttl;
+}
+```
+
+## Spring Boot bridge (`juneau-rest-server-springboot`)
+
+Inside a Spring Boot application, `SpringBeanStore` automatically installs a
+<a 
href="/site/apidocs/org/apache/juneau/rest/springboot/SpringEnvironmentPropertySource.html"
 target="_blank">SpringEnvironmentPropertySource</a>
+the first time it's constructed (typically by 
`SpringRestServlet.createBeanStore(...)`). This
+means `application.yaml` keys are reachable from a Juneau `@Value`:
+
+```yaml
+# application.yaml
+myapp:
+  title: My Awesome App
+  cache:
+    ttl: PT10M
+```
+
+```java
+@Rest
+public class MyResource extends BasicSpringRestServlet {
+
+    @Value("${myapp.title:Untitled}")
+    private String title;
+
+    @Value("${myapp.cache.ttl:PT5M}")
+    private Duration cacheTtl;
+}
+```
+
+The bridge is removed when `SpringBeanStore.clear()` is called — important for 
tests that build
+many transient Spring contexts in the same JVM.
+
+## Classpath-default `Config` (`juneau-config`)
+
+The `juneau-config` module ships a `META-INF/services` entry for
+<a 
href="/site/apidocs/org/apache/juneau/config/ConfigPropertySourceProvider.html" 
target="_blank">ConfigPropertySourceProvider</a>.
+At startup, `Settings.useServiceLoader()` discovers the provider and registers 
a *lazy* bridge to
+`Config.getSystemDefault()`. The resolution is deferred to the first lookup so 
it can't trigger
+class-init cycles, and the bridge is silent when no classpath default 
`juneau.cfg` exists.
+
+This means a plain `juneau.cfg` on the classpath transparently feeds 
`@Value("${section/key}")`
+without any explicit wiring.
+
+## Mutual exclusion with `@Inject`
+
+`@Value` and `@Inject` on the same field, parameter, or setter is an error:
+
+```java
+@Inject
+@Value("${some.key}")   // BeanCreationException at injection time
+private String value;
+```
+
+The exception message identifies the offending site to make the conflict easy 
to fix.
+
+## See also
+
+- [Simple Variable Language Basics](./SimpleVariableLanguageBasics.md) — the 
full SVL surface.
+- [SVL Variables](./SvlVariables.md) — list of built-in `$X{...}` resolvers.
+- [Variable Basics](./VariableBasics.md) — how variables work inside a 
`Config`.
+- <a href="/site/apidocs/org/apache/juneau/commons/inject/Value.html" 
target="_blank">org.apache.juneau.commons.inject.Value</a>
+- <a href="/site/apidocs/org/apache/juneau/commons/settings/Settings.html" 
target="_blank">org.apache.juneau.commons.settings.Settings</a>
+- <a href="/site/apidocs/org/apache/juneau/commons/svl/vars/PropertyVar.html" 
target="_blank">org.apache.juneau.commons.svl.vars.PropertyVar</a>
+- <a 
href="/site/apidocs/org/apache/juneau/rest/springboot/SpringEnvironmentPropertySource.html"
 
target="_blank">org.apache.juneau.rest.springboot.SpringEnvironmentPropertySource</a>
diff --git a/pages/topics/05.04.01.VariableBasics.md 
b/pages/topics/05.04.01.VariableBasics.md
index 5b441a3202..06b3d47c0c 100644
--- a/pages/topics/05.04.01.VariableBasics.md
+++ b/pages/topics/05.04.01.VariableBasics.md
@@ -66,3 +66,10 @@ Additionally, the following method can be used to retrieve a 
`Config` with a dif
 <node-0><java-class><a 
href="/site/apidocs/org/apache/juneau/config/Config.html" 
target="_blank">Config</a></java-class></node-0>
 <node-1><java-method><a 
href="/site/apidocs/org/apache/juneau/config/Config.html#resolving(org.apache.juneau.commons.svl.VarResolverSession)"
 target="_blank">resolving(VarResolverSession)</a></java-method></node-1>
 </tree>
+
+## See also
+
+- [`${xxx}` shortcut](./SimpleVariableLanguageBasics.md) — Spring-style 
placeholder syntax that
+  lowers to `$P{...}` (unified property lookup) and supports `${key:default}` 
defaulting.
+- [@Value Annotation Basics](./ValueAnnotationBasics.md) — declarative 
configuration injection
+  using `@Value("${...}")` on beans, including the Spring Boot 
`application.yaml` bridge.
diff --git a/sidebars.ts b/sidebars.ts
index 0a6de7d053..6a2c2111a3 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -347,6 +347,11 @@ const sidebars: SidebarsConfig = {
                                                                        id: 
'topics/02.21.05.SvlOtherNotes',
                                                                        label: 
'2.21.5. SVL Other Notes',
                                                                },
+                                                               {
+                                                                       type: 
'doc',
+                                                                       id: 
'topics/02.21.06.ValueAnnotationBasics',
+                                                                       label: 
'2.21.6. @Value Annotation Basics',
+                                                               },
                                                        ],
                                                },
                                                {

Reply via email to