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


The following commit(s) were added to refs/heads/master by this push:
     new b832eb2ea7 refactor: finalize framework-internal @Value adoption and 
tests
b832eb2ea7 is described below

commit b832eb2ea7fbb4f4680a5f5e64880aa129ceb13b
Author: James Bognar <[email protected]>
AuthorDate: Wed May 27 07:07:15 2026 -0400

    refactor: finalize framework-internal @Value adoption and tests
---
 .../apache/juneau/junit/bct/BctConfiguration.java  |  70 ++++++
 .../microservice/jetty/JettyServerComponent.java   |  21 +-
 .../apache/juneau/microservice/Microservice.java   |  35 ++-
 .../juneau/rest/auth/jwt/JwtTokenValidator.java    |  28 ++-
 .../java/org/apache/juneau/rest/RestContext.java   | 104 +++++++--
 .../java/org/apache/juneau/rest/RestOpContext.java |  33 +--
 .../rest/convention/BasicVersionResource.java      |  38 +++-
 .../org/apache/juneau/rest/logger/CallLogger.java  | 131 ++++-------
 .../bct/BctConfiguration_ValueAdoption_Test.java   |  79 +++++++
 .../Microservice_ValueAdoption_Test.java           |  62 ++++++
 .../rest/RestContext_ValueAdoption_Test.java       | 241 +++++++++++++++++++++
 .../jwt/JwtTokenValidator_ValueAdoption_Test.java  |  58 +++++
 .../BasicVersionResource_ValueAdoption_Test.java   |  76 +++++++
 .../rest/logger/CallLogger_ValueAdoption_Test.java | 160 ++++++++++++++
 14 files changed, 1011 insertions(+), 125 deletions(-)

diff --git 
a/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctConfiguration.java
 
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctConfiguration.java
index e2ceae840e..33c35c226a 100644
--- 
a/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctConfiguration.java
+++ 
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctConfiguration.java
@@ -20,6 +20,7 @@ import static 
org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import org.apache.juneau.commons.function.*;
+import org.apache.juneau.commons.inject.*;
 import org.apache.juneau.commons.settings.*;
 
 /**
@@ -342,4 +343,73 @@ public class BctConfiguration {
        static BeanConverter getConverter() {
                return 
opt(BctConfiguration.CONVERTER_OVERRIDE.get()).orElseGet(CONVERTER_SUPPLIER.get());
        }
+
+       /**
+        * Returns the {@link Value @Value}-resolved defaults for {@link 
#BCT_SORT_MAPS} and
+        * {@link #BCT_SORT_COLLECTIONS}, sourced from the active
+        * {@link org.apache.juneau.commons.settings.Settings Settings} chain 
(system properties
+        * &rarr; environment variables &rarr; registered property sources). 
Each invocation creates
+        * a fresh, fully-injected instance.
+        *
+        * <p>
+        * This is the canonical seam for &quot;BCT default sort flags&quot; 
reads — production code that
+        * makes a per-call decision based on the resolved defaults should call
+        * {@code BctConfiguration.defaults().isSortMaps()} / {@code 
.isSortCollections()} instead of
+        * hand-rolling its own {@code System.getProperty(...)} read.
+        *
+        * @return A new {@link Defaults} instance, populated via {@link 
BeanInstantiator}.
+        */
+       public static Defaults defaults() {
+               return BeanInstantiator.of(Defaults.class, 
BasicBeanStore.INSTANCE).run();
+       }
+
+       /**
+        * Holder for {@link Value @Value}-resolved BCT default sort flags.
+        *
+        * <p>
+        * Constructed by {@link #defaults()} via {@link BeanInstantiator}; 
both fields are populated
+        * by {@link Value @Value} annotations whose SVL expressions inline the 
canonical
+        * {@link #BCT_SORT_MAPS} and {@link #BCT_SORT_COLLECTIONS} property 
names as string literals
+        * (per the project-wide rule that every {@code @Value} expression is a 
fully self-contained
+        * string literal &mdash; no concatenation with Java constants). The 
constants remain the
+        * canonical reference for external callers ({@link Listifiers}, {@code 
BctConfigExtension},
+        * and the {@code BctConfiguration.set/get} helpers).
+        */
+       public static class Defaults {
+
+               /**
+                * The {@code Bct.sortMaps} default; {@code true} when the 
{@link #BCT_SORT_MAPS} property is
+                * set to a truthy value, {@code false} otherwise.
+                */
+               @Value("${Bct.sortMaps:false}")
+               boolean sortMaps;
+
+               /**
+                * The {@code Bct.sortCollections} default; {@code true} when 
the {@link #BCT_SORT_COLLECTIONS}
+                * property is set to a truthy value, {@code false} otherwise.
+                */
+               @Value("${Bct.sortCollections:false}")
+               boolean sortCollections;
+
+               /** Constructor &mdash; instantiated by {@link 
BeanInstantiator} via {@link #defaults()}. */
+               protected Defaults() {}
+
+               /**
+                * Returns the resolved {@code Bct.sortMaps} default.
+                *
+                * @return {@code true} when the {@link #BCT_SORT_MAPS} 
property is set to a truthy value, {@code false} otherwise.
+                */
+               public boolean isSortMaps() {
+                       return sortMaps;
+               }
+
+               /**
+                * Returns the resolved {@code Bct.sortCollections} default.
+                *
+                * @return {@code true} when the {@link #BCT_SORT_COLLECTIONS} 
property is set to a truthy value, {@code false} otherwise.
+                */
+               public boolean isSortCollections() {
+                       return sortCollections;
+               }
+       }
 }
diff --git 
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
 
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
index 3ee73234f9..56c950274f 100644
--- 
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
+++ 
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
@@ -31,6 +31,8 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.*;
 
 import org.apache.juneau.commons.inject.BeanStore;
+import org.apache.juneau.commons.inject.Value;
+import org.apache.juneau.commons.reflect.ClassInfo;
 import org.apache.juneau.config.event.*;
 import org.apache.juneau.cp.*;
 import org.apache.juneau.microservice.*;
