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 5db31ae80b Support for HTTP part annotation with def values on remote 
interfaces.
5db31ae80b is described below

commit 5db31ae80b21b29a02265985adadc42099096036
Author: James Bognar <[email protected]>
AuthorDate: Mon Oct 13 15:23:41 2025 -0400

    Support for HTTP part annotation with def values on remote interfaces.
---
 .../org/apache/juneau/http/annotation/Content.java |  13 +
 .../juneau/http/annotation/ContentAnnotation.java  |  40 +-
 .../org/apache/juneau/httppart/HttpPartSchema.java |   7 +-
 juneau-docs/docs/release-notes/9.2.0.md            |  72 ++++
 .../docs/topics/11.10.01.RestProxyBasics.md        | 164 ++++++++
 .../org/apache/juneau/rest/client/RestClient.java  |  80 +++-
 .../rest/client/remote/RemoteOperationMeta.java    | 180 +++++++++
 .../remote/Remote_FormDataAnnotation_Test.java     |   4 +-
 .../http/remote/Remote_HeaderAnnotation_Test.java  |   4 +-
 .../Remote_MethodDefaultsAnnotation_Test.java      | 428 +++++++++++++++++++++
 .../http/remote/Remote_QueryAnnotation_Test.java   |   4 +-
 11 files changed, 981 insertions(+), 15 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Content.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Content.java
