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

FrankChen021 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 2f35573537a build(deps): Bump jackson to `2.21.3` (#19528)
2f35573537a is described below

commit 2f35573537a46f2afca1e239f232db56f57284e7
Author: Andreas Maechler <[email protected]>
AuthorDate: Fri May 29 07:50:04 2026 -0600

    build(deps): Bump jackson to `2.21.3` (#19528)
    
    * Bump jackson to 2.21.3
    
    Jackson 2.21 (issue #1381) changed the default resolution of
    @JacksonInject when combined with @JsonProperty on the same parameter:
    the injected value now wins over the JSON value, where 2.20 treated
    the inject as a fallback used only when JSON did not supply one.
    
    DruidNode's serviceName, port, and tlsPort parameters carry both
    annotations, with JSON expected to win when supplied — this is how
    DruidNode JSON config files have always worked. Add the explicit
    useInput = OptBoolean.TRUE to restore that contract.
    
    A repo-wide audit confirmed DruidNode's three parameters are the only
    sites in Druid where @JacksonInject and @JsonProperty annotate the
    same parameter; everywhere else the annotations are on distinct
    parameters and are unaffected.
    
    Also adds the previously-missing license entry for org.jspecify:jspecify
    1.0.0 in extensions-core/kubernetes-extensions, which the
    check-licenses dependency report flagged.
    
    * Preserve @JacksonInject metadata in GuiceAnnotationIntrospector
    
    findInjectableValue was returning JacksonInject.Value.forId(id), which
    strips useInput and optional from the original annotation. Production
    deserialization happens to remain correct under jackson 2.21 because
    AnnotationIntrospectorPair.findInjectableValue falls back to the
    secondary (default Jackson) introspector and merges the recovered
    useInput onto the primary's Value via withUseInput.
    
    That fallback is undocumented as part of the introspector contract and
    would silently regress if the pair semantics change, or if this
    introspector were ever installed standalone for a special-purpose
    mapper. Construct the Value via JacksonInject.Value.from(annotation)
    .withId(id) so the introspector returns a complete Value on its own
    and no longer relies on the pair to fix it up.
    
    The annotation lookup is hoisted to the top of findInjectableValue so
    the non-null contract between it and findGuiceInjectId is explicit —
    findGuiceInjectId now documents the precondition and trusts the caller
    to verify, eliminating the duplicate getAnnotation call.
    
    Defensive cleanup motivated by FasterXML/jackson-databind#1381; no
    observable behavior change.
---
 licenses.yaml                                        | 20 +++++++++++++++-----
 pom.xml                                              |  2 +-
 .../druid/guice/GuiceAnnotationIntrospector.java     | 18 ++++++++++++------
 .../main/java/org/apache/druid/server/DruidNode.java |  7 ++++---
 4 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/licenses.yaml b/licenses.yaml
index 23f58a0d3b3..8032c582975 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -321,7 +321,7 @@ name: Jackson
 license_category: binary
 module: java-core
 license_name: Apache License version 2.0
-version: 2.20.2
+version: 2.21.3
 libraries:
   - com.fasterxml.jackson.core: jackson-core
   - com.fasterxml.jackson.core: jackson-annotations
@@ -364,7 +364,7 @@ name: Jackson
 license_category: binary
 module: java-core
 license_name: Apache License version 2.0
-version: "2.20"
+version: "2.21"
 libraries:
   - com.fasterxml.jackson.core: jackson-annotations
 
@@ -374,7 +374,7 @@ name: Jackson
 license_category: binary
 module: extensions-contrib/druid-deltalake-extensions
 license_name: Apache License version 2.0
-version: 2.20.2
+version: 2.21.3
 libraries:
   - com.fasterxml.jackson.core: jackson-databind
 notice: |
@@ -1002,7 +1002,7 @@ name: Jackson
 license_category: binary
 module: extensions-core/kubernetes-overlord-extensions
 license_name: Apache License version 2.0
-version: 2.20.2
+version: 2.21.3
 libraries:
   - com.fasterxml.jackson.dataformat: jackson-dataformat-properties
 notice: |
@@ -1107,6 +1107,16 @@ libraries:
 
 ---
 
+name: org.jspecify jspecify
+license_category: binary
+module: extensions-core/kubernetes-extensions
+license_name: Apache License version 2.0
+version: 1.0.0
+libraries:
+  - org.jspecify: jspecify
+
+---
+
 name: io.gsonfire gson-fire
 license_category: binary
 module: extensions-core/kubernetes-extensions
@@ -3069,7 +3079,7 @@ libraries:
 ---
 
 name: Jackson Dataformat Yaml
-version: 2.20.2
+version: 2.21.3
 license_category: binary
 module: extensions/druid-avro-extensions
 license_name: Apache License version 2.0
diff --git a/pom.xml b/pom.xml
index aabb17d07f0..fa07aa254c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
         <iceberg.core.version>1.10.0</iceberg.core.version>
         <jetty.version>12.1.8</jetty.version>
         <jersey.version>1.19.4</jersey.version>
-        <jackson.version>2.20.2</jackson.version>
+        <jackson.version>2.21.3</jackson.version>
         <codehaus.jackson.version>1.9.13</codehaus.jackson.version>
         <log4j.version>2.25.4</log4j.version>
         <mysql.version>8.2.0</mysql.version>
diff --git 
a/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java
 
b/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java
index fd8ee5e9e02..890e3c233a0 100644
--- 
a/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java
+++ 
b/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java
@@ -44,19 +44,25 @@ public class GuiceAnnotationIntrospector extends 
NopAnnotationIntrospector
   @Override
   public JacksonInject.Value findInjectableValue(AnnotatedMember m)
   {
-    Object id = findGuiceInjectId(m);
+    // Preserve useInput / optional from the annotation. The simpler 
Value.forId(id) drops
+    // them and relies on AnnotationIntrospectorPair's fallback. See 
FasterXML/jackson-databind#1381.
+    final JacksonInject annotation = m.getAnnotation(JacksonInject.class);
+    if (annotation == null) {
+      return null;
+    }
+    final Object id = findGuiceInjectId(m);
     if (id == null) {
       return null;
     }
-    return JacksonInject.Value.forId(id);
+    return JacksonInject.Value.from(annotation).withId(id);
   }
 
+  /**
+   * Resolves the Guice {@link Key} for an annotated member. Callers must 
verify that {@code m}
+   * carries a {@link JacksonInject} annotation before invoking; this method 
does not re-check.
+   */
   private Object findGuiceInjectId(AnnotatedMember m)
   {
-    if (m.getAnnotation(JacksonInject.class) == null) {
-      return null;
-    }
-
     Type genericType = null;
 
     Annotation guiceAnnotation = null;
diff --git a/server/src/main/java/org/apache/druid/server/DruidNode.java 
b/server/src/main/java/org/apache/druid/server/DruidNode.java
index 820d8d32a08..19252fde755 100644
--- a/server/src/main/java/org/apache/druid/server/DruidNode.java
+++ b/server/src/main/java/org/apache/druid/server/DruidNode.java
@@ -22,6 +22,7 @@ package org.apache.druid.server;
 import com.fasterxml.jackson.annotation.JacksonInject;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.OptBoolean;
 import com.google.common.base.Preconditions;
 import com.google.common.net.HostAndPort;
 import com.google.inject.name.Named;
@@ -130,12 +131,12 @@ public class DruidNode
    */
   @JsonCreator
   public DruidNode(
-      @JacksonInject @Named("serviceName") @JsonProperty("service") String 
serviceName,
+      @JacksonInject(useInput = OptBoolean.TRUE) @Named("serviceName") 
@JsonProperty("service") String serviceName,
       @JsonProperty("host") String host,
       @JsonProperty("bindOnHost") boolean bindOnHost,
       @JsonProperty("plaintextPort") Integer plaintextPort,
-      @JacksonInject @Named("servicePort") @JsonProperty("port") Integer port,
-      @JacksonInject @Named("tlsServicePort") @JsonProperty("tlsPort") Integer 
tlsPort,
+      @JacksonInject(useInput = OptBoolean.TRUE) @Named("servicePort") 
@JsonProperty("port") Integer port,
+      @JacksonInject(useInput = OptBoolean.TRUE) @Named("tlsServicePort") 
@JsonProperty("tlsPort") Integer tlsPort,
       @JsonProperty("enablePlaintextPort") Boolean enablePlaintextPort,
       @JsonProperty("enableTlsPort") boolean enableTlsPort,
       @JsonProperty("labels") @Nullable Map<String, String> labels


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to