diff --git a/extensions-contrib/compressed-bigdecimal/pom.xml b/extensions-contrib/compressed-bigdecimal/pom.xml index 29a177e86850..a05e757a7a67 100644 --- a/extensions-contrib/compressed-bigdecimal/pom.xml +++ b/extensions-contrib/compressed-bigdecimal/pom.xml @@ -126,7 +126,6 @@ joda-time joda-time - 2.10.5 provided @@ -138,12 +137,10 @@ com.fasterxml.jackson.core jackson-core - 2.10.2 com.fasterxml.jackson.core jackson-annotations - 2.10.2 diff --git a/extensions-contrib/kafka-emitter/pom.xml b/extensions-contrib/kafka-emitter/pom.xml index 90b9d236d6fa..92a8257b5161 100644 --- a/extensions-contrib/kafka-emitter/pom.xml +++ b/extensions-contrib/kafka-emitter/pom.xml @@ -81,6 +81,11 @@ jackson-core provided + + com.fasterxml.jackson.datatype + jackson-datatype-joda + provided + org.slf4j slf4j-api diff --git a/extensions-contrib/kafka-emitter/src/test/java/org/apache/druid/emitter/kafka/KafkaEmitterTest.java b/extensions-contrib/kafka-emitter/src/test/java/org/apache/druid/emitter/kafka/KafkaEmitterTest.java index b40da9bd9e08..5d0df12eadfc 100644 --- a/extensions-contrib/kafka-emitter/src/test/java/org/apache/druid/emitter/kafka/KafkaEmitterTest.java +++ b/extensions-contrib/kafka-emitter/src/test/java/org/apache/druid/emitter/kafka/KafkaEmitterTest.java @@ -20,6 +20,7 @@ package org.apache.druid.emitter.kafka; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.apache.druid.java.util.common.DateTimes; @@ -102,9 +103,11 @@ public void testKafkaEmitter() throws InterruptedException requestTopic == null ? totalEventsExcludingRequestLogEvents : totalEvents); final KafkaProducer producer = mock(KafkaProducer.class); + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new JodaModule()); final KafkaEmitter kafkaEmitter = new KafkaEmitter( new KafkaEmitterConfig("", eventsType, "metrics", "alerts", requestTopic, "metadata", "test-cluster", null), - new ObjectMapper() + mapper ) { @Override diff --git a/licenses.yaml b/licenses.yaml index 7083cf1171bc..eed679e46053 100644 --- a/licenses.yaml +++ b/licenses.yaml @@ -248,7 +248,7 @@ name: Jackson license_category: binary module: java-core license_name: Apache License version 2.0 -version: 2.10.5 +version: 2.12.7 libraries: - com.fasterxml.jackson.core: jackson-annotations - com.fasterxml.jackson.core: jackson-core @@ -289,7 +289,7 @@ name: Jackson license_category: binary module: java-core license_name: Apache License version 2.0 -version: 2.10.5.1 +version: 2.12.7 libraries: - com.fasterxml.jackson.core: jackson-databind notice: | @@ -3592,7 +3592,7 @@ libraries: --- name: Jackson Dataformat Yaml -version: 2.10.5 +version: 2.12.7 license_category: binary module: extensions/druid-avro-extensions license_name: Apache License version 2.0 diff --git a/owasp-dependency-check-suppressions.xml b/owasp-dependency-check-suppressions.xml index 8a3ec43419d4..175459abe749 100644 --- a/owasp-dependency-check-suppressions.xml +++ b/owasp-dependency-check-suppressions.xml @@ -117,13 +117,6 @@ --> CVE-2022-42003 CVE-2022-42004 - - CVE-2021-46877 - - CVE-2023-35116 @@ -638,7 +631,6 @@ - CVE-2020-36518 CVE-2022-45688 @@ -675,14 +667,6 @@ CVE-2020-17516 - - - - CVE-2020-28491 - - 1.3 9.4.51.v20230217 1.19.4 - 2.10.5.20201202 + 2.12.7 1.9.13 2.18.0 5.1.49 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 ce49253e0ffb..fd8ee5e9e02a 100644 --- a/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java +++ b/processing/src/main/java/org/apache/druid/guice/GuiceAnnotationIntrospector.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; +import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; @@ -33,6 +34,7 @@ import org.apache.druid.java.util.common.IAE; import java.lang.annotation.Annotation; +import java.lang.reflect.Type; import java.util.Map; /** @@ -40,12 +42,23 @@ public class GuiceAnnotationIntrospector extends NopAnnotationIntrospector { @Override - public Object findInjectableValueId(AnnotatedMember m) + public JacksonInject.Value findInjectableValue(AnnotatedMember m) + { + Object id = findGuiceInjectId(m); + if (id == null) { + return null; + } + return JacksonInject.Value.forId(id); + } + + private Object findGuiceInjectId(AnnotatedMember m) { if (m.getAnnotation(JacksonInject.class) == null) { return null; } + Type genericType = null; + Annotation guiceAnnotation = null; for (Annotation annotation : m.annotations()) { if (annotation.annotationType().isAnnotationPresent(BindingAnnotation.class)) { @@ -54,39 +67,54 @@ public Object findInjectableValueId(AnnotatedMember m) } } + // Annotated.getGenericType() is removed since jackson-databind 2.11 version. We need the generic type so that we can inject values of the type such as List correctly. + // Jackson library removed the method on the abstract class but the methods are still there in the implementations of AnnotatedMember. The method signatures are implementation specific and we are calling those methods to get the generic type. + + if (m instanceof AnnotatedField) { + genericType = ((AnnotatedField) m).getAnnotated().getGenericType(); + } else if (m instanceof AnnotatedMethod) { + genericType = ((AnnotatedMethod) m).getAnnotated().getGenericReturnType(); + } else if (m instanceof AnnotatedParameter) { + genericType = ((AnnotatedParameter) m).getOwner().getGenericParameterType(((AnnotatedParameter) m).getIndex()); + } + + if (genericType == null) { + // Fall back to type-erased raw type in case we missed an implementation. We are unlikely to ever get here though + genericType = m.getRawType(); + } if (guiceAnnotation == null) { if (m instanceof AnnotatedMethod) { throw new IAE("Annotated methods don't work very well yet..."); } - return Key.get(m.getGenericType()); + return Key.get(genericType); } - return Key.get(m.getGenericType(), guiceAnnotation); + return Key.get(genericType, guiceAnnotation); } - /** - * This method is used to find what property to ignore in deserialization. Jackson calls this method - * per every class and every constructor parameter. - * - * This implementation returns a {@link JsonIgnoreProperties.Value#empty()} that allows empty names if - * the parameters has the {@link JsonProperty} annotation. Otherwise, it returns - * {@code JsonIgnoreProperties.Value.forIgnoredProperties("")} that does NOT allow empty names. - * This behavior is to work around a bug in Jackson deserializer (see the below comment for details) and - * can be removed in the future after the bug is fixed. - * For example, suppose a constructor like below: - * - *
{@code
-   * @JsonCreator
-   * public ClassWithJacksonInject(
-   *   @JsonProperty("val") String val,
-   *   @JacksonInject InjectedParameter injected
-   * )
-   * }
- * - * During deserializing a JSON string into this class, this method will be called at least twice, - * one for {@code val} and another for {@code injected}. It will return {@code Value.empty()} for {@code val}, - * while {Value.forIgnoredProperties("")} for {@code injected} because the later does not have {@code JsonProperty}. - * As a result, {@code injected} will be ignored during deserialization since it has no name. - */ + /** + * This method is used to find what property to ignore in deserialization. Jackson calls this method + * per every class and every constructor parameter. + * + * This implementation returns a {@link JsonIgnoreProperties.Value#empty()} that allows empty names if + * the parameters has the {@link JsonProperty} annotation. Otherwise, it returns + * {@code JsonIgnoreProperties.Value.forIgnoredProperties("")} that does NOT allow empty names. + * This behavior is to work around a bug in Jackson deserializer (see the below comment for details) and + * can be removed in the future after the bug is fixed. + * For example, suppose a constructor like below: + * + *
{@code
+     * @JsonCreator
+     * public ClassWithJacksonInject(
+     *   @JsonProperty("val") String val,
+     *   @JacksonInject InjectedParameter injected
+     * )
+     * }
+ * + * During deserializing a JSON string into this class, this method will be called at least twice, + * one for {@code val} and another for {@code injected}. It will return {@code Value.empty()} for {@code val}, + * while {Value.forIgnoredProperties("")} for {@code injected} because the later does not have {@code JsonProperty}. + * As a result, {@code injected} will be ignored during deserialization since it has no name. + */ @Override public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated ac) { diff --git a/processing/src/test/java/org/apache/druid/segment/TestHelper.java b/processing/src/test/java/org/apache/druid/segment/TestHelper.java index 5916fe8860b5..c167f6fe9524 100644 --- a/processing/src/test/java/org/apache/druid/segment/TestHelper.java +++ b/processing/src/test/java/org/apache/druid/segment/TestHelper.java @@ -19,6 +19,7 @@ package org.apache.druid.segment; +import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.ObjectMapper; @@ -85,7 +86,7 @@ public static AnnotationIntrospector makeAnnotationIntrospector() return new GuiceAnnotationIntrospector() { @Override - public Object findInjectableValueId(AnnotatedMember m) + public JacksonInject.Value findInjectableValue(AnnotatedMember m) { return null; } diff --git a/server/src/test/java/org/apache/druid/client/cache/CacheConfigTest.java b/server/src/test/java/org/apache/druid/client/cache/CacheConfigTest.java index 3a0a184f1a4a..f0f18667d69d 100644 --- a/server/src/test/java/org/apache/druid/client/cache/CacheConfigTest.java +++ b/server/src/test/java/org/apache/druid/client/cache/CacheConfigTest.java @@ -130,22 +130,22 @@ public void testValidationInsaneError() throw new IllegalStateException("Should have already failed"); } - @Test(expected = ProvisionException.class) + @Test public void testTRUE() { properties.put(PROPERTY_PREFIX + ".populateCache", "TRUE"); configProvider.inject(properties, configurator); CacheConfig config = configProvider.get(); - throw new IllegalStateException("Should have already failed"); + Assert.assertTrue(config.isPopulateCache()); } - @Test(expected = ProvisionException.class) + @Test public void testFALSE() { properties.put(PROPERTY_PREFIX + ".populateCache", "FALSE"); configProvider.inject(properties, configurator); CacheConfig config = configProvider.get(); - throw new IllegalStateException("Should have already failed"); + Assert.assertFalse(config.isPopulateCache()); }