From fd3921574a2bb1533122fd0c507f6ed0fc323b85 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 7 Sep 2023 11:15:01 +0900 Subject: [PATCH 01/15] wip --- .../jackson/databind/ObjectMapper.java | 1 + .../jackson/databind/cfg/CacheProvider.java | 4 +++- .../ser/DefaultSerializerProvider.java | 22 ++++++++++++++++++- .../jackson/databind/ser/SerializerCache.java | 8 +++++++ .../databind/cfg/CacheProviderTest.java | 13 +++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index a9ccb1bb81..ac361552f1 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -2283,6 +2283,7 @@ public ObjectMapper setCacheProvider(CacheProvider cacheProvider) { _deserializationConfig = _deserializationConfig.with(cacheProvider); _serializationConfig = _serializationConfig.with(cacheProvider); _deserializationContext = _deserializationContext.withCaches(cacheProvider); + _serializerProvider = _serializerProvider.withCaches(cacheProvider); return this; } diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java index d1a8487dbc..9fee1a7d37 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.deser.DeserializerCache; import com.fasterxml.jackson.databind.util.LookupCache; @@ -23,5 +24,6 @@ public interface CacheProvider * @return {@link LookupCache} instance for constructing {@link DeserializerCache}. */ LookupCache> forDeserializerCache(DeserializationConfig config); - + + int forSerializerCache(SerializationConfig config); } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java index 8d029c5def..2e3064124e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.cfg.CacheProvider; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; @@ -92,6 +93,20 @@ public abstract DefaultSerializerProvider createInstance(SerializationConfig con public DefaultSerializerProvider copy() { throw new IllegalStateException("DefaultSerializerProvider sub-class not overriding copy()"); } + + /* + /********************************************************** + /* Extended API, life-cycle + /********************************************************** + */ + + /** + * Fluent factory method used for constructing a new instance with cache instances provided by {@link CacheProvider}. + * + * @since 2.16 + */ + public abstract DefaultSerializerProvider withCaches(CacheProvider cacheProvider); + /* /********************************************************** @@ -592,7 +607,6 @@ public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(C return new com.fasterxml.jackson.databind.jsonschema.JsonSchema((ObjectNode) schemaNode); } - /* /********************************************************** /* Helper classes @@ -624,5 +638,11 @@ public DefaultSerializerProvider copy() public Impl createInstance(SerializationConfig config, SerializerFactory jsf) { return new Impl(this, config, jsf); } + + @Override + public DefaultSerializerProvider withCaches(CacheProvider cacheProvider) { + return new Impl(this, + new SerializerCache(cacheProvider.forSerializerCache(_config))); + } } } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java index 73f66e5784..dbb494b58b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java @@ -53,6 +53,14 @@ public SerializerCache(int maxCached) { _readOnlyMap = new AtomicReference(); } + /** + * @since 2.16 + */ + public SerializerCache(LRUMap> cache) { + _sharedMap = cache; + _readOnlyMap = new AtomicReference(); + } + /** * Method that can be called to get a read-only instance populated from the * most recent version of the shared lookup Map. diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index a9c0a6738a..b7accc1a19 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -177,4 +177,17 @@ public void testBuilderBuildWithDefaults() throws Exception // does not throw DefaultCacheProvider.builder().build(); } + + @Test + public void testDefaultCacheProviderConfigSerializerCache() throws Exception + { + CacheProvider cacheProvider = DefaultCacheProvider.builder() + .maxDeserializerCacheSize(1234) + .build(); + ObjectMapper mapper = JsonMapper.builder() + .cacheProvider(cacheProvider).build(); + + assertNotNull(mapper.readValue("{\"point\":24}", RandomBean.class)); + } + } From b35d015140c6235793aafd0dd998c41bd717f81a Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 7 Sep 2023 22:56:40 +0900 Subject: [PATCH 02/15] Implement all except SerializerCache --- .../jackson/databind/SerializerProvider.java | 22 +++++ .../jackson/databind/cfg/CacheProvider.java | 15 ++-- .../databind/cfg/DefaultCacheProvider.java | 53 +++++++++-- .../ser/DefaultSerializerProvider.java | 9 ++ .../jackson/databind/ser/SerializerCache.java | 8 +- .../databind/cfg/CacheProviderTest.java | 87 +++++++++++++++++-- .../ser/filter/NullSerializationTest.java | 6 ++ 7 files changed, 178 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java index 3b11c51d95..aa52ff6a5c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java @@ -261,6 +261,28 @@ protected SerializerProvider(SerializerProvider src) _stdNullValueSerializer = src._stdNullValueSerializer; } + + /** + * @since 2.16 + */ + protected SerializerProvider(SerializerProvider src, SerializerCache serializerCache) + { + _serializerFactory = src._serializerFactory; + _config = src._config; + + _serializerCache = serializerCache; + _unknownTypeSerializer = src._unknownTypeSerializer; + _keySerializer = src._keySerializer; + _nullValueSerializer = src._nullValueSerializer; + _nullKeySerializer = src._nullKeySerializer; + + _stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER); + + _serializationView = src._serializationView; + _attributes = src._attributes; + _knownSerializers = src._knownSerializers; + } + /* /********************************************************** /* Methods for configuring default settings diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java index 9fee1a7d37..b261053cfb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/CacheProvider.java @@ -1,11 +1,9 @@ package com.fasterxml.jackson.databind.cfg; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializerCache; import com.fasterxml.jackson.databind.util.LookupCache; +import com.fasterxml.jackson.databind.util.TypeKey; /** * Interface that defines API Jackson uses for constructing various internal @@ -24,6 +22,11 @@ public interface CacheProvider * @return {@link LookupCache} instance for constructing {@link DeserializerCache}. */ LookupCache> forDeserializerCache(DeserializationConfig config); - - int forSerializerCache(SerializationConfig config); + + /** + * Method to provide a {@link LookupCache} instance for constructing {@link com.fasterxml.jackson.databind.ser.SerializerCache}. + * + * @return {@link LookupCache} instance for constructing {@link com.fasterxml.jackson.databind.ser.SerializerCache}. + */ + LookupCache> forSerializerCache(SerializationConfig config); } diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java index 6859889725..27648dc2ac 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java @@ -1,11 +1,11 @@ package com.fasterxml.jackson.databind.cfg; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.DeserializerCache; +import com.fasterxml.jackson.databind.ser.SerializerCache; import com.fasterxml.jackson.databind.util.LRUMap; import com.fasterxml.jackson.databind.util.LookupCache; +import com.fasterxml.jackson.databind.util.TypeKey; /** * The default implementation of {@link CacheProvider}. @@ -21,7 +21,7 @@ public class DefaultCacheProvider private static final long serialVersionUID = 1L; private final static DefaultCacheProvider DEFAULT - = new DefaultCacheProvider(DeserializerCache.DEFAULT_MAX_CACHE_SIZE); + = new DefaultCacheProvider(DeserializerCache.DEFAULT_MAX_CACHE_SIZE, SerializerCache.DEFAULT_MAX_CACHED); /** * Maximum size of the {@link LookupCache} instance constructed by {@link #forDeserializerCache(DeserializationConfig)}. @@ -29,6 +29,13 @@ public class DefaultCacheProvider * @see Builder#maxDeserializerCacheSize(int) */ protected final int _maxDeserializerCacheSize; + + /** + * Maximum size of the {@link LookupCache} instance constructed by {@link #forSerializerCache(SerializationConfig)} + * + * @see Builder#maxSerializerCacheSize(int) + */ + protected final int _maxSerializerCacheSize; /* /********************************************************************** @@ -36,9 +43,10 @@ public class DefaultCacheProvider /********************************************************************** */ - protected DefaultCacheProvider(int deserializerCache) + protected DefaultCacheProvider(int deserializerCacheSize, int serializerCacheSize) { - _maxDeserializerCacheSize = deserializerCache; + _maxDeserializerCacheSize = deserializerCacheSize; + _maxSerializerCacheSize = serializerCacheSize; } /* @@ -71,6 +79,11 @@ public LookupCache> forDeserializerCache(Dese return _buildCache(_maxDeserializerCacheSize); } + @Override + public LookupCache> forSerializerCache(SerializationConfig config) { + return _buildCache(_maxSerializerCacheSize); + } + /* /********************************************************** /* Overridable factory methods @@ -108,6 +121,12 @@ public static class Builder { */ private int _maxDeserializerCacheSize; + /** + * Maximum Size of the {@link LookupCache} instance created by {@link #forSerializerCache(SerializationConfig)} + * Corresponds to {@link DefaultCacheProvider#_maxSerializerCacheSize}. + */ + private int _maxSerializerCacheSize; + Builder() { } /** @@ -130,13 +149,33 @@ public Builder maxDeserializerCacheSize(int maxDeserializerCacheSize) { return this; } + /** + * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forSerializerCache(SerializationConfig)} + * The cache is instantiated as: + *
+         *     return new LRUMap<>(Math.min(64, maxSize >> 2), maxSize);
+         * 
+ * + * @param maxSerializerCacheSize Size for the {@link LookupCache} to use within {@link SerializerCache} + * @return this builder + * @throws IllegalArgumentException if {@code maxSerializerCacheSize} is negative + * @since 2.16 + */ + public Builder maxSerializerCacheSize(int maxSerializerCacheSize) { + if (maxSerializerCacheSize < 0) { + throw new IllegalArgumentException("Cannot set maxSerializerCacheSize to a negative value"); + } + _maxSerializerCacheSize = maxSerializerCacheSize; + return this; + } + /** * Constructs a {@link DefaultCacheProvider} with the provided configuration values, using defaults where not specified. * * @return A {@link DefaultCacheProvider} instance with the specified configuration */ public DefaultCacheProvider build() { - return new DefaultCacheProvider(_maxDeserializerCacheSize); + return new DefaultCacheProvider(_maxDeserializerCacheSize, _maxSerializerCacheSize); } } } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java index 2e3064124e..d9e87bcd7c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java @@ -74,6 +74,11 @@ protected DefaultSerializerProvider(DefaultSerializerProvider src) { super(src); } + protected DefaultSerializerProvider(SerializerProvider src, + SerializerCache serializerCache) { + super(src, serializerCache); + } + /** * Method that sub-classes need to implement: used to create a non-blueprint instances * from the blueprint. @@ -628,6 +633,10 @@ protected Impl(SerializerProvider src, SerializationConfig config, super(src, config, f); } + protected Impl(SerializerProvider src, SerializerCache serializerCache) { + super(src, serializerCache); + } + @Override public DefaultSerializerProvider copy() { diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java index dbb494b58b..925d3388c6 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap; import com.fasterxml.jackson.databind.util.LRUMap; +import com.fasterxml.jackson.databind.util.LookupCache; import com.fasterxml.jackson.databind.util.TypeKey; /** @@ -36,7 +37,7 @@ public final class SerializerCache * NOTE: keys are of various types (see below for key types), in addition to * basic {@link JavaType} used for "untyped" serializers. */ - private final LRUMap> _sharedMap; + private final LookupCache> _sharedMap; /** * Most recent read-only instance, created from _sharedMap, if any. @@ -56,7 +57,7 @@ public SerializerCache(int maxCached) { /** * @since 2.16 */ - public SerializerCache(LRUMap> cache) { + public SerializerCache(LookupCache> cache) { _sharedMap = cache; _readOnlyMap = new AtomicReference(); } @@ -79,7 +80,8 @@ private final synchronized ReadOnlyClassToSerializerMap _makeReadOnlyLookupMap() // not correctness ReadOnlyClassToSerializerMap m = _readOnlyMap.get(); if (m == null) { - m = ReadOnlyClassToSerializerMap.from(_sharedMap); + // TODO: Figure out how to pass something that can provides content-iterable without hard type casting. + m = ReadOnlyClassToSerializerMap.from((LRUMap>) _sharedMap); _readOnlyMap.set(m); } return m; diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index b7accc1a19..e9494e0db3 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -1,11 +1,10 @@ package com.fasterxml.jackson.databind.cfg; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.util.LRUMap; import com.fasterxml.jackson.databind.util.LookupCache; +import com.fasterxml.jackson.databind.util.TypeKey; import org.junit.Test; import java.util.HashMap; @@ -28,6 +27,10 @@ static class RandomBean { static class AnotherBean { public int height; } + + static class SerBean { + public int slide = 123; + } static class SimpleTestCache implements LookupCache> { @@ -87,10 +90,41 @@ public LookupCache> forDeserializerCache(Dese return _cache; } + @Override + public LookupCache> forSerializerCache(SerializationConfig config) { + return new LRUMap<>(8, 64); + } + int createCacheCount() { return createCacheCount; } } + + static class CustomSerializerCacheProvider implements CacheProvider { + + final CustomTestSerializerCache _cache; + + public CustomSerializerCacheProvider(CustomTestSerializerCache cache) { + _cache = cache; + } + + @Override + public LookupCache> forDeserializerCache(DeserializationConfig config) { + return new LRUMap<>(16, 64); + } + + @Override + public LookupCache> forSerializerCache(SerializationConfig config) { + return _cache; + } + } + + static class CustomTestSerializerCache extends LRUMap> { + + public CustomTestSerializerCache() { + super(8, 64); + } + } /* /********************************************************************** @@ -182,12 +216,53 @@ public void testBuilderBuildWithDefaults() throws Exception public void testDefaultCacheProviderConfigSerializerCache() throws Exception { CacheProvider cacheProvider = DefaultCacheProvider.builder() - .maxDeserializerCacheSize(1234) + .maxSerializerCacheSize(1234) .build(); ObjectMapper mapper = JsonMapper.builder() .cacheProvider(cacheProvider).build(); + + String json = mapper.writeValueAsString(new SerBean()); + + assertEquals("{\"slide\":123}", json); + } - assertNotNull(mapper.readValue("{\"point\":24}", RandomBean.class)); + @Test + public void testDefaultCacheProviderConfigSerializerCacheSizeZero() throws Exception + { + CacheProvider cacheProvider = DefaultCacheProvider.builder() + .maxSerializerCacheSize(0) + .build(); + ObjectMapper mapper = JsonMapper.builder() + .cacheProvider(cacheProvider) + .build(); + + String json = mapper.writeValueAsString(new SerBean()); + + assertEquals("{\"slide\":123}", json); + } + + @Test + public void testBuilderNullCheckingForSerializerCacheConfig() throws Exception + { + try { + DefaultCacheProvider.builder() + .maxSerializerCacheSize(-1); + fail("Should not reach here"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Cannot set maxSerializerCacheSize to a negative value")); + } } + @Test + public void testCustomCacheProviderSerializerCacheConfig() throws Exception + { + CustomTestSerializerCache cache = new CustomTestSerializerCache(); + ObjectMapper mapper = JsonMapper.builder() + .cacheProvider(new CustomSerializerCacheProvider(cache)) + .build(); + + String json = mapper.writeValueAsString(new SerBean()); + + assertEquals("{\"slide\":123}", json); + } } diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/filter/NullSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/filter/NullSerializationTest.java index ee81699c81..5fc5437a3c 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ser/filter/NullSerializationTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ser/filter/NullSerializationTest.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.cfg.CacheProvider; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import com.fasterxml.jackson.databind.ser.SerializerFactory; @@ -44,6 +45,11 @@ public DefaultSerializerProvider copy() { return this; } + @Override + public DefaultSerializerProvider withCaches(CacheProvider cacheProvider) { + throw new UnsupportedOperationException(); + } + @Override public DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) { return new MyNullProvider(this, config, jsf); From 81026d64c0ed31b12b69b6c7013f904f9d25a82b Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 12 Sep 2023 09:07:39 +0900 Subject: [PATCH 03/15] Add @since in DefaultSerializerProvider --- .../jackson/databind/ser/DefaultSerializerProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java index d9e87bcd7c..3fea52182b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java @@ -74,6 +74,9 @@ protected DefaultSerializerProvider(DefaultSerializerProvider src) { super(src); } + /** + * @since 2.16 + */ protected DefaultSerializerProvider(SerializerProvider src, SerializerCache serializerCache) { super(src, serializerCache); From f9c49bfd03458111012d1ba5e15b144a2b7b4cf9 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 12 Sep 2023 23:15:34 +0900 Subject: [PATCH 04/15] Add LookUpCache.contents() --- .../fasterxml/jackson/databind/util/LRUMap.java | 7 +------ .../jackson/databind/util/LookupCache.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java b/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java index 2d67236b1e..b60c530939 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java @@ -74,12 +74,7 @@ public V putIfAbsent(K key, V value) { @Override public int size() { return _map.size(); } - /* - /********************************************************************** - /* Extended API (2.14) - /********************************************************************** - */ - + @Override public void contents(BiConsumer consumer) { for (Map.Entry entry : _map.entrySet()) { consumer.accept(entry.getKey(), entry.getValue()); diff --git a/src/main/java/com/fasterxml/jackson/databind/util/LookupCache.java b/src/main/java/com/fasterxml/jackson/databind/util/LookupCache.java index 777a97b82c..2d668f0611 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/LookupCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/LookupCache.java @@ -1,5 +1,7 @@ package com.fasterxml.jackson.databind.util; +import java.util.function.BiConsumer; + /** * An interface describing the required API for the Jackson-databind Type cache. *

@@ -11,6 +13,20 @@ */ public interface LookupCache { + /** + * Method to apply operation on cache contents without exposing them. + *

+ * Default implementation throws {@link UnsupportedOperationException}. + * Implementations are required to override this method. + * + * @since 2.16 + * @throws UnsupportedOperationException if implementation does not override this method. + * @param consumer Operation to apply on cache contents. + */ + default void contents(BiConsumer consumer) { + throw new UnsupportedOperationException(); + } + /** * Method needed for creating clones but without contents. *

From 29aacb07edeb6eeef8f58268db128b55adf144a9 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 06:56:36 +0900 Subject: [PATCH 05/15] Improve JavaDoc and names --- .../jackson/databind/cfg/DefaultCacheProvider.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java index 27648dc2ac..e39d5ecdb2 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java @@ -43,10 +43,10 @@ public class DefaultCacheProvider /********************************************************************** */ - protected DefaultCacheProvider(int deserializerCacheSize, int serializerCacheSize) + protected DefaultCacheProvider(int maxDeserializerCacheSize, int maxSerializerCacheSize) { - _maxDeserializerCacheSize = deserializerCacheSize; - _maxSerializerCacheSize = serializerCacheSize; + _maxDeserializerCacheSize = maxDeserializerCacheSize; + _maxSerializerCacheSize = maxSerializerCacheSize; } /* @@ -135,6 +135,7 @@ public static class Builder { *

          *     return new LRUMap<>(Math.min(64, maxSize >> 2), maxSize);
          * 
+ * ... such. Refer to {@link #_buildCache(int)} * * @param maxDeserializerCacheSize Size for the {@link LookupCache} to use within {@link DeserializerCache} * @return this builder @@ -155,6 +156,7 @@ public Builder maxDeserializerCacheSize(int maxDeserializerCacheSize) { *
          *     return new LRUMap<>(Math.min(64, maxSize >> 2), maxSize);
          * 
+ * ... such. Refer to {@link #_buildCache(int)} * * @param maxSerializerCacheSize Size for the {@link LookupCache} to use within {@link SerializerCache} * @return this builder From 2d7559865df1f3fe57a293571cfd32cf0fe46493 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 06:56:53 +0900 Subject: [PATCH 06/15] Retrofit DeserializerCache style approach --- .../ser/DefaultSerializerProvider.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java index 3fea52182b..68de6b15da 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.cfg.CacheProvider; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; +import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; @@ -77,9 +78,10 @@ protected DefaultSerializerProvider(DefaultSerializerProvider src) { /** * @since 2.16 */ - protected DefaultSerializerProvider(SerializerProvider src, - SerializerCache serializerCache) { - super(src, serializerCache); + protected DefaultSerializerProvider(DefaultSerializerProvider src, + CacheProvider cp) { + super(src, + new SerializerCache(cp.forSerializerCache(src._config))); } /** @@ -636,8 +638,11 @@ protected Impl(SerializerProvider src, SerializationConfig config, super(src, config, f); } - protected Impl(SerializerProvider src, SerializerCache serializerCache) { - super(src, serializerCache); + /** + * @since 2.16 + */ + protected Impl(Impl src, CacheProvider cp) { + super(src, cp); } @Override @@ -652,9 +657,8 @@ public Impl createInstance(SerializationConfig config, SerializerFactory jsf) { } @Override - public DefaultSerializerProvider withCaches(CacheProvider cacheProvider) { - return new Impl(this, - new SerializerCache(cacheProvider.forSerializerCache(_config))); + public DefaultSerializerProvider withCaches(CacheProvider cp) { + return new Impl(this, cp); } } } From b146db1bdf7648bd1fe2d1cb381bb07809229eaa Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 07:01:54 +0900 Subject: [PATCH 07/15] Retrofit SerializerCache --- .../fasterxml/jackson/databind/ser/SerializerCache.java | 8 +++----- .../databind/ser/impl/ReadOnlyClassToSerializerMap.java | 5 +++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java index 925d3388c6..82480a26cb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java @@ -42,7 +42,8 @@ public final class SerializerCache /** * Most recent read-only instance, created from _sharedMap, if any. */ - private final AtomicReference _readOnlyMap; + private final AtomicReference _readOnlyMap = + new AtomicReference(); public SerializerCache() { this(DEFAULT_MAX_CACHED); @@ -51,7 +52,6 @@ public SerializerCache() { public SerializerCache(int maxCached) { int initial = Math.min(64, maxCached>>2); _sharedMap = new LRUMap>(initial, maxCached); - _readOnlyMap = new AtomicReference(); } /** @@ -59,7 +59,6 @@ public SerializerCache(int maxCached) { */ public SerializerCache(LookupCache> cache) { _sharedMap = cache; - _readOnlyMap = new AtomicReference(); } /** @@ -80,8 +79,7 @@ private final synchronized ReadOnlyClassToSerializerMap _makeReadOnlyLookupMap() // not correctness ReadOnlyClassToSerializerMap m = _readOnlyMap.get(); if (m == null) { - // TODO: Figure out how to pass something that can provides content-iterable without hard type casting. - m = ReadOnlyClassToSerializerMap.from((LRUMap>) _sharedMap); + m = ReadOnlyClassToSerializerMap.from(_sharedMap); _readOnlyMap.set(m); } return m; diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/ReadOnlyClassToSerializerMap.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/ReadOnlyClassToSerializerMap.java index 04c68009a7..6ee6ff5e31 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/ReadOnlyClassToSerializerMap.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/ReadOnlyClassToSerializerMap.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.util.LRUMap; +import com.fasterxml.jackson.databind.util.LookupCache; import com.fasterxml.jackson.databind.util.TypeKey; /** @@ -22,7 +23,7 @@ public final class ReadOnlyClassToSerializerMap private final int _mask; - public ReadOnlyClassToSerializerMap(LRUMap> src) + public ReadOnlyClassToSerializerMap(LookupCache> src) { _size = findSize(src.size()); _mask = (_size-1); @@ -48,7 +49,7 @@ private final static int findSize(int size) /** * Factory method for constructing an instance. */ - public static ReadOnlyClassToSerializerMap from(LRUMap> src) { + public static ReadOnlyClassToSerializerMap from(LookupCache> src) { return new ReadOnlyClassToSerializerMap(src); } From e5811fe419706072446189693f5a80ee1fad1c87 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 07:22:43 +0900 Subject: [PATCH 08/15] Change DEFAULT_MAX_CACHED name --- .../fasterxml/jackson/databind/cfg/DefaultCacheProvider.java | 2 +- .../com/fasterxml/jackson/databind/ser/SerializerCache.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java index e39d5ecdb2..387adeffb5 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java @@ -21,7 +21,7 @@ public class DefaultCacheProvider private static final long serialVersionUID = 1L; private final static DefaultCacheProvider DEFAULT - = new DefaultCacheProvider(DeserializerCache.DEFAULT_MAX_CACHE_SIZE, SerializerCache.DEFAULT_MAX_CACHED); + = new DefaultCacheProvider(DeserializerCache.DEFAULT_MAX_CACHE_SIZE, SerializerCache.DEFAULT_MAX_CACHE_SIZE); /** * Maximum size of the {@link LookupCache} instance constructed by {@link #forDeserializerCache(DeserializationConfig)}. diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java index 82480a26cb..ebc3b48866 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java @@ -29,7 +29,7 @@ public final class SerializerCache * By default, allow caching of up to 4000 serializer entries (for possibly up to * 1000 types; but depending access patterns may be as few as half of that). */ - public final static int DEFAULT_MAX_CACHED = 4000; + public final static int DEFAULT_MAX_CACHE_SIZE = 4000; /** * Shared, modifiable map; all access needs to be through synchronized blocks. @@ -46,7 +46,7 @@ public final class SerializerCache new AtomicReference(); public SerializerCache() { - this(DEFAULT_MAX_CACHED); + this(DEFAULT_MAX_CACHE_SIZE); } public SerializerCache(int maxCached) { From d1545f635f696c4ed4f321ec04ac1e0422299c84 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 07:22:46 +0900 Subject: [PATCH 09/15] Update CacheProviderTest.java --- .../databind/cfg/CacheProviderTest.java | 77 +++++++++---------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index e9494e0db3..ba736ea9f8 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -19,7 +19,7 @@ */ public class CacheProviderTest { - + static class RandomBean { public int point; } @@ -27,7 +27,7 @@ static class RandomBean { static class AnotherBean { public int height; } - + static class SerBean { public int slide = 123; } @@ -35,13 +35,13 @@ static class SerBean { static class SimpleTestCache implements LookupCache> { final HashMap> _cachedDeserializers; - + boolean invokedAtLeastOnce = false; public SimpleTestCache(int cacheSize) { _cachedDeserializers = new HashMap<>(cacheSize); } - + @Override public int size() { return _cachedDeserializers.size(); @@ -74,12 +74,12 @@ boolean isInvokedAtLeastOnce() { return invokedAtLeastOnce; } } - + static class CustomCacheProvider implements CacheProvider { - + final SimpleTestCache _cache; int createCacheCount = 0; - + public CustomCacheProvider(SimpleTestCache cache) { _cache = cache; } @@ -131,7 +131,7 @@ public CustomTestSerializerCache() { /* Unit tests /********************************************************************** */ - + @Test public void testDefaultCacheProviderConfigDeserializerCache() throws Exception { @@ -157,18 +157,6 @@ public void testDefaultCacheProviderConfigDeserializerCacheSizeZero() throws Exc assertNotNull(mapper.readValue("{\"point\":24}", RandomBean.class)); } - @Test - public void testBuilderNullCheckingForDeserializerCacheConfig() throws Exception - { - try { - DefaultCacheProvider.builder() - .maxDeserializerCacheSize(-1); - fail("Should not reach here"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains("Cannot set maxDeserializerCacheSize to a negative value")); - } - } - @Test public void testCustomCacheProviderConfig() throws Exception { @@ -194,22 +182,42 @@ public void testDefaultCacheProviderSharesCache() throws Exception ObjectMapper mapper2 = JsonMapper.builder() .cacheProvider(cacheProvider) .build(); - + // Act // 3. Add two different types to each mapper cache mapper1.readValue("{\"point\":24}", RandomBean.class); mapper2.readValue("{\"height\":24}", AnotherBean.class); - + // Assert // 4. Should have created two cache instance assertEquals(2, cacheProvider.createCacheCount()); } @Test - public void testBuilderBuildWithDefaults() throws Exception + public void testBuilderValueValidation() throws Exception { // does not throw - DefaultCacheProvider.builder().build(); + DefaultCacheProvider.builder() + .build(); + DefaultCacheProvider.builder() + .maxDeserializerCacheSize(Integer.MAX_VALUE) + .maxSerializerCacheSize(Integer.MAX_VALUE) + .build(); + + // validation fails + _verifyValidationFail(() -> DefaultCacheProvider.builder().maxDeserializerCacheSize(-1), + "Cannot set maxDeserializerCacheSize to a negative value"); + _verifyValidationFail(() -> DefaultCacheProvider.builder().maxSerializerCacheSize(-1), + "Cannot set maxSerializerCacheSize to a negative value"); + } + + private void _verifyValidationFail(Runnable cacheProviderBuilder, String expectedErrorMsg) { + try { + cacheProviderBuilder.run(); + fail("Should not reach here"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains(expectedErrorMsg)); + } } @Test @@ -219,10 +227,11 @@ public void testDefaultCacheProviderConfigSerializerCache() throws Exception .maxSerializerCacheSize(1234) .build(); ObjectMapper mapper = JsonMapper.builder() - .cacheProvider(cacheProvider).build(); - + .cacheProvider(cacheProvider) + .build(); + String json = mapper.writeValueAsString(new SerBean()); - + assertEquals("{\"slide\":123}", json); } @@ -237,20 +246,8 @@ public void testDefaultCacheProviderConfigSerializerCacheSizeZero() throws Excep .build(); String json = mapper.writeValueAsString(new SerBean()); - - assertEquals("{\"slide\":123}", json); - } - @Test - public void testBuilderNullCheckingForSerializerCacheConfig() throws Exception - { - try { - DefaultCacheProvider.builder() - .maxSerializerCacheSize(-1); - fail("Should not reach here"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains("Cannot set maxSerializerCacheSize to a negative value")); - } + assertEquals("{\"slide\":123}", json); } @Test From bacc3b34977549dcc6b1e29c60718301a729dc5b Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 07:30:29 +0900 Subject: [PATCH 10/15] Clean up code --- .../databind/cfg/DefaultCacheProvider.java | 14 +++------- .../ser/DefaultSerializerProvider.java | 27 +++++++++---------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java index 387adeffb5..02fdf7824d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/DefaultCacheProvider.java @@ -130,12 +130,8 @@ public static class Builder { Builder() { } /** - * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forDeserializerCache(DeserializationConfig)}. - * The cache is instantiated as: - *
-         *     return new LRUMap<>(Math.min(64, maxSize >> 2), maxSize);
-         * 
- * ... such. Refer to {@link #_buildCache(int)} + * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forDeserializerCache(DeserializationConfig)} + * and {@link #_buildCache(int)}. * * @param maxDeserializerCacheSize Size for the {@link LookupCache} to use within {@link DeserializerCache} * @return this builder @@ -152,11 +148,7 @@ public Builder maxDeserializerCacheSize(int maxDeserializerCacheSize) { /** * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forSerializerCache(SerializationConfig)} - * The cache is instantiated as: - *
-         *     return new LRUMap<>(Math.min(64, maxSize >> 2), maxSize);
-         * 
- * ... such. Refer to {@link #_buildCache(int)} + * and {@link #_buildCache(int)} * * @param maxSerializerCacheSize Size for the {@link LookupCache} to use within {@link SerializerCache} * @return this builder diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java index 68de6b15da..6dcad0d32c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/DefaultSerializerProvider.java @@ -103,20 +103,6 @@ public abstract DefaultSerializerProvider createInstance(SerializationConfig con public DefaultSerializerProvider copy() { throw new IllegalStateException("DefaultSerializerProvider sub-class not overriding copy()"); } - - /* - /********************************************************** - /* Extended API, life-cycle - /********************************************************** - */ - - /** - * Fluent factory method used for constructing a new instance with cache instances provided by {@link CacheProvider}. - * - * @since 2.16 - */ - public abstract DefaultSerializerProvider withCaches(CacheProvider cacheProvider); - /* /********************************************************** @@ -198,6 +184,19 @@ public boolean includeFilterSuppressNulls(Object filter) throws JsonMappingExcep } } + /* + /********************************************************** + /* Extended API, life-cycle + /********************************************************** + */ + + /** + * Fluent factory method used for constructing a new instance with cache instances provided by {@link CacheProvider}. + * + * @since 2.16 + */ + public abstract DefaultSerializerProvider withCaches(CacheProvider cacheProvider); + /* /********************************************************** /* Object Id handling From ef2d31e4da98a029b5599117527583a235c38029 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 13 Sep 2023 08:01:16 +0900 Subject: [PATCH 11/15] Fix SerializerProvider constructor with src.* --- .../jackson/databind/SerializerProvider.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java index aa52ff6a5c..14db5ccde1 100644 --- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java +++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java @@ -267,20 +267,20 @@ protected SerializerProvider(SerializerProvider src) */ protected SerializerProvider(SerializerProvider src, SerializerCache serializerCache) { - _serializerFactory = src._serializerFactory; - _config = src._config; - _serializerCache = serializerCache; - _unknownTypeSerializer = src._unknownTypeSerializer; - _keySerializer = src._keySerializer; - _nullValueSerializer = src._nullValueSerializer; - _nullKeySerializer = src._nullKeySerializer; - - _stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER); + _config = src._config; _serializationView = src._serializationView; + _serializerFactory = src._serializerFactory; _attributes = src._attributes; + _knownSerializers = src._knownSerializers; + _unknownTypeSerializer = src._unknownTypeSerializer; + + _nullValueSerializer = src._nullValueSerializer; + _nullKeySerializer = src._nullKeySerializer; + _keySerializer = src._keySerializer; + _stdNullValueSerializer = src._stdNullValueSerializer; } /* From c64ab75b04678093b7e388cf303a7bb9e2b99fb9 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 19 Sep 2023 12:08:30 +0900 Subject: [PATCH 12/15] Update SerializerCache.java --- .../com/fasterxml/jackson/databind/ser/SerializerCache.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java index ebc3b48866..c9b49f77eb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java @@ -31,6 +31,12 @@ public final class SerializerCache */ public final static int DEFAULT_MAX_CACHE_SIZE = 4000; + /** + * @deprecated Use {@link #DEFAULT_MAX_CACHE_SIZE} instead. + */ + @Deprecated + public final static int DEFAULT_MAX_CACHED = DEFAULT_MAX_CACHE_SIZE; + /** * Shared, modifiable map; all access needs to be through synchronized blocks. *

From a850e5f8d166c39ceed212ebc2a117ed64637f7a Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 19 Sep 2023 22:41:49 +0900 Subject: [PATCH 13/15] Deduplicate test method --- .../databind/cfg/CacheProviderTest.java | 48 ++++++++----------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index ba736ea9f8..472136c20b 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -120,7 +120,6 @@ public LookupCache> forSerializerCache(Serializa } static class CustomTestSerializerCache extends LRUMap> { - public CustomTestSerializerCache() { super(8, 64); } @@ -199,6 +198,7 @@ public void testBuilderValueValidation() throws Exception // does not throw DefaultCacheProvider.builder() .build(); + // does not throw, also DefaultCacheProvider.builder() .maxDeserializerCacheSize(Integer.MAX_VALUE) .maxSerializerCacheSize(Integer.MAX_VALUE) @@ -207,6 +207,7 @@ public void testBuilderValueValidation() throws Exception // validation fails _verifyValidationFail(() -> DefaultCacheProvider.builder().maxDeserializerCacheSize(-1), "Cannot set maxDeserializerCacheSize to a negative value"); + // validation fails _verifyValidationFail(() -> DefaultCacheProvider.builder().maxSerializerCacheSize(-1), "Cannot set maxSerializerCacheSize to a negative value"); } @@ -220,46 +221,35 @@ private void _verifyValidationFail(Runnable cacheProviderBuilder, String expecte } } + /** + * Sanity test for {@link CacheProvider#forSerializerCache(SerializationConfig)} + */ @Test - public void testDefaultCacheProviderConfigSerializerCache() throws Exception + public void sanityCheckSerializerCacheSize() throws Exception { - CacheProvider cacheProvider = DefaultCacheProvider.builder() - .maxSerializerCacheSize(1234) - .build(); - ObjectMapper mapper = JsonMapper.builder() - .cacheProvider(cacheProvider) - .build(); + // with positive value + _verifySerializeSuccess(_defaultProviderWithSerCache(1234)); - String json = mapper.writeValueAsString(new SerBean()); + // with zero value + _verifySerializeSuccess(_defaultProviderWithSerCache(0)); - assertEquals("{\"slide\":123}", json); + // custom + _verifySerializeSuccess(new CustomSerializerCacheProvider(new CustomTestSerializerCache())); } - @Test - public void testDefaultCacheProviderConfigSerializerCacheSizeZero() throws Exception + private CacheProvider _defaultProviderWithSerCache(int maxSerializerCacheSize) { - CacheProvider cacheProvider = DefaultCacheProvider.builder() - .maxSerializerCacheSize(0) + return DefaultCacheProvider.builder() + .maxSerializerCacheSize(maxSerializerCacheSize) .build(); - ObjectMapper mapper = JsonMapper.builder() - .cacheProvider(cacheProvider) - .build(); - - String json = mapper.writeValueAsString(new SerBean()); - - assertEquals("{\"slide\":123}", json); } - @Test - public void testCustomCacheProviderSerializerCacheConfig() throws Exception + private void _verifySerializeSuccess(CacheProvider cacheProvider) throws Exception { - CustomTestSerializerCache cache = new CustomTestSerializerCache(); ObjectMapper mapper = JsonMapper.builder() - .cacheProvider(new CustomSerializerCacheProvider(cache)) + .cacheProvider(cacheProvider) .build(); - - String json = mapper.writeValueAsString(new SerBean()); - - assertEquals("{\"slide\":123}", json); + assertEquals("{\"slide\":123}", + mapper.writeValueAsString(new SerBean())); } } From 87506ad1824b98f276bf3548c3604ecf2fcc7ece Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 19 Sep 2023 22:57:45 +0900 Subject: [PATCH 14/15] Update CacheProviderTest.java --- .../databind/cfg/CacheProviderTest.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index 472136c20b..e24d429f91 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -100,13 +100,9 @@ int createCacheCount() { } } - static class CustomSerializerCacheProvider implements CacheProvider { + static class CustomSerCacheProvider implements CacheProvider { - final CustomTestSerializerCache _cache; - - public CustomSerializerCacheProvider(CustomTestSerializerCache cache) { - _cache = cache; - } + final CustomTestSerializerCache _cache = new CustomTestSerializerCache(); @Override public LookupCache> forDeserializerCache(DeserializationConfig config) { @@ -120,10 +116,17 @@ public LookupCache> forSerializerCache(Serializa } static class CustomTestSerializerCache extends LRUMap> { + public boolean _isInvoked = false; public CustomTestSerializerCache() { super(8, 64); } - } + + @Override + public JsonSerializer put(TypeKey key, JsonSerializer value) { + _isInvoked = true; + return super.put(key, value); + } + } /* /********************************************************************** @@ -205,19 +208,18 @@ public void testBuilderValueValidation() throws Exception .build(); // validation fails - _verifyValidationFail(() -> DefaultCacheProvider.builder().maxDeserializerCacheSize(-1), - "Cannot set maxDeserializerCacheSize to a negative value"); + try { + DefaultCacheProvider.builder().maxDeserializerCacheSize(-1); + fail("Should not reach here"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Cannot set maxDeserializerCacheSize to a negative value")); + } // validation fails - _verifyValidationFail(() -> DefaultCacheProvider.builder().maxSerializerCacheSize(-1), - "Cannot set maxSerializerCacheSize to a negative value"); - } - - private void _verifyValidationFail(Runnable cacheProviderBuilder, String expectedErrorMsg) { try { - cacheProviderBuilder.run(); + DefaultCacheProvider.builder().maxSerializerCacheSize(-1); fail("Should not reach here"); } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains(expectedErrorMsg)); + assertTrue(e.getMessage().contains("Cannot set maxSerializerCacheSize to a negative value")); } } @@ -234,7 +236,9 @@ public void sanityCheckSerializerCacheSize() throws Exception _verifySerializeSuccess(_defaultProviderWithSerCache(0)); // custom - _verifySerializeSuccess(new CustomSerializerCacheProvider(new CustomTestSerializerCache())); + CustomSerCacheProvider customProvider = new CustomSerCacheProvider(); + _verifySerializeSuccess(customProvider); + assertTrue(customProvider._cache._isInvoked); // -- verify that custom cache is actually used } private CacheProvider _defaultProviderWithSerCache(int maxSerializerCacheSize) From b1967d9083092d9da3c005dee636b16c13721344 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Tue, 19 Sep 2023 23:02:43 +0900 Subject: [PATCH 15/15] Update CacheProviderTest.java --- .../jackson/databind/cfg/CacheProviderTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java index e24d429f91..9841997695 100644 --- a/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/cfg/CacheProviderTest.java @@ -116,6 +116,7 @@ public LookupCache> forSerializerCache(Serializa } static class CustomTestSerializerCache extends LRUMap> { + public boolean _isInvoked = false; public CustomTestSerializerCache() { super(8, 64); @@ -198,23 +199,25 @@ public void testDefaultCacheProviderSharesCache() throws Exception @Test public void testBuilderValueValidation() throws Exception { - // does not throw + // success cases DefaultCacheProvider.builder() .build(); - // does not throw, also + DefaultCacheProvider.builder() + .maxDeserializerCacheSize(0) + .maxSerializerCacheSize(0) + .build(); DefaultCacheProvider.builder() .maxDeserializerCacheSize(Integer.MAX_VALUE) .maxSerializerCacheSize(Integer.MAX_VALUE) .build(); - // validation fails + // fail cases try { DefaultCacheProvider.builder().maxDeserializerCacheSize(-1); fail("Should not reach here"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("Cannot set maxDeserializerCacheSize to a negative value")); } - // validation fails try { DefaultCacheProvider.builder().maxSerializerCacheSize(-1); fail("Should not reach here"); @@ -224,14 +227,13 @@ public void testBuilderValueValidation() throws Exception } /** - * Sanity test for {@link CacheProvider#forSerializerCache(SerializationConfig)} + * Sanity test for serialization with {@link CacheProvider#forSerializerCache(SerializationConfig)} */ @Test public void sanityCheckSerializerCacheSize() throws Exception { // with positive value _verifySerializeSuccess(_defaultProviderWithSerCache(1234)); - // with zero value _verifySerializeSuccess(_defaultProviderWithSerCache(0));