diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index d76b28b48f..494d47c4f2 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -41,6 +41,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 cc4263e4a2..50cfcaf005 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -526,7 +526,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)
*/
@@ -573,7 +573,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