@@ -85,6 +87,20 @@ public class JettyServerComponent implements 
MicroserviceListener {
        private final AtomicReference<Server> server = new AtomicReference<>();
        private final AtomicReference<Microservice> microservice = new 
AtomicReference<>();
 
+       /**
+        * Env-driven sentinel for {@code availablePort}; {@link 
Optional#empty()} when unset (in which case
+        * {@link #onStart(Microservice)} publishes the bound port back as the 
{@code availablePort} system property).
+        */
+       @Value("${availablePort}")
+       Optional<String> availablePortEnv;
+
+       /**
+        * Env-driven sentinel for {@code juneau.serverPort}; {@link 
Optional#empty()} when unset (in which case
+        * {@link #onStart(Microservice)} publishes the bound port back as the 
{@code juneau.serverPort} system property).
+        */
+       @Value("${juneau.serverPort}")
+       Optional<String> serverPortEnv;
+
        private static int[] parseIntArray(String csv) {
                if (csv == null || csv.isEmpty())
                        return new int[0];
@@ -172,6 +188,7 @@ public class JettyServerComponent implements 
MicroserviceListener {
                try {
                        microservice.set(ms);
                        var store = ms.getBeanStore();
+                       ClassInfo.of(this).inject(this, store);
                        var cf = ms.getConfig();
                        var mf = ms.getManifest();
                        var vr = ms.getVarResolver();
@@ -184,7 +201,7 @@ public class JettyServerComponent implements 
MicroserviceListener {
                                        .orElseGet(() -> 
mf.get("Jetty-Port").map(JettyServerComponent::parseIntArray).orElseGet(() -> 
ints(8000)));
                        var availablePort = findOpenPort(ports);
 
-                       if (env("availablePort").isEmpty())
+                       if (availablePortEnv == null || 
availablePortEnv.isEmpty())
                                System.setProperty("availablePort", 
String.valueOf(availablePort));
 
                        // Prefer a @Bean-supplied Server, else build one from 
jetty.xml.
@@ -265,7 +282,7 @@ public class JettyServerComponent implements 
MicroserviceListener {
                                addServlet(servlet, pathSpecs);
                        }
 
-                       if (env("juneau.serverPort").isEmpty())
+                       if (serverPortEnv == null || serverPortEnv.isEmpty())
                                System.setProperty("juneau.serverPort", 
String.valueOf(availablePort));
 
                        server.get().start();
diff --git 
a/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
 
b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
index b423351d1c..4dbad4aff1 100755
--- 
a/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
+++ 
b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
@@ -124,7 +124,7 @@ public class Microservice implements ConfigEventListener {
                Scanner consoleReader;
                PrintWriter consoleWriter;
                MicroserviceListener listener;
-               File workingDir = 
env("juneau.workingDir").map(File::new).orElse(null);
+               File workingDir;
                WritableBeanStore beanStore;
                BeanStore overridingBeanStore;
                List<Class<?>> configurations = list();
@@ -134,6 +134,21 @@ public class Microservice implements ConfigEventListener {
                 */
                protected Builder() {}
 
+               /**
+                * {@link Inject @Inject}-annotated initializer that populates 
{@link #workingDir} from the
+                * {@code juneau.workingDir} property (system property &rarr; 
environment variable &rarr;
+                * registered property sources) when the property is set. Has 
no effect if {@code workingDir}
+                * was already set programmatically.
+                *
+                * @param workingDirEnv The resolved {@code juneau.workingDir} 
value, or {@code null}/empty
+                *      when not configured.
+                */
+               @Inject
+               public void 
initWorkingDirFromEnv(@Value("${juneau.workingDir}") String workingDirEnv) {
+                       if (workingDir == null && workingDirEnv != null && 
!workingDirEnv.isEmpty())
+                               workingDir = new File(workingDirEnv);
+               }
+
                /**
                 * Copy constructor.
                 *
@@ -621,10 +636,26 @@ public class Microservice implements ConfigEventListener {
        /**
         * Creates a new builder for this object.
         *
+        * <p>
+        * Routes builder construction through {@link BeanInstantiator} so that 
the
+        * {@code juneau.workingDir} env default is resolved through the active
+        * {@link org.apache.juneau.commons.settings.Settings Settings} chain.
+        *
         * @return A new microservice builder.
         */
        public static Builder create() {
-               return new Builder();
+               return create(BasicBeanStore.INSTANCE);
+       }
+
+       /**
+        * Creates a new builder for this object using the supplied {@link 
BeanStore} for
+        * {@link Value @Value}-resolution and dependency injection.
+        *
+        * @param beanStore The bean store to use for dependency injection.
+        * @return A new microservice builder.
+        */
+       public static Builder create(BeanStore beanStore) {
+               return BeanInstantiator.of(Builder.class, beanStore).run();
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-server-jwt/src/main/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator.java
 
b/juneau-rest/juneau-rest-server-jwt/src/main/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator.java
index 738e869230..6f304c09cb 100644
--- 
a/juneau-rest/juneau-rest-server-jwt/src/main/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator.java
+++ 
b/juneau-rest/juneau-rest-server-jwt/src/main/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator.java
@@ -24,6 +24,7 @@ import java.text.*;
 import java.time.*;
 import java.util.*;
 
+import org.apache.juneau.commons.inject.*;
 import org.apache.juneau.rest.auth.*;
 
 import com.nimbusds.jose.*;
@@ -99,10 +100,26 @@ public class JwtTokenValidator implements TokenValidator {
        /**
         * Static creator.
         *
+        * <p>
+        * Routes builder construction through {@link BeanInstantiator} so the
+        * {@link Builder#jwksCacheTtl jwksCacheTtl} default is resolved via 
{@link Value @Value} from the
+        * active {@link org.apache.juneau.commons.settings.Settings Settings} 
chain
+        * ({@code juneau.jwt.jwksCacheTtl} property &rarr; {@code PT5M}).
+        *
         * @return A new builder.
         */
        public static Builder create() {
-               return new Builder();
+               return create(BasicBeanStore.INSTANCE);
+       }
+
+       /**
+        * Static creator with explicit bean store.
+        *
+        * @param beanStore The bean store to use for dependency injection.
+        * @return A new builder.
+        */
+       public static Builder create(BeanStore beanStore) {
+               return BeanInstantiator.of(Builder.class, beanStore).run();
        }
 
        /**
@@ -116,7 +133,14 @@ public class JwtTokenValidator implements TokenValidator {
                private String audience;
                private Set<JWSAlgorithm> algorithms = new 
LinkedHashSet<>(Arrays.asList(JWSAlgorithm.RS256, JWSAlgorithm.ES256));
                private Duration clockSkew = Duration.ofSeconds(60);
-               private Duration jwksCacheTtl = Duration.ofMinutes(5);
+
+               /**
+                * JWKS cache TTL; populated via {@link Value @Value} from
+                * {@code juneau.jwt.jwksCacheTtl} (ISO-8601 duration, default 
{@code PT5M} = 5 minutes).
+                */
+               @Value("${juneau.jwt.jwksCacheTtl:PT5M}")
+               Duration jwksCacheTtl;
+
                private Clock clock = Clock.systemUTC();
 
                /** Constructor. */
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 6105d8a180..c5c0ee7dff 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
@@ -871,6 +871,75 @@ public class RestContext extends Context {
                return u(toList(s));
        });
 
+       
//---------------------------------------------------------------------------------------------
+       // @Value-injected env-driven defaults
+       //
+       // Populated by ClassInfo.of(this).inject(this, beanStore) during 
construction; consumed by the
+       // memoizer lambdas below (which run lazily, i.e. after injection has 
completed). Each field
+       // is the env-driven default that flows into 
mergeReplacedStringAttribute / mergeReplacedBooleanAttribute
+       // as the initial value before the @Rest annotation chain is walked.
+       
//---------------------------------------------------------------------------------------------
+
+       /** Env-driven default for {@code @Rest(debugDefault)}; consumed by the 
{@link #debugEnablement} memoizer. */
+       @org.apache.juneau.commons.inject.Value("${RestContext.debugDefault:}")
+       private String defaultDebugDefault;
+
+       /** Env-driven default for the call-logger debug level fallback in the 
{@link #debugConfig} memoizer. */
+       
@org.apache.juneau.commons.inject.Value("${juneau.restLogger.level:INFO}")
+       private String defaultDebugLevel;
+
+       /** Env-driven default for {@code @Rest(allowedHeaderParams)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.allowedHeaderParams:Accept,Content-Type}")
+       private String defaultAllowedHeaderParams;
+
+       /** Env-driven default for {@code @Rest(allowedMethodHeaders)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.allowedMethodHeaders:}")
+       private String defaultAllowedMethodHeaders;
+
+       /** Env-driven default for {@code @Rest(allowedMethodParams)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.allowedMethodParams:HEAD,OPTIONS}")
+       private String defaultAllowedMethodParams;
+
+       /** Env-driven default for {@code @Rest(disableContentParam)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.disableContentParam:false}")
+       private boolean defaultDisableContentParam;
+
+       /** Env-driven default for {@code @Rest(renderResponseStackTraces)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.renderResponseStackTraces:false}")
+       private boolean defaultRenderResponseStackTraces;
+
+       /** Env-driven default for {@code @Rest(problemDetails)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.problemDetails:false}")
+       private boolean defaultProblemDetails;
+
+       /** Env-driven default for {@code @Rest(virtualThreads)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.virtualThreads:false}")
+       private boolean defaultVirtualThreads;
+
+       /** Env-driven default for {@code @Rest(eagerInit)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.eagerInit:false}")
+       private boolean defaultEagerInit;
+
+       /** Env-driven default for {@code @Rest(clientVersionHeader)}. */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.clientVersionHeader:Client-Version}")
+       private String defaultClientVersionHeader;
+
+       /** Env-driven default for {@code @Rest(uriRelativity)}; resolves to 
empty string when unset (treated as "no default"). */
+       @org.apache.juneau.commons.inject.Value("${RestContext.uriRelativity:}")
+       private String defaultUriRelativity;
+
+       /** Env-driven default for {@code @Rest(uriAuthority)}; {@link 
Optional#empty()} when unset (preserves null-vs-empty distinction). */
+       @org.apache.juneau.commons.inject.Value("${RestContext.uriAuthority}")
+       private Optional<String> defaultUriAuthority;
+
+       /** Env-driven default for {@code @Rest(uriContext)}; {@link 
Optional#empty()} when unset (preserves null-vs-empty distinction). */
+       @org.apache.juneau.commons.inject.Value("${RestContext.uriContext}")
+       private Optional<String> defaultUriContext;
+
+       /** Env-driven default for {@code @Rest(uriResolution)}; resolves to 
empty string when unset (treated as "no default"). */
+       @org.apache.juneau.commons.inject.Value("${RestContext.uriResolution:}")
+       private String defaultUriResolution;
+
        /**
         * The {@link DebugEnablement} for this resource.
         *
@@ -888,7 +957,7 @@ public class RestContext extends Context {
                // If neither a debugDefault annotation value NOR a 
pre-registered Enablement bean is present, fall back
                // to the @Rest(debug=true|false) boolean flag — ALWAYS when 
set, NEVER otherwise.
                var bs = beanStore();
-               String debugDefaultStr = 
mergeReplacedStringAttribute(PROPERTY_debugDefault, 
env("RestContext.debugDefault").orElse(null));
+               String debugDefaultStr = 
mergeReplacedStringAttribute(PROPERTY_debugDefault, defaultDebugDefault);
                Enablement resolvedDebugDefault = null;
                if (nn(debugDefaultStr) && !debugDefaultStr.isBlank())
                        resolvedDebugDefault = 
Enablement.fromString(debugDefaultStr);
@@ -923,7 +992,7 @@ public class RestContext extends Context {
                        .reduce((first, second) -> second)
                        .orElse("");
                var format = formatType == null ? new BasicTextFormat() : 
BeanInstantiator.of(DebugFormat.class, bs).type(formatType).run();
-               var level = StringUtils.isNotBlank(levelStr) ? 
Level.parse(levelStr) : Level.parse(env(CallLogger.SP_level, "INFO"));
+               var level = StringUtils.isNotBlank(levelStr) ? 
Level.parse(levelStr) : Level.parse(defaultDebugLevel);
                var mode2 = mode;
                return new DebugConfig(bs) {
                        @Override
@@ -1939,6 +2008,11 @@ public class RestContext extends Context {
                                .addBean(AnnotationWorkList.class, 
annotationWork);
                        // @formatter:on
 
+                       // Inject @Value-annotated env-driven defaults onto 
this RestContext instance so that the
+                       // memoizer lambdas below (which run lazily on first 
.get() call) read fully resolved values.
+                       // Must run BEFORE isEagerInit() since the eagerInit 
memoizer itself reads defaultEagerInit.
+                       ClassInfo.of(this).inject(this, beanStore);
+
                        if (isEagerInit()) {
                                // Force-fire the framework-bean memoizers in 
dependency-friendly order so their @Rest()
                                // annotation walks (e.g. 
`@Rest(partParser=…)`, `@Rest(partSerializer=…)`, `@Rest(encoders=…)`,
@@ -2128,42 +2202,42 @@ public class RestContext extends Context {
         * default {@code "Accept,Content-Type"}.
         */
        private final Memoizer<Set<String>> allowedHeaderParams = memoizer(() ->
-               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedHeaderParams,
 env("RestContext.allowedHeaderParams", "Accept,Content-Type")))));
+               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedHeaderParams,
 defaultAllowedHeaderParams))));
 
        /**
         * HTTP method names that may be specified via a request header; 
resolved from {@code @Rest(allowedMethodHeaders)},
         * default empty.
         */
        private final Memoizer<Set<String>> allowedMethodHeaders = memoizer(() 
->
-               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedMethodHeaders,
 env("RestContext.allowedMethodHeaders").orElse("")))));