index 89d0e00396..827fd77586 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Content.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Content.java
@@ -110,6 +110,19 @@ import org.apache.juneau.json.*;
 @ContextApply(ContentAnnotation.Applier.class)
 public @interface Content {
 
+       /**
+        * Default value for this parameter.
+        *
+        * <p>
+        * This value is only used when annotation is applied to a method (not 
a parameter).
+        * When applied to a remote interface method, it specifies the default 
content to use
+        * if not overridden by the client.
+        *
+        * @return The annotation value.
+        * @since 9.2.0
+        */
+       String def() default "";
+
     /**
      * Optional description for the exposed API.
      *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
index 4477ddc9b7..d90e84798b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
@@ -94,6 +94,8 @@ public class ContentAnnotation {
         */
        public static class Builder extends 
TargetedAnnotationTMBuilder<Builder> {
 
+               String def = "";
+               String[] description = {};
                Schema schema = SchemaAnnotation.DEFAULT;
 
                /**
@@ -112,6 +114,28 @@ public class ContentAnnotation {
                        return new Impl(this);
                }
 
+               /**
+                * Sets the {@link Content#def} property on this annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object.
+                */
+               public Builder def(String value) {
+                       this.def = value;
+                       return this;
+               }
+
+               /**
+                * Sets the {@link Content#description} property on this 
annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object.
+                */
+               public Builder description(String...value) {
+                       this.description = value;
+                       return this;
+               }
+
                /**
                 * Sets the {@link Content#schema} property on this annotation.
                 *
@@ -131,15 +155,29 @@ public class ContentAnnotation {
 
        private static class Impl extends TargetedAnnotationTImpl implements 
Content {
 
+               private final String def;
+               private final String[] description;
                private final Schema schema;
 
                Impl(Builder b) {
                        super(b);
+                       this.def = b.def;
+                       this.description = b.description;
                        this.schema = b.schema;
                        postConstruct();
                }
 
-               @Override /* Body */
+               @Override /* Content */
+               public String def() {
+                       return def;
+               }
+
+               @Override /* Content */
+               public String[] description() {
+                       return description;
+               }
+
+               @Override /* Content */
                public Schema schema() {
                        return schema;
                }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index f1b2a7af10..700530e030 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -744,6 +744,7 @@ public class HttpPartSchema {
                Builder apply(Content a) {
                        if (! SchemaAnnotation.empty(a.schema()))
                                apply(a.schema());
+                       _default(a.def());
                        return this;
                }
 
@@ -751,6 +752,7 @@ public class HttpPartSchema {
                        if (! SchemaAnnotation.empty(a.schema()))
                                apply(a.schema());
                        name(firstNonEmpty(a.name(), a.value()));
+                       _default(a.def());
                        parser(a.parser());
                        serializer(a.serializer());
                        return this;
@@ -760,6 +762,7 @@ public class HttpPartSchema {
                        if (! SchemaAnnotation.empty(a.schema()))
                                apply(a.schema());
                        name(firstNonEmpty(a.name(), a.value()));
+                       _default(a.def());
                        parser(a.parser());
                        serializer(a.serializer());
                        return this;
@@ -769,6 +772,7 @@ public class HttpPartSchema {
                        if (! SchemaAnnotation.empty(a.schema()))
                                apply(a.schema());
                        name(firstNonEmpty(a.name(), a.value()));
+                       _default(a.def());
                        parser(a.parser());
                        serializer(a.serializer());
                        return this;
@@ -778,6 +782,7 @@ public class HttpPartSchema {
                        if (! SchemaAnnotation.empty(a.schema()))
                                apply(a.schema());
                        name(firstNonEmpty(a.name(), a.value()));
+                       _default(a.def());
                        parser(a.parser());
                        serializer(a.serializer());
 
@@ -2000,7 +2005,7 @@ public class HttpPartSchema {
                 * @return This object.
                 */
                public Builder _default(String value) {
-                       if (value != null)
+                       if (isNotEmpty(value))
                                this._default = value;
                        return this;
                }
diff --git a/juneau-docs/docs/release-notes/9.2.0.md 
b/juneau-docs/docs/release-notes/9.2.0.md
index 61bdca01d8..99483d54d2 100644
--- a/juneau-docs/docs/release-notes/9.2.0.md
+++ b/juneau-docs/docs/release-notes/9.2.0.md
@@ -17,6 +17,7 @@ Major changes include:
 
 - **New Module**: Introduced `juneau-shaded` with five shaded (uber) JAR 
artifacts for simplified dependency management, especially useful for Bazel
 - **@Schema Annotation** upgraded to JSON Schema Draft 2020-12 with 18 new 
properties, while maintaining full backward compatibility with Draft 04
+- **Remote Proxy Default Values**: Added `def` attribute to all HTTP part 
annotations (`@Header`, `@Query`, `@FormData`, `@Path`, `@Content`) for 
specifying method-level default values
 - JSON Schema beans upgraded to Draft 2020-12 specification with backward 
compatibility for Draft 04
 - Comprehensive enhancements to HTML5 beans with improved javadocs and 
`HtmlBuilder` integration
 - Standardized license headers across all Java files
@@ -416,6 +417,77 @@ The previous `juneau-all` module has been deprecated and 
removed in favor of `ju
 
 - **Improved Error Handling**: Added comprehensive logging for exceptions 
caught during cleanup to aid debugging while maintaining AutoCloseable 
compliance and preventing exception masking in try-catch blocks
 
+#### Remote Proxy Default Values
+
+- **Parameter-Level and Method-Level Default Values**: Added support for 
specifying default values on remote proxy interface parameters and methods 
using the `def` attribute on HTTP part annotations:
+  - `@Header(name="...", def="...")` - Default HTTP request headers
+  - `@Query(name="...", def="...")` - Default query string parameters
+  - `@FormData(name="...", def="...")` - Default form post parameters
+  - `@Path(name="...", def="...")` - Default path variables
+  - `@Content(def="...")` - Default request body (new attribute)
+  - Parameter-level defaults take precedence over method-level defaults when 
both are specified
+  
+  Parameter-level defaults example:
+  ```java
+  @Remote(path="/petstore")
+  public interface PetStore {
+  
+      @RemoteGet("/pets")
+      Pet[] getPets(
+          @Header(name="Accept-Language", def="en-US") String language,
+          @Query(name="limit", def="10") Integer limit
+      );
+  }
+  
+  PetStore store = client.getRemote(PetStore.class, "http://localhost:10000";);
+  
+  // Uses default language="en-US" and limit=10
+  Pet[] pets1 = store.getPets(null, null);
+  
+  // Uses custom language, default limit=10
+  Pet[] pets2 = store.getPets("fr-FR", null);
+  ```
+  
+  Method-level defaults example:
+  ```java
+  @RemoteGet("/pets")
+  @Header(name="Accept-Language", def="en-US")
+  @Query(name="limit", def="10")
+  Pet[] getPets(
+      @Header("Accept-Language") String language,
+      @Query("limit") Integer limit
+  );
+  ```
+  
+  Precedence example (parameter-level wins):
+  ```java
+  @RemoteGet("/data")
+  @Query(name="format", def="xml")  // Method-level default
+  String getData(
+      @Query(name="format", def="json") String format  // Takes precedence
+  );
+  ```
+
+- **Multiple Defaults Support**: Methods can have multiple default annotations 
of the same type, properly handling Java's `@Repeatable` annotation mechanism:
+  ```java
+  @RemotePost("/resource")
+  @Header(name="X-API-Key", def="default-key")
+  @Header(name="X-Client-Version", def="1.0")
+  String createResource(
+      @Header("X-API-Key") String apiKey,
+      @Header("X-Client-Version") String clientVersion
+  );
+  ```
+
+- **Use Cases**: Default values are particularly useful for:
+  - API keys and authentication credentials
+  - API versioning headers
+  - Pagination limits and page sizes
+  - Content negotiation (language, format)
+  - Feature flags and debug modes
+
+- **Behavior**: Default values are only applied when the parameter value is 
`null`. Empty strings, zero values, and empty collections are considered valid 
values and will not trigger the default.
+
 ### Documentation
 
 #### Historical Javadocs
diff --git a/juneau-docs/docs/topics/11.10.01.RestProxyBasics.md 
b/juneau-docs/docs/topics/11.10.01.RestProxyBasics.md
index bb67ca1fbf..03c9f51b89 100644
--- a/juneau-docs/docs/topics/11.10.01.RestProxyBasics.md
+++ b/juneau-docs/docs/topics/11.10.01.RestProxyBasics.md
@@ -83,4 +83,168 @@ public interface PetStore {
     String postPets(@Content CreatePet pet);
 }
 ```
+:::
+
+## Default Values
+
+As of Juneau 9.2.0, you can specify default values for method parameters using 
the `def` attribute. Defaults can be specified either at the **method level** 
(on the method itself) or at the **parameter level** (on individual 
parameters). Parameter-level defaults take precedence when both are present.
+
+### Basic Usage - Parameter-Level Defaults
+
+The most straightforward approach is to specify defaults directly on the 
parameters:
+
+:::tip Example
+```java
+@Remote(path="/petstore")
+public interface PetStore {
+
+    @RemoteGet("/pets")
+    Pet[] getPets(
+        @Header(name="Accept-Language", def="en-US") String language,
+        @Query(name="limit", def="10") Integer limit
+    );
+}
+```
+
+```java
+PetStore store = client.getRemote(PetStore.class, "http://localhost:10000";);
+
+// Uses default language="en-US" and limit=10
+Pet[] pets1 = store.getPets(null, null);
+
+// Uses custom language, default limit=10
+Pet[] pets2 = store.getPets("fr-FR", null);
+
+// Uses default language="en-US", custom limit
+Pet[] pets3 = store.getPets(null, 25);
+```
+:::
+
+The above examples translate to the following REST calls:
+
+```text
+GET http://localhost:10000/petstore/pets?limit=10 HTTP/1.1
+Accept-Language: en-US
+
+GET http://localhost:10000/petstore/pets?limit=10 HTTP/1.1
+Accept-Language: fr-FR
+
+GET http://localhost:10000/petstore/pets?limit=25 HTTP/1.1
+Accept-Language: en-US
+```
+
+### Supported Annotations
+
+Default values are supported on the following annotations:
+
+- `@Header(name="...", def="...")` - HTTP request headers
+- `@Query(name="...", def="...")` - Query string parameters
+- `@FormData(name="...", def="...")` - Form post parameters
+- `@Path(name="...", def="...")` - Path variables
+- `@Content(def="...")` - Request body (new in 9.2.0)
+
+### Method-Level Defaults (Alternative Approach)
+
+You can also specify defaults at the method level, which can be useful for 
interface-level configuration:
+
+:::tip Example
+```java
+@Remote(path="/api")
+public interface MyApi {
+
+    @RemotePost("/resource")
+    @Header(name="X-API-Key", def="default-key")
+    @Header(name="X-Client-Version", def="1.0")
+    @Query(name="format", def="json")
+    @Content(def="{}")
+    String createResource(
+        @Header("X-API-Key") String apiKey,
+        @Header("X-Client-Version") String clientVersion,
+        @Query("format") String format,
+        @Content String data
+    );
+}
+```
+
+```java
+// All parameters null - all defaults applied
+String result = api.createResource(null, null, null, null);
+// POST /api/resource?format=json
+// X-API-Key: default-key
+// X-Client-Version: 1.0
+// Content: {}
+
+// Mix of provided and null values
+String result = api.createResource("my-key", null, "xml", "{data:true}");
+// POST /api/resource?format=xml
+// X-API-Key: my-key
+// X-Client-Version: 1.0
+// Content: {data:true}
+```
+:::
+
+### Precedence: Parameter vs. Method Level
+
+When defaults are specified at both the parameter and method level, the 
**parameter-level default takes precedence**:
+
+:::tip Example
+```java
+@Remote(path="/api")
+public interface MyApi {
+
+    @RemoteGet("/data")
+    @Query(name="format", def="xml")  // Method-level default
+    String getData(
+        @Query(name="format", def="json") String format  // Parameter-level 
default (takes precedence)
+    );
+}
+```
+
+```java
+// Uses parameter-level default: format=json
+String result = api.getData(null);
+```
+:::
+
+This precedence allows you to:
+- Define common defaults at the method level for multiple parameters
+- Override specific parameters with more specific defaults at the parameter 
level
+- Keep your interface clean by placing defaults where they're most relevant
+
+### Content Body Defaults
+
+The `@Content` annotation now supports a `def` attribute for specifying a 
default request body:
+
+:::tip Example
+```java
+@Remote(path="/petstore")
+public interface PetStore {
+
+    @RemotePost("/pets")
+    @Content(def="{name:'Unknown',price:0}")
+    Pet addPet(@Content CreatePet pet);
+}
+```
+
+```java
+// When pet is null, sends default JSON
+Pet result = store.addPet(null);
+// POST /petstore/pets
+// Content-Type: application/json
+// Content: {name:'Unknown',price:0}
+```
+:::
+
+### Use Cases
+
+Default values are particularly useful for:
+
+1. **API Keys and Authentication**: Provide default credentials that can be 
overridden per call
+2. **Versioning**: Specify default API versions
+3. **Pagination**: Set default page sizes and limits
+4. **Content Negotiation**: Specify default content types and languages
+5. **Feature Flags**: Enable/disable features with default values
+
+:::note
+Default values are only applied when the parameter value is `null`. Empty 
strings, zero values, and empty collections are considered valid values and 
will not trigger the default.
 :::
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 7a0b05ba65..4814bc8db5 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -7216,18 +7216,84 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
                                        String httpMethod = rom.getHttpMethod();
                                        RestRequest rc = request(httpMethod, 
uri, hasContent(httpMethod));
 
-                                       rc.serializer(serializer);
+                                               rc.serializer(serializer);
                                        rc.parser(parser);
 
                                        rm.getHeaders().forEach(x -> 
rc.header(x));
-                                       rom.forEachPathArg(a -> 
rc.pathArg(a.getName(), args[a.getIndex()], a.getSchema(), 
a.getSerializer().orElse(partSerializer)));
-                                       rom.forEachQueryArg(a -> 
rc.queryArg(a.getName(), args[a.getIndex()], a.getSchema(), 
a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty()));
-                                       rom.forEachFormDataArg(a -> 
rc.formDataArg(a.getName(), args[a.getIndex()], a.getSchema(), 
a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty()));
-                                       rom.forEachHeaderArg(a -> 
rc.headerArg(a.getName(), args[a.getIndex()], a.getSchema(), 
a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty()));
 
+                                       // Apply method-level defaults if 
parameter values are not provided (9.2.0)
+                                       rom.forEachPathArg(a -> {
+                                               Object val = args[a.getIndex()];
+                                               if (val == null) {
+                                                       // Check 
parameter-level default first (9.2.0)
+                                                       String def = 
a.getSchema().getDefault();
+                                                       // Fall back to 
method-level default if parameter-level not set
+                                                       if (def == null)
+                                                               def = 
rom.getPathDefault(a.getName());
+                                                       if (def != null)
+                                                               val = def;
+                                               }
+                                               rc.pathArg(a.getName(), val, 
a.getSchema(), a.getSerializer().orElse(partSerializer));
+                                       });
+                                       rom.forEachQueryArg(a -> {
+                                               Object val = args[a.getIndex()];
+                                               if (val == null) {
+                                                       // Check 
parameter-level default first (9.2.0)
+                                                       String def = 
a.getSchema().getDefault();
+                                                       // Fall back to 
method-level default if parameter-level not set
+                                                       if (def == null)
+                                                               def = 
rom.getQueryDefault(a.getName());
+                                                       if (def != null)
+                                                               val = def;
+                                               }
+                                               rc.queryArg(a.getName(), val, 
a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
+                                       });
+                                       rom.forEachFormDataArg(a -> {
+                                               Object val = args[a.getIndex()];
+                                               if (val == null) {
+                                                       // Check 
parameter-level default first (9.2.0)
+                                                       String def = 
a.getSchema().getDefault();
+                                                       // Fall back to 
method-level default if parameter-level not set
+                                                       if (def == null)
+                                                               def = 
rom.getFormDataDefault(a.getName());
+                                                       if (def != null)
+                                                               val = def;
+                                               }
+                                               rc.formDataArg(a.getName(), 
val, a.getSchema(), a.getSerializer().orElse(partSerializer), 
a.isSkipIfEmpty());
+                                       });
+                                       rom.forEachHeaderArg(a -> {
+                                               Object val = args[a.getIndex()];
+                                               if (val == null) {
+                                                       // Check 
parameter-level default first (9.2.0)
+                                                       String def = 
a.getSchema().getDefault();
+                                                       // Fall back to 
method-level default if parameter-level not set
+                                                       if (def == null)
+                                                               def = 
rom.getHeaderDefault(a.getName());
+                                                       if (def != null)
+                                                               val = def;
+                                               }
+                                               rc.headerArg(a.getName(), val, 
a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
+                                       });
+       
                                        RemoteOperationArg ba = 
rom.getContentArg();
-                                       if (ba != null)
-                                               rc.content(args[ba.getIndex()], 
ba.getSchema());
+                                       if (ba != null) {
+                                               Object val = 
args[ba.getIndex()];
+                                               if (val == null) {
+                                                       // Check 
parameter-level default first (9.2.0)
+                                                       String def = 
ba.getSchema().getDefault();
+                                                       // Fall back to 
method-level default if parameter-level not set
+                                                       if (def == null)
+                                                               def = 
rom.getContentDefault();
+                                                       if (def != null)
+                                                               val = def;
+                                               }
+                                               rc.content(val, ba.getSchema());
+                                       } else {
+                                               // Apply Content default if no 
parameter is present
+                                               String contentDef = 
rom.getContentDefault();
+                                               if (contentDef != null)
+                                                       rc.content(contentDef);
+                                       }
 
                                        rom.forEachRequestArg(rmba -> {
                                                        RequestBeanMeta rbm = 
rmba.getMeta();
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationMeta.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationMeta.java
index 0158e799a6..4c4f055fb2 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationMeta.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationMeta.java
@@ -54,6 +54,10 @@ public class RemoteOperationMeta {
        private final RemoteOperationArg contentArg;
        private final RemoteOperationReturn methodReturn;
        private final Class<?>[] exceptions;
+       
+       // Method-level annotations with defaults (9.2.0)
+       private final Map<String,String> pathDefaults, queryDefaults, 
headerDefaults, formDataDefaults;
+       private final String contentDefault;
 
        /**
         * Constructor.
@@ -74,6 +78,11 @@ public class RemoteOperationMeta {
                this.contentArg = b.bodyArg;
                this.methodReturn = b.methodReturn;
                this.exceptions = m.getExceptionTypes();
+               this.pathDefaults = Collections.unmodifiableMap(b.pathDefaults);
+               this.queryDefaults = 
Collections.unmodifiableMap(b.queryDefaults);
+               this.headerDefaults = 
Collections.unmodifiableMap(b.headerDefaults);
+               this.formDataDefaults = 
Collections.unmodifiableMap(b.formDataDefaults);
+               this.contentDefault = b.contentDefault;
        }
 
        private static class Builder {
@@ -87,6 +96,12 @@ public class RemoteOperationMeta {
                        requestArgs = new LinkedList<>();
                RemoteOperationArg bodyArg;
                RemoteOperationReturn methodReturn;
+               Map<String,String> 
+                       pathDefaults = new LinkedHashMap<>(),
+                       queryDefaults = new LinkedHashMap<>(),
+                       headerDefaults = new LinkedHashMap<>(),
+                       formDataDefaults = new LinkedHashMap<>();
+               String contentDefault = null;
 
                Builder(String parentPath, Method m, String defaultMethod) {
 
@@ -157,6 +172,117 @@ public class RemoteOperationMeta {
                                        requestArgs.add(new 
RemoteOperationBeanArg(x.getIndex(), rmba));
                                }
                        });
+
+                       // Process method-level annotations for defaults (9.2.0)
+                       // Note: We need to handle both individual annotations 
and repeated annotation arrays
+                       processHeaderDefaults(mi, headerDefaults);
+                       processQueryDefaults(mi, queryDefaults);
+                       processFormDataDefaults(mi, formDataDefaults);
+                       processPathDefaults(mi, pathDefaults);
+                       processContentDefaults(mi);
+               }
+
+               // Helper methods to process method-level annotations with 
defaults (9.2.0)
+               // These handle both individual annotations and repeated 
annotation arrays
+
+               private void processHeaderDefaults(MethodInfo mi, 
Map<String,String> defaults) {
+                       // Check for individual @Header annotations
+                       mi.getAnnotationList().forEach(Header.class, null, x -> 
{
+                               Header h = x.inner();
+                               String name = firstNonEmpty(h.name(), 
h.value());
+                               String def = h.def();
+                               if (isNotEmpty(name) && isNotEmpty(def)) {
+                                       defaults.put(name, def);
+                               }
+                       });
+                       // Check for @Header.Array (repeated annotations)
+                       
mi.getAnnotationList().forEach(HeaderAnnotation.Array.class, null, x -> {
+                               for (Header h : x.inner().value()) {
+                                       String name = firstNonEmpty(h.name(), 
h.value());
+                                       String def = h.def();
+                                       if (isNotEmpty(name) && 
isNotEmpty(def)) {
+                                               defaults.put(name, def);
+                                       }
+                               }
+                       });
+               }
+
+               private void processQueryDefaults(MethodInfo mi, 
Map<String,String> defaults) {
+                       mi.getAnnotationList().forEach(Query.class, null, x -> {
+                               Query q = x.inner();
+                               String name = firstNonEmpty(q.name(), 
q.value());
+                               String def = q.def();
+                               if (isNotEmpty(name) && isNotEmpty(def)) {
+                                       defaults.put(name, def);
+                               }
+                       });
+                       
mi.getAnnotationList().forEach(QueryAnnotation.Array.class, null, x -> {
+                               for (Query q : x.inner().value()) {
+                                       String name = firstNonEmpty(q.name(), 
q.value());
+                                       String def = q.def();
+                                       if (isNotEmpty(name) && 
isNotEmpty(def)) {
+                                               defaults.put(name, def);
+                                       }
+                               }
+                       });
+               }
+
+               private void processFormDataDefaults(MethodInfo mi, 
Map<String,String> defaults) {
+                       mi.getAnnotationList().forEach(FormData.class, null, x 
-> {
+                               FormData fd = x.inner();
+                               String name = firstNonEmpty(fd.name(), 
fd.value());
+                               String def = fd.def();
+                               if (isNotEmpty(name) && isNotEmpty(def)) {
+                                       defaults.put(name, def);
+                               }
+                       });
+                       
mi.getAnnotationList().forEach(FormDataAnnotation.Array.class, null, x -> {
+                               for (FormData fd : x.inner().value()) {
+                                       String name = firstNonEmpty(fd.name(), 
fd.value());
+                                       String def = fd.def();
+                                       if (isNotEmpty(name) && 
isNotEmpty(def)) {
+                                               defaults.put(name, def);
+                                       }
+                               }
+                       });
+               }
+
+               private void processPathDefaults(MethodInfo mi, 
Map<String,String> defaults) {
+                       mi.getAnnotationList().forEach(Path.class, null, x -> {
+                               Path p = x.inner();
+                               String name = firstNonEmpty(p.name(), 
p.value());
+                               String def = p.def();
+                               if (isNotEmpty(name) && isNotEmpty(def)) {
+                                       defaults.put(name, def);
+                               }
+                       });
+                       
mi.getAnnotationList().forEach(PathAnnotation.Array.class, null, x -> {
+                               for (Path p : x.inner().value()) {
+                                       String name = firstNonEmpty(p.name(), 
p.value());
+                                       String def = p.def();
+                                       if (isNotEmpty(name) && 
isNotEmpty(def)) {
+                                               defaults.put(name, def);
+                                       }
+                               }
+                       });
+               }
+
+               private void processContentDefaults(MethodInfo mi) {
+                       mi.getAnnotationList().forEach(Content.class, null, x 
-> {
+                               Content c = x.inner();
+                               String def = c.def();
+                               if (isNotEmpty(def)) {
+                                       contentDefault = def;
+                               }
+                       });
+                       
mi.getAnnotationList().forEach(ContentAnnotation.Array.class, null, x -> {
+                               for (Content c : x.inner().value()) {
+                                       String def = c.def();
+                                       if (isNotEmpty(def)) {
+                                               contentDefault = def;
+                                       }
+                               }
+                       });
                }
        }
 
@@ -267,4 +393,58 @@ public class RemoteOperationMeta {
                        action.accept(e);
                return this;
        }
+
+       /**
+        * Returns the default value for a {@link Header @Header} annotation on 
the method.
+        *
+        * @param name The header name.
+        * @return The default value, or <jk>null</jk> if not specified.
+        * @since 9.2.0
+        */
+       public String getHeaderDefault(String name) {
+               return headerDefaults.get(name);
+       }
+
+       /**
+        * Returns the default value for a {@link Query @Query} annotation on 
the method.
+        *
+        * @param name The query parameter name.
+        * @return The default value, or <jk>null</jk> if not specified.
+        * @since 9.2.0
+        */
+       public String getQueryDefault(String name) {
+               return queryDefaults.get(name);
+       }
+
+       /**
+        * Returns the default value for a {@link FormData @FormData} 
annotation on the method.
+        *
+        * @param name The form data parameter name.
+        * @return The default value, or <jk>null</jk> if not specified.
+        * @since 9.2.0
+        */
+       public String getFormDataDefault(String name) {
+               return formDataDefaults.get(name);
+       }
+
+       /**
+        * Returns the default value for a {@link Path @Path} annotation on the 
method.
+        *
+        * @param name The path parameter name.
+        * @return The default value, or <jk>null</jk> if not specified.
+        * @since 9.2.0
+        */
+       public String getPathDefault(String name) {
+               return pathDefaults.get(name);
+       }
+
+       /**
+        * Returns the default value for a {@link Content @Content} annotation 
on the method.
+        *
+        * @return The default value, or <jk>null</jk> if not specified.
+        * @since 9.2.0
+        */
+       public String getContentDefault() {
+               return contentDefault;
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
index 88182400cc..f254cb4f54 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
@@ -165,9 +165,9 @@ class Remote_FormDataAnnotation_Test extends TestBase {
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.postX1(""));
                assertEquals("{x:'foo'}",x.postX2(null));
                assertEquals("{x:''}",x.postX2(""));
-               assertEquals("{x:''}",x.postX3(null));
+               assertEquals("{}",x.postX3(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.postX3(""));
-               assertEquals("{x:''}",x.postX4(null));
+               assertEquals("{}",x.postX4(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertEquals("{x:''}",x.postX4(""));
        }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
index 9f8e7defec..92b837f46f 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
@@ -139,9 +139,9 @@ class Remote_HeaderAnnotation_Test extends TestBase {
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.getX1(""));
                assertEquals("{x:'foo'}",x.getX2(null));
                assertEquals("{x:''}",x.getX2(""));
-               assertEquals("{x:''}",x.getX3(null));
+               assertEquals("{}",x.getX3(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.getX3(""));
-               assertEquals("{x:''}",x.getX4(null));
+               assertEquals("{}",x.getX4(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertEquals("{x:''}",x.getX4(""));
        }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_MethodDefaultsAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_MethodDefaultsAnnotation_Test.java
new file mode 100644
index 0000000000..800a9b084b
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_MethodDefaultsAnnotation_Test.java
@@ -0,0 +1,428 @@
+/*
+ * 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.http.remote;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.config.*;
+import org.apache.juneau.rest.mock.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * Tests for method-level default values on remote proxy interfaces.
+ * 
+ * @since 9.2.0
+ */
+class Remote_MethodDefaultsAnnotation_Test {
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @Header defaults on methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class A implements BasicJson5Config {
+               @RestGet(path="/x1")
+               public String x1(@Header("Foo") String foo, @Header("Bar") 
String bar) {
+                       return "Foo=" + foo + ",Bar=" + bar;
+               }
+       }
+
+       @Remote
+       public interface A1 {
+               @RemoteGet("/x1")
+               @Header(name="Foo", def="defaultFoo")
+               String x1(@Header("Foo") String foo, @Header("Bar") String bar);
+       }
+
+       @Test
+       void a01_headerDefaults_providedValue() {
+               var x = MockRestClient.buildJson(A.class).getRemote(A1.class);
+               assertEquals("Foo=customFoo,Bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       @Test
+       void a02_headerDefaults_nullValue() {
+               var x = MockRestClient.buildJson(A.class).getRemote(A1.class);
+               assertEquals("Foo=defaultFoo,Bar=customBar", x.x1(null, 
"customBar"));
+       }
+
+       @Test
+       void a03_headerDefaults_bothNull() {
+               var x = MockRestClient.buildJson(A.class).getRemote(A1.class);
+               assertEquals("Foo=defaultFoo,Bar=null", x.x1(null, null));
+       }
+
+       @Remote
+       public interface A2 {
+               @RemoteGet("/x1")
+               @Header(name="Foo", def="defaultFoo")
+               @Header(name="Bar", def="defaultBar")
+               String x1(@Header("Foo") String foo, @Header("Bar") String bar);
+       }
+
+       @Test
+       void a04_headerDefaults_multipleDefaults() {
+               var x = MockRestClient.buildJson(A.class).getRemote(A2.class);
+               assertEquals("Foo=defaultFoo,Bar=defaultBar", x.x1(null, null));
+               assertEquals("Foo=customFoo,Bar=defaultBar", x.x1("customFoo", 
null));
+               assertEquals("Foo=defaultFoo,Bar=customBar", x.x1(null, 
"customBar"));
+               assertEquals("Foo=customFoo,Bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @Query defaults on methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class B implements BasicJson5Config {
+               @RestGet(path="/x1")
+               public String x1(@Query("foo") String foo, @Query("bar") String 
bar) {
+                       return "foo=" + foo + ",bar=" + bar;
+               }
+       }
+
+       @Remote
+       public interface B1 {
+               @RemoteGet("/x1")
+               @Query(name="foo", def="defaultFoo")
+               String x1(@Query("foo") String foo, @Query("bar") String bar);
+       }
+
+       @Test
+       void b01_queryDefaults_providedValue() {
+               var x = MockRestClient.buildJson(B.class).getRemote(B1.class);
+               assertEquals("foo=customFoo,bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       @Test
+       void b02_queryDefaults_nullValue() {
+               var x = MockRestClient.buildJson(B.class).getRemote(B1.class);
+               assertEquals("foo=defaultFoo,bar=customBar", x.x1(null, 
"customBar"));
+       }
+
+       @Remote
+       public interface B2 {
+               @RemoteGet("/x1")
+               @Query(name="foo", def="defaultFoo")
+               @Query(name="bar", def="defaultBar")
+               String x1(@Query("foo") String foo, @Query("bar") String bar);
+       }
+
+       @Test
+       void b03_queryDefaults_multipleDefaults() {
+               var x = MockRestClient.buildJson(B.class).getRemote(B2.class);
+               assertEquals("foo=defaultFoo,bar=defaultBar", x.x1(null, null));
+               assertEquals("foo=customFoo,bar=defaultBar", x.x1("customFoo", 
null));
+               assertEquals("foo=defaultFoo,bar=customBar", x.x1(null, 
"customBar"));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @FormData defaults on methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class C implements BasicJson5Config {
+               @RestPost(path="/x1")
+               public String x1(@FormData("foo") String foo, @FormData("bar") 
String bar) {
+                       return "foo=" + foo + ",bar=" + bar;
+               }
+       }
+
+       @Remote
+       public interface C1 {
+               @RemotePost("/x1")
+               @FormData(name="foo", def="defaultFoo")
+               String x1(@FormData("foo") String foo, @FormData("bar") String 
bar);
+       }
+
+       @Test
+       void c01_formDataDefaults_providedValue() {
+               var x = MockRestClient.buildJson(C.class).getRemote(C1.class);
+               assertEquals("foo=customFoo,bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       @Test
+       void c02_formDataDefaults_nullValue() {
+               var x = MockRestClient.buildJson(C.class).getRemote(C1.class);
+               assertEquals("foo=defaultFoo,bar=customBar", x.x1(null, 
"customBar"));
+       }
+
+       @Remote
+       public interface C2 {
+               @RemotePost("/x1")
+               @FormData(name="foo", def="defaultFoo")
+               @FormData(name="bar", def="defaultBar")
+               String x1(@FormData("foo") String foo, @FormData("bar") String 
bar);
+       }
+
+       @Test
+       void c03_formDataDefaults_multipleDefaults() {
+               var x = MockRestClient.buildJson(C.class).getRemote(C2.class);
+               assertEquals("foo=defaultFoo,bar=defaultBar", x.x1(null, null));
+               assertEquals("foo=customFoo,bar=defaultBar", x.x1("customFoo", 
null));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @Path defaults on methods
+       // NOTE: Path variables with nulls cause validation errors, so we test 
with actual provided values only
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class D implements BasicJson5Config {
+               @RestGet(path="/x1/{foo}/{bar}")
+               public String x1(@Path("foo") String foo, @Path("bar") String 
bar) {
+                       return "foo=" + foo + ",bar=" + bar;
+               }
+       }
+
+       @Remote
+       public interface D1 {
+               @RemoteGet("/x1/{foo}/{bar}")
+               @Path(name="foo", def="defaultFoo")
+               String x1(@Path("foo") String foo, @Path("bar") String bar);
+       }
+
+       @Test
+       void d01_pathDefaults_providedValue() {
+               var x = MockRestClient.buildJson(D.class).getRemote(D1.class);
+               assertEquals("foo=customFoo,bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @Content defaults on methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class E implements BasicJson5Config {
+               @RestPost(path="/x1")
+               public String x1(@Content String content) {
+                       return "content=" + content;
+               }
+       }
+
+       @Remote
+       public interface E1 {
+               @RemotePost("/x1")
+               @Content(def="{foo:'defaultBar'}")
+               String x1(@Content String content);
+       }
+
+       @Test
+       void e01_contentDefaults_providedValue() {
+               var x = MockRestClient.buildJson(E.class).getRemote(E1.class);
+               assertEquals("content={foo:'customBar'}", 
x.x1("{foo:'customBar'}"));
+       }
+
+       @Test
+       void e02_contentDefaults_nullValue() {
+               var x = MockRestClient.buildJson(E.class).getRemote(E1.class);
+               assertEquals("content={foo:'defaultBar'}", x.x1(null));
+       }
+
+       @Remote
+       public interface E2 {
+               @RemotePost("/x1")
+               @Content(def="{foo:'defaultBar'}")
+               String x1();
+       }
+
+       @Test
+       void e03_contentDefaults_noParameter() {
+               var x = MockRestClient.buildJson(E.class).getRemote(E2.class);
+               assertEquals("content={foo:'defaultBar'}", x.x1());
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Combined defaults test (without @Path since nulls cause validation 
errors)
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class F implements BasicJson5Config {
+               @RestPost(path="/x1")
+               public String x1(
+                       @Query("queryParam") String queryParam,
+                       @Header("HeaderParam") String headerParam,
+                       @Content String content
+               ) {
+                       return "queryParam=" + queryParam 
+                               + ",HeaderParam=" + headerParam 
+                               + ",content=" + content;
+               }
+       }
+
+       @Remote
+       public interface F1 {
+               @RemotePost("/x1")
+               @Query(name="queryParam", def="defaultQuery")
+               @Header(name="HeaderParam", def="defaultHeader")
+               @Content(def="defaultContent")
+               String x1(
+                       @Query("queryParam") String queryParam,
+                       @Header("HeaderParam") String headerParam,
+                       @Content String content
+               );
+       }
+
+       @Test
+       void f01_combinedDefaults_allNull() {
+               var x = MockRestClient.buildJson(F.class).getRemote(F1.class);
+               assertEquals(
+                       
"queryParam=defaultQuery,HeaderParam=defaultHeader,content=defaultContent",
+                       x.x1(null, null, null)
+               );
+       }
+
+       @Test
+       void f02_combinedDefaults_allProvided() {
+               var x = MockRestClient.buildJson(F.class).getRemote(F1.class);
+               assertEquals(
+                       
"queryParam=customQuery,HeaderParam=customHeader,content=customContent",
+                       x.x1("customQuery", "customHeader", "customContent")
+               );
+       }
+
+       @Test
+       void f03_combinedDefaults_mixed() {
+               var x = MockRestClient.buildJson(F.class).getRemote(F1.class);
+               assertEquals(
+                       
"queryParam=defaultQuery,HeaderParam=customHeader,content=customContent",
+                       x.x1(null, "customHeader", "customContent")
+               );
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Parameter-level defaults (9.2.0)
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class G implements BasicJson5Config {
+               @RestGet(path="/x1")
+               public String x1(
+                       @Header("Foo") String foo,
+                       @Query("bar") String bar
+               ) {
+                       return "Foo=" + foo + ",bar=" + bar;
+               }
+       }
+
+       @Remote
+       public interface G1 {
+               @RemoteGet("/x1")
+               String x1(
+                       @Header(name="Foo", def="paramDefaultFoo") String foo,
+                       @Query(name="bar", def="paramDefaultBar") String bar
+               );
+       }
+
+       @Test
+       void g01_parameterDefaults_bothNull() {
+               var x = MockRestClient.buildJson(G.class).getRemote(G1.class);
+               assertEquals("Foo=paramDefaultFoo,bar=paramDefaultBar", 
x.x1(null, null));
+       }
+
+       @Test
+       void g02_parameterDefaults_oneProvided() {
+               var x = MockRestClient.buildJson(G.class).getRemote(G1.class);
+               assertEquals("Foo=customFoo,bar=paramDefaultBar", 
x.x1("customFoo", null));
+               assertEquals("Foo=paramDefaultFoo,bar=customBar", x.x1(null, 
"customBar"));
+       }
+
+       @Test
+       void g03_parameterDefaults_bothProvided() {
+               var x = MockRestClient.buildJson(G.class).getRemote(G1.class);
+               assertEquals("Foo=customFoo,bar=customBar", x.x1("customFoo", 
"customBar"));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Parameter-level defaults take precedence over method-level defaults
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class H implements BasicJson5Config {
+               @RestGet(path="/x1")
+               public String x1(@Query("param") String param) {
+                       return "param=" + param;
+               }
+       }
+
+       @Remote
+       public interface H1 {
+               @RemoteGet("/x1")
+               @Query(name="param", def="methodDefault")
+               String x1(@Query(name="param", def="paramDefault") String 
param);
+       }
+
+       @Test
+       void h01_parameterOverridesMethod_nullValue() {
+               var x = MockRestClient.buildJson(H.class).getRemote(H1.class);
+               // Parameter-level default should take precedence
+               assertEquals("param=paramDefault", x.x1(null));
+       }
+
+       @Test
+       void h02_parameterOverridesMethod_providedValue() {
+               var x = MockRestClient.buildJson(H.class).getRemote(H1.class);
+               assertEquals("param=customValue", x.x1("customValue"));
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // @Content parameter-level defaults
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class I implements BasicJson5Config {
+               @RestPost(path="/x1")
+               public String x1(@Content String content) {
+                       return "content=" + content;
+               }
+       }
+
+       @Remote
+       public interface I1 {
+               @RemotePost("/x1")
+               String x1(@Content(def="{paramDefault:true}") String content);
+       }
+
+       @Test
+       void i01_contentParameterDefault_nullValue() {
+               var x = MockRestClient.buildJson(I.class).getRemote(I1.class);
+               assertEquals("content={paramDefault:true}", x.x1(null));
+       }
+
+       @Test
+       void i02_contentParameterDefault_providedValue() {
+               var x = MockRestClient.buildJson(I.class).getRemote(I1.class);
+               assertEquals("content={custom:true}", x.x1("{custom:true}"));
+       }
+
+       // Test that parameter-level Content default overrides method-level
+       @Remote
+       public interface I2 {
+               @RemotePost("/x1")
+               @Content(def="{methodDefault:true}")
+               String x1(@Content(def="{paramDefault:true}") String content);
+       }
+
+       @Test
+       void i03_contentParameterOverridesMethod() {
+               var x = MockRestClient.buildJson(I.class).getRemote(I2.class);
+               assertEquals("content={paramDefault:true}", x.x1(null));
+       }
+}
+
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
index 842ceaa862..b21acc30dc 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
@@ -147,9 +147,9 @@ class Remote_QueryAnnotation_Test extends TestBase {
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.getX1(""));
                assertEquals("{x:'foo'}",x.getX2(null));
                assertEquals("{x:''}",x.getX2(""));
-               assertEquals("{x:''}",x.getX3(null));
+               assertEquals("{}",x.getX3(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertThrowsWithMessage(Exception.class, "Empty value not 
allowed.", ()->x.getX3(""));
-               assertEquals("{x:''}",x.getX4(null));
+               assertEquals("{}",x.getX4(null));  // Empty string default is 
not applied (changed in 9.2.0)
                assertEquals("{x:''}",x.getX4(""));
        }
 


Reply via email to