From c0a8928b99abb3f4dbcbe4a03855bbf35a45f7d2 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 11 Jun 2020 19:32:48 -0700 Subject: [PATCH 1/3] minor test refactoring --- .../jackson/databind/deser/std/DateDeserializers.java | 1 - .../jackson/databind/objectid/ObjectId687Test.java | 2 +- .../jackson/databind/objectid/ObjectId825BTest.java | 7 ++++++- .../jackson/databind/ser/TestArraySerialization.java | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java index a3d3c7577c..9af1525b07 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java @@ -14,7 +14,6 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.cfg.CoercionAction; -import com.fasterxml.jackson.databind.cfg.CoercionInputShape; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.type.LogicalType; import com.fasterxml.jackson.databind.util.ClassUtil; diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java index 972a5fa8f9..91eda5e44b 100644 --- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java @@ -63,7 +63,7 @@ static class EnclosingForRefWithNoCreator { /***************************************************** */ - private final ObjectMapper MAPPER = objectMapper(); + private final ObjectMapper MAPPER = newJsonMapper(); // for [databind#687] public void testSerializeDeserializeWithCreator() throws IOException { diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java index af173eedec..171f1ded1b 100644 --- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java @@ -136,10 +136,15 @@ static class V extends AbstractData { private static final long serialVersionUID = 1L; } + /* + /***************************************************** + /* Test methods + /***************************************************** + */ + public void testFull825() throws Exception { final ObjectMapper mapper = jsonMapperBuilder() - .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT) .activateDefaultTyping(NoCheckSubTypeValidator.instance, ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE) .build(); diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java index 10baa8ef6e..e1cd38d696 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java +++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java @@ -6,7 +6,7 @@ public class TestArraySerialization extends BaseMapTest { - private final ObjectMapper MAPPER = newJsonMapper(); + private final ObjectMapper MAPPER = sharedMapper(); public void testLongStringArray() throws Exception { From 97ed5c9880f417e0fadd6ede51eac2cc82731ba1 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 11 Jun 2020 19:57:41 -0700 Subject: [PATCH 2/3] Fixed #2755 --- release-notes/VERSION-2.x | 3 +++ .../jackson/databind/ObjectMapper.java | 4 ++-- .../databind/jsontype/SubtypeResolver.java | 20 +++++++++++++++++-- .../jsontype/impl/StdSubtypeResolver.java | 13 ++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 77f9c318be..83ad6df2d5 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -8,6 +8,9 @@ Project: jackson-databind #2486: Builder Deserialization with JsonCreator Value vs Array (reported by Ville K) +#2755: `StdSubtypeResolver` is not thread safe (possibly due to copy + not being made with `ObjectMapper.copy()`) + (reported by tjwilson90@github) 2.11.0 (26-Apr-2020) diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index 03bf5f3ef5..2529ee2797 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -512,7 +512,7 @@ public boolean useForType(JavaType t) * (should very quickly converge to zero after startup), let's * explicitly define a low concurrency setting. *

- * Since version 1.5, these may are either "raw" deserializers (when + * These may are either "raw" deserializers (when * no type information is needed for base type), or type-wrapped * deserializers (if it is needed) */ @@ -559,7 +559,7 @@ protected ObjectMapper(ObjectMapper src) { _jsonFactory = src._jsonFactory.copy(); _jsonFactory.setCodec(this); - _subtypeResolver = src._subtypeResolver; + _subtypeResolver = src._subtypeResolver.copy(); _typeFactory = src._typeFactory; _injectableValues = src._injectableValues; _configOverrides = src._configOverrides.copy(); diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java index 0f6c50b6ee..206eb9a66b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/SubtypeResolver.java @@ -14,9 +14,25 @@ */ public abstract class SubtypeResolver { + /** + * Method called by {@code ObjectMapper.copy()} to make sure that + * {@link SubtypeResolver} instances used by two independent mappers + * can not cause thread-safety issues: if resolver is immutable, it + * may return {@code this}, but if not, it should create a copy with + * same configuration and return that instead. + * + * @return Either new instance with same configuration as this one (if + * instances are mutable), or this instance (if immutable) + * + * @since 2.12 + */ + public SubtypeResolver copy() { + return this; + } + /* /********************************************************** - /* Methods for registering external subtype definitions + /* Methods for registering external subtype definitions (init/config) /********************************************************** */ @@ -36,7 +52,7 @@ public abstract class SubtypeResolver /* /********************************************************** - /* Subtype resolution + /* Subtype resolution (public API) /********************************************************** */ diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java index 3d2a3dcd26..7807c85b7e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdSubtypeResolver.java @@ -23,6 +23,19 @@ public class StdSubtypeResolver public StdSubtypeResolver() { } + // @since 2.12 + protected StdSubtypeResolver(StdSubtypeResolver src) { + LinkedHashSet reg = src._registeredSubtypes; + _registeredSubtypes = (reg == null) ? null + : new LinkedHashSet<>(reg); + } + + // @since 2.12 + @Override + public SubtypeResolver copy() { + return new StdSubtypeResolver(this); + } + /* /********************************************************** /* Subtype registration From 25c4274242a77099b2a4f2de89fa0ae1a5749d6c Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 11 Jun 2020 20:00:19 -0700 Subject: [PATCH 3/3] ... add basic test for #2755 (can not easily test problem, but can verify copying) --- .../java/com/fasterxml/jackson/databind/ObjectMapperTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java index 7f1daa511a..5f4cffbd9d 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java @@ -133,9 +133,11 @@ public void testCopy() throws Exception assertFalse(m2.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE)); // // Also, underlying JsonFactory instances should be distinct - assertNotSame(m.getFactory(), m2.getFactory()); + // [databind#2755]: also need to copy this: + assertNotSame(m.getSubtypeResolver(), m2.getSubtypeResolver()); + // [databind#122]: Need to ensure mix-ins are not shared assertEquals(0, m.getSerializationConfig().mixInCount()); assertEquals(0, m2.getSerializationConfig().mixInCount());