+               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedMethodHeaders,
 defaultAllowedMethodHeaders))));
 
        /**
         * HTTP method names that may be specified via URL query parameter; 
resolved from {@code @Rest(allowedMethodParams)},
         * default {@code "HEAD,OPTIONS"}.
         */
        private final Memoizer<Set<String>> allowedMethodParams = memoizer(() ->
-               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedMethodParams,
 env("RestContext.allowedMethodParams", "HEAD,OPTIONS")))));
+               
Collections.unmodifiableSet(newCaseInsensitiveSet(mergeReplacedStringAttribute(PROPERTY_allowedMethodParams,
 defaultAllowedMethodParams))));
 
        /**
         * Whether a {@code &content=} URL parameter may override the request 
body; inverse of
         * {@code @Rest(disableContentParam)}.
         */
        private final Memoizer<Boolean> allowContentParam = memoizer(() ->
-               !mergeReplacedBooleanAttribute(PROPERTY_disableContentParam, 
env("RestContext.disableContentParam", false)));
+               !mergeReplacedBooleanAttribute(PROPERTY_disableContentParam, 
defaultDisableContentParam));
 
        /**
         * Whether exception stack traces are rendered in error responses; 
resolved from
         * {@code @Rest(renderResponseStackTraces)}.
         */
        private final Memoizer<Boolean> renderResponseStackTraces = memoizer(() 
->
-               
mergeReplacedBooleanAttribute(PROPERTY_renderResponseStackTraces, 
env("RestContext.renderResponseStackTraces", false)));
+               
mergeReplacedBooleanAttribute(PROPERTY_renderResponseStackTraces, 
defaultRenderResponseStackTraces));
 
        /**
         * Whether the resource emits RFC 7807 {@code application/problem+json} 
responses; resolved from
         * {@code @Rest(problemDetails)}.
         */
        private final Memoizer<Boolean> problemDetails = memoizer(() ->
-               mergeReplacedBooleanAttribute(PROPERTY_problemDetails, 
env("RestContext.problemDetails", false)));
+               mergeReplacedBooleanAttribute(PROPERTY_problemDetails, 
defaultProblemDetails));
 
        /**
         * Whether the resource opts into per-request virtual-thread dispatch 
on Java 21+; resolved from
@@ -2174,7 +2248,7 @@ public class RestContext extends Context {
         * than Java 21 the flag is logged once and ignored — see {@link 
#virtualThreadExecutor}.
         */
        private final Memoizer<Boolean> virtualThreadsEnabled = memoizer(() ->
-               mergeReplacedBooleanAttribute(PROPERTY_virtualThreads, 
env("RestContext.virtualThreads", false)));
+               mergeReplacedBooleanAttribute(PROPERTY_virtualThreads, 
defaultVirtualThreads));
 
        /**
         * Configurable async-response timeout (milliseconds) applied by {@code 
AsyncResponseProcessor} to
@@ -2233,14 +2307,14 @@ public class RestContext extends Context {
         * resolved from {@code @Rest(eagerInit)}.
         */
        private final Memoizer<Boolean> eagerInit = memoizer(() ->
-               mergeReplacedBooleanAttribute(PROPERTY_eagerInit, 
env("RestContext.eagerInit", false)));
+               mergeReplacedBooleanAttribute(PROPERTY_eagerInit, 
defaultEagerInit));
 
        /**
         * The request header used for client-version matching; resolved from 
{@code @Rest(clientVersionHeader)},
         * default {@code "Client-Version"}.
         */
        private final Memoizer<String> clientVersionHeader = memoizer(() ->
-               mergeReplacedStringAttribute(PROPERTY_clientVersionHeader, 
env("RestContext.clientVersionHeader", "Client-Version")));
+               mergeReplacedStringAttribute(PROPERTY_clientVersionHeader, 
defaultClientVersionHeader));
 
        /**
         * The {@link UriRelativity} strategy for URI resolution in this 
resource.
@@ -2251,7 +2325,7 @@ public class RestContext extends Context {
         */
        private final Memoizer<UriRelativity> uriRelativity = memoizer(() -> {
                var v = new AtomicReference<>(
-                       parseEnumConstant(UriRelativity.class, 
resolve(emptyIfNull(env("RestContext.uriRelativity").get())))
+                       parseEnumConstant(UriRelativity.class, 
resolve(emptyIfNull(defaultUriRelativity)))
                                .orElse(UriRelativity.RESOURCE)
                );
                
restAnnotationsForPropertySortedByRank(PROPERTY_uriRelativity).forEach(ai -> 
ai.getString(PROPERTY_uriRelativity).filter(StringUtils::isNotBlank).ifPresent(s
 ->
@@ -2268,7 +2342,7 @@ public class RestContext extends Context {
         * blocked by {@code noInherit}. {@code null} means no override.
         */
        private final Memoizer<String> uriAuthority = memoizer(() -> {
-               String local = 
mergeReplacedStringAttribute(PROPERTY_uriAuthority, 
env("RestContext.uriAuthority").orElse(null));
+               String local = 
mergeReplacedStringAttribute(PROPERTY_uriAuthority, 
defaultUriAuthority.orElse(null));
                if (nn(local))
                        return local;
                var pc = parentContext();
@@ -2283,7 +2357,7 @@ public class RestContext extends Context {
         * blocked by {@code noInherit}. {@code null} means no override.
         */
        private final Memoizer<String> uriContext = memoizer(() -> {
-               String local = 
mergeReplacedStringAttribute(PROPERTY_uriContext, 
env("RestContext.uriContext").orElse(null));
+               String local = 
mergeReplacedStringAttribute(PROPERTY_uriContext, 
defaultUriContext.orElse(null));
                if (nn(local))
                        return local;
                var pc = parentContext();
@@ -2299,7 +2373,7 @@ public class RestContext extends Context {
         */
        private final Memoizer<UriResolution> uriResolution = memoizer(() -> {
                var v = new AtomicReference<>(
-                       parseEnumConstant(UriResolution.class, 
resolve(emptyIfNull(env("RestContext.uriResolution").get())))
+                       parseEnumConstant(UriResolution.class, 
resolve(emptyIfNull(defaultUriResolution)))
                                .orElse(UriResolution.ROOT_RELATIVE)
                );
                
restAnnotationsForPropertySortedByRank(PROPERTY_uriResolution).forEach(ai -> 
ai.getString(PROPERTY_uriResolution).filter(StringUtils::isNotBlank).ifPresent(s
 ->
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 96e59eba17..d33808e7b0 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
@@ -19,7 +19,6 @@ package org.apache.juneau.rest;
 import org.apache.juneau.commons.http.MediaType;
 import static org.apache.juneau.commons.reflect.AnnotationTraversal.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
-import static org.apache.juneau.commons.utils.IoUtils.UTF8;
 import static org.apache.juneau.commons.utils.StringUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
@@ -97,17 +96,21 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
 
        private static final AnnotationProvider AP = 
AnnotationProvider.INSTANCE;
 
-       private static Charset envDefaultRestCharset() {
-               return 
env("RestContext.defaultCharset").map(Charset::forName).orElse(UTF8);
-       }
-
-       private static long envDefaultRestMaxInput() {
-               return 
env("RestContext.maxInput").map(RestOpContext::parseMaxInputEnv).orElse(100_000_000L);
-       }
+       /**
+        * Env-driven default charset for this operation, populated by {@link 
ClassInfo#inject(Object, BeanStore)}
+        * before the {@link #defaultCharset} memoizer fires; resolved from 
{@code RestContext.defaultCharset} or
+        * {@code "UTF-8"}.
+        */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.defaultCharset:UTF-8}")
+       private String defaultCharsetName;
 
-       private static long parseMaxInputEnv(String value) {
-               return parseLongWithSuffix(value);
-       }
+       /**
+        * Env-driven default max-input string for this operation, populated by 
{@link ClassInfo#inject(Object, BeanStore)}
+        * before the {@link #maxInput} memoizer fires; resolved from {@code 
RestContext.maxInput} or
+        * {@code "100000000"}.
+        */
+       
@org.apache.juneau.commons.inject.Value("${RestContext.maxInput:100000000}")
+       private String defaultMaxInputString;
 
        /**
         * Internal construction-time state holder.
@@ -288,7 +291,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        if (rv != null && !rv.isEmpty())
                                return Charset.forName(rv);
                }
-               return envDefaultRestCharset();
+               return Charset.forName(defaultCharsetName);
        });
 
        /**
@@ -617,7 +620,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        if (rv != null && !rv.isEmpty())
                                return parseLongWithSuffix(rv);
                }
-               return envDefaultRestMaxInput();
+               return parseLongWithSuffix(defaultMaxInputString);
        });
 
        /**
@@ -1223,6 +1226,10 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        bs.add(HttpPartSerializer.class, getPartSerializer());
                        bs.add(SerializerSet.class, getSerializers());
 
+                       // Inject @Value-annotated env-driven defaults onto 
this RestOpContext instance so that the
+                       // memoizer lambdas (defaultCharset, maxInput) read 
fully resolved values when first invoked.
+                       ClassInfo.of(this).inject(this, bs);
+
                        // The 6 formerly-eager scalar fields are now memoized; 
no eagerness needed here.
                        // Pre-warm httpMethod so it is in the memoizer cache 
for immediate use by compareTo/match.
                        httpMethod.get();
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/convention/BasicVersionResource.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/convention/BasicVersionResource.java
index b1d1362ebc..599ef5ac1d 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/convention/BasicVersionResource.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/convention/BasicVersionResource.java
@@ -16,12 +16,15 @@
  */
 package org.apache.juneau.rest.convention;
 
+import static org.apache.juneau.commons.utils.Utils.*;
+
 import java.io.*;
 import java.net.*;
 import java.util.*;
 import java.util.function.*;
 import java.util.jar.*;
 
+import org.apache.juneau.commons.inject.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
@@ -140,12 +143,25 @@ public class BasicVersionResource {
        public static final String UNKNOWN = "(unknown)";
 
        /**
-        * Creates a new builder.
+        * Creates a new builder, with {@link Value @Value}-annotated fields 
populated through
+        * {@link BeanInstantiator} from the active
+        * {@link org.apache.juneau.commons.settings.Settings Settings} chain.
         *
         * @return A new builder.
         */
        public static Builder create() {
-               return new Builder();
+               return create(BasicBeanStore.INSTANCE);
+       }
+
+       /**
+        * Creates a new builder using the supplied {@link BeanStore} for 
{@link Value @Value}-resolution
+        * and dependency injection.
+        *
+        * @param beanStore The bean store to use for dependency injection.
+        * @return A new builder.
+        */
+       public static Builder create(BeanStore beanStore) {
+               return BeanInstantiator.of(Builder.class, beanStore).run();
        }
 
        private final Map<String,String> info;
@@ -220,7 +236,21 @@ public class BasicVersionResource {
                private final Map<String,String> entries = new 
LinkedHashMap<>();
                private boolean explicit;
 
-               /** Constructor &mdash; package access for {@link 
BasicVersionResource#create()}. */
+               /**
+                * Env-driven default for the {@code javaVersion} entry; 
resolved from the {@code java.version}
+                * system property (defaulting to the literal {@code 
(unknown)}, matching
+                * {@link BasicVersionResource#UNKNOWN}). Populated by {@link 
BeanInstantiator} via
+                * {@link Value @Value} field injection.
+                *
+                * <p>
+                * The default is inlined as a string literal rather than 
referencing {@code UNKNOWN} via
+                * concatenation, per the project-wide rule that every {@code 
@Value} expression is a
+                * fully self-contained string literal.
+                */
+               @Value("${java.version:(unknown)}")
+               String javaVersionDefault;
+
+               /** Constructor &mdash; protected access for {@link 
BasicVersionResource#create()}. */
                protected Builder() {}
 
                /**
@@ -356,7 +386,7 @@ public class BasicVersionResource {
                 * @return This object.
                 */
                public Builder fromJavaVersion() {
-                       entries.putIfAbsent("javaVersion", 
System.getProperty("java.version", UNKNOWN));
+                       entries.putIfAbsent("javaVersion", 
opt(javaVersionDefault).orElse(UNKNOWN));
                        explicit = true;
                        return this;
                }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
index 06c4c5c369..e6633899bb 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
@@ -119,10 +119,19 @@ public class CallLogger {
                ThrownStore thrownStore;
                List<CallLoggerRule> normalRules = list();
                List<CallLoggerRule> debugRules = list();
+
+               @Value("${juneau.restLogger.enabled:ALWAYS}")
                Enablement enabled;
-               Predicate<HttpServletRequest> enabledTest;
+
+               Predicate<HttpServletRequest> enabledTest = x -> false;
+
+               @Value("${juneau.restLogger.requestDetail:STATUS_LINE}")
                CallLoggingDetail requestDetail;
+
+               @Value("${juneau.restLogger.responseDetail:STATUS_LINE}")
                CallLoggingDetail responseDetail;
+
+               @Value("${juneau.restLogger.level:OFF}")
                Level level;
 
                /**
@@ -131,12 +140,19 @@ public class CallLogger {
                 * @param beanStore The bean store to use for creating beans.
                 */
                protected Builder(BeanStore beanStore) {
-                       logger = Logger.getLogger(env(SP_logger, "global"));
-                       enabled = env(SP_enabled, ALWAYS);
-                       enabledTest = x -> false;
-                       requestDetail = env(SP_requestDetail, STATUS_LINE);
-                       responseDetail = env(SP_responseDetail, STATUS_LINE);
-                       level = env(SP_level).map(Level::parse).orElse(OFF);
+               }
+
+               /**
+                * Init method invoked by {@link BeanInstantiator} after 
construction; resolves the default
+                * logger from the {@code juneau.restLogger.logger} property 
(defaulting to {@code "global"})
+                * and installs it as this builder's logger.
+                *
+                * @param loggerName The resolved logger name. Defaulted to 
{@code "global"} when unset.
+                */
+               @Inject
+               public void 
initLoggerFromName(@Value("${juneau.restLogger.logger:global}") String 
loggerName) {
+                       if (logger == null)
+                               logger = Logger.getLogger(loggerName);
                }
 
                /**
@@ -180,8 +196,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the setting is determined via the 
following:
                 * <ul>
-                *      <li><js>{@link CallLogger#SP_enabled 
"juneau.restLogger.enabled"} system property.
-                *      <li><js>{@link CallLogger#SP_enabled 
"JUNEAU_RESTLOGGER_ENABLED"} environment variable.
+                *      <li><js>"juneau.restLogger.enabled"</js> system 
property.
+                *      <li><js>"JUNEAU_RESTLOGGER_ENABLED"</js> environment 
variable.
                 *      <li><js>"ALWAYS"</js>.
                 * </ul>
                 *
@@ -231,8 +247,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the setting is determined via the 
following:
                 * <ul>
-                *      <li><js>{@link CallLogger#SP_level 
"juneau.restLogger.level"} system property.
-                *      <li><js>{@link CallLogger#SP_level 
"JUNEAU_RESTLOGGER_level"} environment variable.
+                *      <li><js>"juneau.restLogger.level"</js> system property.
+                *      <li><js>"JUNEAU_RESTLOGGER_LEVEL"</js> environment 
variable.
                 *      <li><js>"OFF"</js>.
                 * </ul>
                 *
@@ -251,8 +267,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the logger name is determined in the 
following order:
                 * <ol>
-                *      <li><js>{@link CallLogger#SP_logger 
"juneau.restLogger.logger"} system property.
-                *      <li><js>{@link CallLogger#SP_logger 
"JUNEAU_RESTLOGGER_LOGGER"} environment variable.
+                *      <li><js>"juneau.restLogger.logger"</js> system property.
+                *      <li><js>"JUNEAU_RESTLOGGER_LOGGER"</js> environment 
variable.
                 *      <li><js>"global"</js>.
                 * </ol>
                 *
@@ -277,8 +293,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the logger name is determined in the 
following order:
                 * <ol>
-                *      <li><js>{@link CallLogger#SP_logger 
"juneau.restLogger.logger"} system property.
-                *      <li><js>{@link CallLogger#SP_logger 
"JUNEAU_RESTLOGGER_LOGGER"} environment variable.
+                *      <li><js>"juneau.restLogger.logger"</js> system property.
+                *      <li><js>"JUNEAU_RESTLOGGER_LOGGER"</js> environment 
variable.
                 *      <li><js>"global"</js>.
                 * </ol>
                 *
@@ -329,8 +345,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the setting is determined via the 
following:
                 * <ul>
-                *      <li><js>{@link CallLogger#SP_requestDetail 
"juneau.restLogger.requestDetail"} system property.
-                *      <li><js>{@link CallLogger#SP_requestDetail 
"JUNEAU_RESTLOGGER_requestDetail"} environment variable.
+                *      <li><js>"juneau.restLogger.requestDetail"</js> system 
property.
+                *      <li><js>"JUNEAU_RESTLOGGER_REQUESTDETAIL"</js> 
environment variable.
                 *      <li><js>"STATUS_LINE"</js>.
                 * </ul>
                 *
@@ -358,8 +374,8 @@ public class CallLogger {
                 * <p>
                 * If not specified, the setting is determined via the 
following:
                 * <ul>
-                *      <li><js>{@link CallLogger#SP_responseDetail 
"juneau.restLogger.responseDetail"} system property.
-                *      <li><js>{@link CallLogger#SP_responseDetail 
"JUNEAU_RESTLOGGER_responseDetail"} environment variable.
+                *      <li><js>"juneau.restLogger.responseDetail"</js> system 
property.
+                *      <li><js>"JUNEAU_RESTLOGGER_RESPONSEDETAIL"</js> 
environment variable.
                 *      <li><js>"STATUS_LINE"</js>.
                 * </ul>
                 *
@@ -429,80 +445,21 @@ public class CallLogger {
        private static final CallLoggerRule DEFAULT_RULE = 
CallLoggerRule.create(BasicBeanStore.INSTANCE).build();
 
        /**
-        * System property name for the default logger name to use for {@link 
CallLogger} objects.
-        * <p>
-        * Can also use a <c>JUNEAU_RESTLOGGER_LOGGER</c> environment variable.
-        * <p>
-        * If not specified, the default is <js>"global"</js>.
-        */
-       public static final String SP_logger = "juneau.restLogger.logger";
-
-       /**
-        * System property name for the default enablement setting for {@link 
CallLogger} objects.
-        * <p>
-        * Can also use a <c>JUNEAU_RESTLOGGER_ENABLED</c> environment variable.
-        * <p>
-        * The possible values are:
-        * <ul>
-        *      <li>{@link Enablement#ALWAYS "ALWAYS"} (default) - Logging is 
enabled.
-        *      <li>{@link Enablement#NEVER "NEVER"} - Logging is disabled.
-        *      <li>{@link Enablement#CONDITIONAL "CONDITIONALLY"} - Logging is 
enabled if it passes the {@link Builder#enabledTest(Predicate)} test.
-        * </ul>
-        */
-       public static final String SP_enabled = "juneau.restLogger.enabled";
-
-       /**
-        * System property name for the default request detail setting for 
{@link CallLogger} objects.
-        * <p>
-        * Can also use a <c>JUNEAU_RESTLOGGER_REQUESTDETAIL</c> environment 
variable.
-        *
-        * <ul class='values'>
-        *      <li>{@link CallLoggingDetail#STATUS_LINE "STATUS_LINE"} 
(default) - Log only the status line.
-        *      <li>{@link CallLoggingDetail#HEADER "HEADER"} - Log the status 
line and headers.
-        *      <li>{@link CallLoggingDetail#ENTITY "ENTITY"} - Log the status 
line and headers and content if available.
-        * </ul>
-        */
-       public static final String SP_requestDetail = 
"juneau.restLogger.requestDetail";
-
-       /**
-        * System property name for the default response detail setting for 
{@link CallLogger} objects.
-        * <p>
-        * Can also use a <c>JUNEAU_RESTLOGGER_RESPONSEDETAIL</c> environment 
variable.
+        * Static creator.
         *
-        * <ul class='values'>
-        *      <li>{@link CallLoggingDetail#STATUS_LINE "STATUS_LINE"} 
(default) - Log only the status line.
-        *      <li>{@link CallLoggingDetail#HEADER "HEADER"} - Log the status 
line and headers.
-        *      <li>{@link CallLoggingDetail#ENTITY "ENTITY"} - Log the status 
line and headers and content if available.
-        * </ul>
-        */
-       public static final String SP_responseDetail = 
"juneau.restLogger.responseDetail";
-
-       /**
-        * System property name for the logging level setting for {@link 
CallLogger} objects.
         * <p>
-        * Can also use a <c>JUNEAU_RESTLOGGER_LEVEL</c> environment variable.
-        *
-        * <ul class='values'>
-        *      <li>{@link Level#OFF "OFF"} (default)
-        *      <li>{@link Level#SEVERE "SEVERE"}
-        *      <li>{@link Level#WARNING "WARNING"}
-        *      <li>{@link Level#INFO "INFO"}
-        *      <li>{@link Level#CONFIG "CONFIG"}
-        *      <li>{@link Level#FINE "FINE"}
-        *      <li>{@link Level#FINER "FINER"}
-        *      <li>{@link Level#FINEST "FINEST"}
-        * </ul>
-        */
-       public static final String SP_level = "juneau.restLogger.level";
-
-       /**
-        * Static creator.
+        * Routes builder construction through {@link BeanInstantiator} so that 
{@link Value @Value}-annotated
+        * fields and the {@code @Inject}-annotated logger initializer pick up
+        * {@code juneau.restLogger.logger}, {@code juneau.restLogger.enabled}, 
{@code juneau.restLogger.requestDetail},
+        * {@code juneau.restLogger.responseDetail}, and {@code 
juneau.restLogger.level} from the active
+        * {@link org.apache.juneau.commons.settings.Settings} chain (system 
properties &rarr; environment
+        * variables &rarr; registered property sources).
         *
         * @param beanStore The bean store to use for creating beans.
         * @return A new builder for this object.
         */
        public static Builder create(BeanStore beanStore) {
-               return new Builder(beanStore);
+               return BeanInstantiator.of(Builder.class, beanStore).run();
        }
 
        private final Logger logger;
@@ -762,7 +719,7 @@ public class CallLogger {
         * @return A new builder object.
         */
        protected Builder init(BeanStore beanStore) {
-               return new 
Builder(beanStore).logger(beanStore.getBean(Logger.class).orElse(null)).thrownStore(beanStore.getBean(ThrownStore.class).orElse(null));
+               return 
create(beanStore).logger(beanStore.getBean(Logger.class).orElse(null)).thrownStore(beanStore.getBean(ThrownStore.class).orElse(null));
        }
 
        /**
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BctConfiguration_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BctConfiguration_ValueAdoption_Test.java
new file mode 100644
index 0000000000..4b9673ebf7
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BctConfiguration_ValueAdoption_Test.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.junit.bct;
+
+import static org.apache.juneau.junit.bct.BctConfiguration.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.commons.settings.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for {@code @Value}-driven defaults on {@link 
BctConfiguration.Defaults}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default), and {@code Settings.setGlobal}.
+ */
+class BctConfiguration_ValueAdoption_Test {
+
+       @AfterEach
+       void cleanup() {
+               var s = Settings.get();
+               s.unsetGlobal(BCT_SORT_MAPS);
+               s.unsetGlobal(BCT_SORT_COLLECTIONS);
+               System.clearProperty(BCT_SORT_MAPS);
+               System.clearProperty(BCT_SORT_COLLECTIONS);
+       }
+
+       // -------------------- sortMaps --------------------
+
+       @Test
+       void a01_sortMaps_set() {
+               System.setProperty(BCT_SORT_MAPS, "true");
+               assertTrue(BctConfiguration.defaults().isSortMaps());
+       }
+
+       @Test
+       void a02_sortMaps_unset() {
+               assertFalse(BctConfiguration.defaults().isSortMaps());
+       }
+
+       @Test
+       void a03_sortMaps_setGlobal() {
+               Settings.get().setGlobal(BCT_SORT_MAPS, "true");
+               assertTrue(BctConfiguration.defaults().isSortMaps());
+       }
+
+       // -------------------- sortCollections --------------------
+
+       @Test
+       void b01_sortCollections_set() {
+               System.setProperty(BCT_SORT_COLLECTIONS, "true");
+               assertTrue(BctConfiguration.defaults().isSortCollections());
+       }
+
+       @Test
+       void b02_sortCollections_unset() {
+               assertFalse(BctConfiguration.defaults().isSortCollections());
+       }
+
+       @Test
+       void b03_sortCollections_setGlobal() {
+               Settings.get().setGlobal(BCT_SORT_COLLECTIONS, "true");
+               assertTrue(BctConfiguration.defaults().isSortCollections());
+       }
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_ValueAdoption_Test.java
new file mode 100644
index 0000000000..bc986ca13c
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/microservice/Microservice_ValueAdoption_Test.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.microservice;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.*;
+
+import org.apache.juneau.commons.settings.*;
+import org.apache.juneau.testing.annotations.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for the {@code @Value}-driven {@code 
juneau.workingDir} default on
+ * {@link Microservice.Builder}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default = null), and
+ * {@code Settings.setGlobal} override.
+ */
+@JettyMicroserviceTest
+class Microservice_ValueAdoption_Test {
+
+       private static final String SP = "juneau.workingDir";
+
+       @AfterEach
+       void cleanup() {
+               Settings.get().unsetGlobal(SP);
+               System.clearProperty(SP);
+       }
+
+       @Test
+       void a01_workingDir_set() {
+               System.setProperty(SP, "/tmp/todo92-set");
+               assertEquals(new File("/tmp/todo92-set"), 
Microservice.create().workingDir);
+       }
+
+       @Test
+       void a02_workingDir_unset() {
+               assertNull(Microservice.create().workingDir);
+       }
+
+       @Test
+       void a03_workingDir_setGlobal() {
+               Settings.get().setGlobal(SP, "/tmp/todo92-global");
+               assertEquals(new File("/tmp/todo92-global"), 
Microservice.create().workingDir);
+       }
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_ValueAdoption_Test.java
new file mode 100644
index 0000000000..5978b372b5
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_ValueAdoption_Test.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.rest;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.commons.settings.*;
+import org.apache.juneau.rest.annotation.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for the {@code @Value}-driven env-default fields 
on {@link RestContext}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default), and
+ * {@code Settings.setGlobal} override. Validates the {@code @Value} field 
receives the resolved
+ * value at injection time. The downstream {@code 
mergeReplacedStringAttribute} pipeline applies
+ * its own DefaultConfig-driven precedence on top of these fields and is 
exercised by the existing
+ * {@code RestContext}-level tests; this class scopes coverage to the {@code 
@Value} seam itself.
+ */
+class RestContext_ValueAdoption_Test extends TestBase {
+
+       @Rest
+       public static class A {}
+
+       private static final List<String> PROPS = List.of(
+               "RestContext.debugDefault",
+               "RestContext.allowedHeaderParams",
+               "RestContext.allowedMethodHeaders",
+               "RestContext.allowedMethodParams",
+               "RestContext.disableContentParam",
+               "RestContext.renderResponseStackTraces",
+               "RestContext.problemDetails",
+               "RestContext.virtualThreads",
+               "RestContext.eagerInit",
+               "RestContext.clientVersionHeader",
+               "RestContext.uriRelativity",
+               "RestContext.uriAuthority",
+               "RestContext.uriContext",
+               "RestContext.uriResolution",
+               "juneau.restLogger.level"
+       );
+
+       @AfterEach
+       void cleanup() {
+               var s = Settings.get();
+               for (var k : PROPS) {
+                       s.unsetGlobal(k);
+                       System.clearProperty(k);
+               }
+       }
+
+       private RestContext ctx() throws Exception {
+               var resource = new A();
+               return new RestContext(new RestContext.Args(A.class, null, 
null, () -> resource, "", null, null, null, false))
+                       .postInit().postInitChildFirst();
+       }
+
+       @SuppressWarnings("unchecked")
+       private <T> T fld(RestContext c, String name) throws Exception {
+               Field f = RestContext.class.getDeclaredField(name);
+               f.setAccessible(true);
+               return (T)f.get(c);
+       }
+
+       // -------------------- defaultAllowedHeaderParams (String) 
--------------------
+
+       @Test
+       void a01_allowedHeaderParams_set() throws Exception {
+               System.setProperty("RestContext.allowedHeaderParams", 
"X-Custom1,X-Custom2");
+               assertEquals("X-Custom1,X-Custom2", fld(ctx(), 
"defaultAllowedHeaderParams"));
+       }
+
+       @Test
+       void a02_allowedHeaderParams_unset() throws Exception {
+               assertEquals("Accept,Content-Type", fld(ctx(), 
"defaultAllowedHeaderParams"));
+       }
+
+       @Test
+       void a03_allowedHeaderParams_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.allowedHeaderParams", 
"X-Global");
+               assertEquals("X-Global", fld(ctx(), 
"defaultAllowedHeaderParams"));
+       }
+
+       // -------------------- defaultAllowedMethodParams (String) 
--------------------
+
+       @Test
+       void b01_allowedMethodParams_set() throws Exception {
+               System.setProperty("RestContext.allowedMethodParams", 
"GET,POST");
+               assertEquals("GET,POST", fld(ctx(), 
"defaultAllowedMethodParams"));
+       }
+
+       @Test
+       void b02_allowedMethodParams_unset() throws Exception {
+               assertEquals("HEAD,OPTIONS", fld(ctx(), 
"defaultAllowedMethodParams"));
+       }
+
+       @Test
+       void b03_allowedMethodParams_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.allowedMethodParams", 
"PUT");
+               assertEquals("PUT", fld(ctx(), "defaultAllowedMethodParams"));
+       }
+
+       // -------------------- defaultDisableContentParam (boolean) 
--------------------
+
+       @Test
+       void c01_disableContentParam_set() throws Exception {
+               System.setProperty("RestContext.disableContentParam", "true");
+               assertTrue(this.<Boolean>fld(ctx(), 
"defaultDisableContentParam"));
+       }
+
+       @Test
+       void c02_disableContentParam_unset() throws Exception {
+               assertFalse(this.<Boolean>fld(ctx(), 
"defaultDisableContentParam"));
+       }
+
+       @Test
+       void c03_disableContentParam_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.disableContentParam", 
"true");
+               assertTrue(this.<Boolean>fld(ctx(), 
"defaultDisableContentParam"));
+       }
+
+       // -------------------- defaultRenderResponseStackTraces (boolean) 
--------------------
+
+       @Test
+       void d01_renderResponseStackTraces_set() throws Exception {
+               System.setProperty("RestContext.renderResponseStackTraces", 
"true");
+               assertTrue(this.<Boolean>fld(ctx(), 
"defaultRenderResponseStackTraces"));
+       }
+
+       @Test
+       void d02_renderResponseStackTraces_unset() throws Exception {
+               assertFalse(this.<Boolean>fld(ctx(), 
"defaultRenderResponseStackTraces"));
+       }
+
+       @Test
+       void d03_renderResponseStackTraces_setGlobal() throws Exception {
+               
Settings.get().setGlobal("RestContext.renderResponseStackTraces", "true");
+               assertTrue(this.<Boolean>fld(ctx(), 
"defaultRenderResponseStackTraces"));
+       }
+
+       // -------------------- defaultProblemDetails (boolean) 
--------------------
+
+       @Test
+       void e01_problemDetails_set() throws Exception {
+               System.setProperty("RestContext.problemDetails", "true");
+               assertTrue(this.<Boolean>fld(ctx(), "defaultProblemDetails"));
+       }
+
+       @Test
+       void e02_problemDetails_unset() throws Exception {
+               assertFalse(this.<Boolean>fld(ctx(), "defaultProblemDetails"));
+       }
+
+       @Test
+       void e03_problemDetails_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.problemDetails", "true");
+               assertTrue(this.<Boolean>fld(ctx(), "defaultProblemDetails"));
+       }
+
+       // -------------------- defaultClientVersionHeader (String) 
--------------------
+
+       @Test
+       void f01_clientVersionHeader_set() throws Exception {
+               System.setProperty("RestContext.clientVersionHeader", 
"X-API-Version");
+               assertEquals("X-API-Version", fld(ctx(), 
"defaultClientVersionHeader"));
+       }
+
+       @Test
+       void f02_clientVersionHeader_unset() throws Exception {
+               assertEquals("Client-Version", fld(ctx(), 
"defaultClientVersionHeader"));
+       }
+
+       @Test
+       void f03_clientVersionHeader_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.clientVersionHeader", 
"X-Global-Version");
+               assertEquals("X-Global-Version", fld(ctx(), 
"defaultClientVersionHeader"));
+       }
+
+       // -------------------- defaultUriAuthority (Optional<String>) 
--------------------
+
+       @Test
+       void g01_uriAuthority_set() throws Exception {
+               System.setProperty("RestContext.uriAuthority", 
"https://example.org";);
+               Optional<String> v = fld(ctx(), "defaultUriAuthority");
+               assertEquals(Optional.of("https://example.org";), v);
+       }
+
+       @Test
+       void g02_uriAuthority_unset() throws Exception {
+               Optional<String> v = fld(ctx(), "defaultUriAuthority");
+               assertTrue(v.isEmpty());
+       }
+
+       @Test
+       void g03_uriAuthority_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.uriAuthority", 
"https://global.example.org";);
+               Optional<String> v = fld(ctx(), "defaultUriAuthority");
+               assertEquals(Optional.of("https://global.example.org";), v);
+       }
+
+       // -------------------- defaultUriContext (Optional<String>) 
--------------------
+
+       @Test
+       void h01_uriContext_set() throws Exception {
+               System.setProperty("RestContext.uriContext", "/api");
+               Optional<String> v = fld(ctx(), "defaultUriContext");
+               assertEquals(Optional.of("/api"), v);
+       }
+
+       @Test
+       void h02_uriContext_unset() throws Exception {
+               Optional<String> v = fld(ctx(), "defaultUriContext");
+               assertTrue(v.isEmpty());
+       }
+
+       @Test
+       void h03_uriContext_setGlobal() throws Exception {
+               Settings.get().setGlobal("RestContext.uriContext", "/global");
+               Optional<String> v = fld(ctx(), "defaultUriContext");
+               assertEquals(Optional.of("/global"), v);
+       }
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator_ValueAdoption_Test.java
new file mode 100644
index 0000000000..6940add46e
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/auth/jwt/JwtTokenValidator_ValueAdoption_Test.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.rest.auth.jwt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.time.*;
+
+import org.apache.juneau.commons.settings.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for {@code @Value}-driven defaults on {@link 
JwtTokenValidator.Builder}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default), and {@code Settings.setGlobal}.
+ */
+class JwtTokenValidator_ValueAdoption_Test {
+
+       private static final String SP = "juneau.jwt.jwksCacheTtl";
+
+       @AfterEach
+       void cleanup() {
+               Settings.get().unsetGlobal(SP);
+               System.clearProperty(SP);
+       }
+
+       @Test
+       void a01_jwksCacheTtl_set() {
+               System.setProperty(SP, "PT10M");
+               assertEquals(Duration.ofMinutes(10), 
JwtTokenValidator.create().jwksCacheTtl);
+       }
+
+       @Test
+       void a02_jwksCacheTtl_unset() {
+               assertEquals(Duration.ofMinutes(5), 
JwtTokenValidator.create().jwksCacheTtl);
+       }
+
+       @Test
+       void a03_jwksCacheTtl_setGlobal() {
+               Settings.get().setGlobal(SP, "PT15M");
+               assertEquals(Duration.ofMinutes(15), 
JwtTokenValidator.create().jwksCacheTtl);
+       }
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/convention/BasicVersionResource_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/convention/BasicVersionResource_ValueAdoption_Test.java
new file mode 100644
index 0000000000..dcb0f0c049
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/convention/BasicVersionResource_ValueAdoption_Test.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.rest.convention;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.commons.settings.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for the {@code @Value}-driven {@code java.version} 
default on
+ * {@link BasicVersionResource.Builder}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default = JVM-resolved),
+ * and {@code Settings.setGlobal} override.
+ *
+ * <p>
+ * Note: the unset case for this builder always yields a non-blank value 
because {@code java.version}
+ * is set by the JVM itself; the assertion simply verifies that the 
JVM-supplied value is what flows
+ * through {@code @Value} resolution.
+ */
+class BasicVersionResource_ValueAdoption_Test {
+
+       private static final String SP = "java.version";
+
+       private String saved;
+
+       @BeforeEach
+       void capture() {
+               saved = System.getProperty(SP);
+       }
+
+       @AfterEach
+       void cleanup() {
+               Settings.get().unsetGlobal(SP);
+               if (saved != null)
+                       System.setProperty(SP, saved);
+               else
+                       System.clearProperty(SP);
+       }
+
+       @Test
+       void a01_javaVersion_set() {
+               System.setProperty(SP, "todo92-set");
+               var v = 
BasicVersionResource.create().fromJavaVersion().build().getInfoMap();
+               assertEquals("todo92-set", v.get("javaVersion"));
+       }
+
+       @Test
+       void a02_javaVersion_unset() {
+               var v = 
BasicVersionResource.create().fromJavaVersion().build().getInfoMap();
+               assertEquals(saved, v.get("javaVersion"));
+       }
+
+       @Test
+       void a03_javaVersion_setGlobal() {
+               Settings.get().setGlobal(SP, "todo92-global");
+               var v = 
BasicVersionResource.create().fromJavaVersion().build().getInfoMap();
+               assertEquals("todo92-global", v.get("javaVersion"));
+       }
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/logger/CallLogger_ValueAdoption_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/logger/CallLogger_ValueAdoption_Test.java
new file mode 100644
index 0000000000..da994341de
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/logger/CallLogger_ValueAdoption_Test.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.rest.logger;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.List;
+import java.util.logging.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.TestBase;
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.commons.settings.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * TODO-92 acceptance tests for {@code @Value}-driven defaults on {@link 
CallLogger.Builder}.
+ *
+ * <p>
+ * 3-test triad per migrated field per OQA #4 — system property set, unset 
(default), and {@code Settings.setGlobal}.
+ */
+class CallLogger_ValueAdoption_Test extends TestBase {
+
+       private static final String SP_LOGGER = "juneau.restLogger.logger";
+       private static final String SP_ENABLED = "juneau.restLogger.enabled";
+       private static final String SP_REQUEST_DETAIL = 
"juneau.restLogger.requestDetail";
+       private static final String SP_RESPONSE_DETAIL = 
"juneau.restLogger.responseDetail";
+       private static final String SP_LEVEL = "juneau.restLogger.level";
+
+       private static final List<String> ALL_PROPS = List.of(
+               SP_LOGGER, SP_ENABLED, SP_REQUEST_DETAIL, SP_RESPONSE_DETAIL, 
SP_LEVEL);
+
+       @AfterEach
+       void cleanup() {
+               var s = Settings.get();
+               for (var k : ALL_PROPS) {
+                       s.unsetGlobal(k);
+                       System.clearProperty(k);
+               }
+       }
+
+       private CallLogger.Builder build() {
+               return CallLogger.create(new BasicBeanStore(null));
+       }
+
+       // -------------------- enabled --------------------
+
+       @Test
+       void a01_enabled_set() {
+               System.setProperty(SP_ENABLED, "NEVER");
+               assertEquals(Enablement.NEVER, build().enabled);
+       }
+
+       @Test
+       void a02_enabled_unset() {
+               assertEquals(Enablement.ALWAYS, build().enabled);
+       }
+
+       @Test
+       void a03_enabled_setGlobal() {
+               Settings.get().setGlobal(SP_ENABLED, "CONDITIONAL");
+               assertEquals(Enablement.CONDITIONAL, build().enabled);
+       }
+
+       // -------------------- requestDetail --------------------
+
+       @Test
+       void b01_requestDetail_set() {
+               System.setProperty(SP_REQUEST_DETAIL, "HEADER");
+               assertEquals(CallLoggingDetail.HEADER, build().requestDetail);
+       }
+
+       @Test
+       void b02_requestDetail_unset() {
+               assertEquals(CallLoggingDetail.STATUS_LINE, 
build().requestDetail);
+       }
+
+       @Test
+       void b03_requestDetail_setGlobal() {
+               Settings.get().setGlobal(SP_REQUEST_DETAIL, "ENTITY");
+               assertEquals(CallLoggingDetail.ENTITY, build().requestDetail);
+       }
+
+       // -------------------- responseDetail --------------------
+
+       @Test
+       void c01_responseDetail_set() {
+               System.setProperty(SP_RESPONSE_DETAIL, "HEADER");
+               assertEquals(CallLoggingDetail.HEADER, build().responseDetail);
+       }
+
+       @Test
+       void c02_responseDetail_unset() {
+               assertEquals(CallLoggingDetail.STATUS_LINE, 
build().responseDetail);
+       }
+
+       @Test
+       void c03_responseDetail_setGlobal() {
+               Settings.get().setGlobal(SP_RESPONSE_DETAIL, "ENTITY");
+               assertEquals(CallLoggingDetail.ENTITY, build().responseDetail);
+       }
+
+       // -------------------- level --------------------
+
+       @Test
+       void d01_level_set() {
+               System.setProperty(SP_LEVEL, "WARNING");
+               assertEquals(Level.WARNING, build().level);
+       }
+
+       @Test
+       void d02_level_unset() {
+               assertEquals(Level.OFF, build().level);
+       }
+
+       @Test
+       void d03_level_setGlobal() {
+               Settings.get().setGlobal(SP_LEVEL, "INFO");
+               assertEquals(Level.INFO, build().level);
+       }
+
+       // -------------------- logger (name -> Logger via @Inject method) 
--------------------
+
+       @Test
+       void e01_logger_set() {
+               System.setProperty(SP_LOGGER, "TODO92.set");
+               var logger = build().logger;
+               assertNotNull(logger);
+               assertEquals("TODO92.set", logger.getName());
+       }
+
+       @Test
+       void e02_logger_unset() {
+               var logger = build().logger;
+               assertNotNull(logger);
+               assertEquals("global", logger.getName());
+       }
+
+       @Test
+       void e03_logger_setGlobal() {
+               Settings.get().setGlobal(SP_LOGGER, "TODO92.global");
+               var logger = build().logger;
+               assertNotNull(logger);
+               assertEquals("TODO92.global", logger.getName());
+       }
+}

Reply via email to