From 3682312067935b675e32bf3e01e9d2360e0fe6e2 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 16:47:33 +0100 Subject: [PATCH 1/8] remove use of ClassKey --- .../ScalaAnnotationIntrospectorModule.scala | 14 +++++++------- .../ScalaAnnotationIntrospectorTest.scala | 17 ++++++++--------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala index f15b2cdb..74ec8220 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala @@ -178,7 +178,7 @@ object ScalaAnnotationIntrospector extends NopAnnotationIntrospector with ValueI } private def _descriptorFor(clz: Class[_]): Option[BeanDescriptor] = { - val key = new ClassKey(clz) + val key = clz.getName val isScala = { Option(ScalaAnnotationIntrospectorModule._scalaTypeCache.get(key)) match { case Some(result) => result @@ -247,11 +247,11 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { this += { _.appendAnnotationIntrospector(ScalaAnnotationIntrospector) } this += { _.addValueInstantiators(ScalaAnnotationIntrospector) } - private[introspect] var _descriptorCache: LookupCache[ClassKey, BeanDescriptor] = - new LRUMap[ClassKey, BeanDescriptor](16, 100) + private[introspect] var _descriptorCache: LookupCache[String, BeanDescriptor] = + new LRUMap[String, BeanDescriptor](16, 100) - private[introspect] var _scalaTypeCache: LookupCache[ClassKey, Boolean] = - new LRUMap[ClassKey, Boolean](16, 1000) + private[introspect] var _scalaTypeCache: LookupCache[String, Boolean] = + new LRUMap[String, Boolean](16, 1000) private[introspect] val overrideMap = MutableMap[String, ClassOverrides]() @@ -326,7 +326,7 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { overrideMap.clear() } - def setDescriptorCache(cache: LookupCache[ClassKey, BeanDescriptor]): LookupCache[ClassKey, BeanDescriptor] = { + def setDescriptorCache(cache: LookupCache[String, BeanDescriptor]): LookupCache[String, BeanDescriptor] = { val existingCache = _descriptorCache _descriptorCache = cache existingCache @@ -339,7 +339,7 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { * @return old cache instance * @since 2.14.0 */ - def setScalaTypeCache(cache: LookupCache[ClassKey, Boolean]): LookupCache[ClassKey, Boolean] = { + def setScalaTypeCache(cache: LookupCache[String, Boolean]): LookupCache[String, Boolean] = { val existingCache = _scalaTypeCache _scalaTypeCache = cache existingCache diff --git a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala index a568704a..892d12a0 100644 --- a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala +++ b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala @@ -4,7 +4,6 @@ package introspect import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.`type`.ClassKey import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.ser.ContextualSerializer @@ -38,17 +37,17 @@ object ScalaAnnotationIntrospectorTest { case class CaseClassWithDefault(a: String = "defaultParam", b: Option[String] = Some("optionDefault"), c: Option[String]) - class ConcurrentLookupCache[T]() extends LookupCache[ClassKey, T] { - final private val cache = TrieMap.empty[ClassKey, T] + class ConcurrentLookupCache[T]() extends LookupCache[String, T] { + final private val cache = TrieMap.empty[String, T] - override def put(key: ClassKey, value: T): T = + override def put(key: String, value: T): T = cache.put(key, value).getOrElse(None.orNull).asInstanceOf[T] - override def putIfAbsent(key: ClassKey, value: T): T = + override def putIfAbsent(key: String, value: T): T = cache.putIfAbsent(key, value).getOrElse(None.orNull).asInstanceOf[T] override def get(key: Any): T = key match { - case classKey: ClassKey => cache.get(classKey).getOrElse(None.orNull).asInstanceOf[T] + case classKey: String => cache.get(classKey).getOrElse(None.orNull).asInstanceOf[T] case _ => None.orNull.asInstanceOf[T] } @@ -244,7 +243,7 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { withoutDefault.a shouldEqual "notDefault" cache.size shouldBe >=(1) - cache.get(new ClassKey(classOf[CaseClassWithDefault])) should not be (null) + cache.get(classOf[CaseClassWithDefault].getName) should not be (null) } finally { ScalaAnnotationIntrospectorModule.setDescriptorCache(defaultCache) } @@ -263,11 +262,11 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { withoutDefault.a shouldEqual "notDefault" cache.size shouldBe >=(1) - cache.get(new ClassKey(classOf[CaseClassWithDefault])) shouldBe true + cache.get(classOf[CaseClassWithDefault].getName) shouldBe true val javaValueHolder = mapper.readValue("\"2\"", classOf[ValueHolder]) javaValueHolder should not be(null) - cache.get(new ClassKey(classOf[ValueHolder])) shouldBe false + cache.get(classOf[ValueHolder].getName) shouldBe false } finally { ScalaAnnotationIntrospectorModule.setScalaTypeCache(defaultCache) } From b69e6d2c29a698635aea6580f6be57b91f11df7e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 17:14:38 +0100 Subject: [PATCH 2/8] new APIs for controlling the caches --- .../module/scala/LookupCacheFactory.scala | 16 ++++++++ .../ScalaAnnotationIntrospectorModule.scala | 39 ++++++++++++++++--- 2 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala b/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala new file mode 100644 index 00000000..3dfc7eab --- /dev/null +++ b/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala @@ -0,0 +1,16 @@ +package com.fasterxml.jackson.module.scala + +import com.fasterxml.jackson.databind.util.{LRUMap, LookupCache} + +/** + * Factory for creating {@link LookupCache} instances + */ +trait LookupCacheFactory { + def createLookupCache[K, V](initialEntries: Int, maxEntries: Int): LookupCache[K, V] +} + +object DefaultLookupCacheFactory extends LookupCacheFactory { + override def createLookupCache[K, V](initialEntries: Int, maxEntries: Int): LookupCache[K, V] = { + new LRUMap[K, V](initialEntries, maxEntries) + } +} diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala index 74ec8220..a9cc3ffd 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala @@ -2,14 +2,14 @@ package com.fasterxml.jackson.module.scala.introspect import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.core.Version -import com.fasterxml.jackson.databind.`type`.{ClassKey, CollectionLikeType, MapLikeType, ReferenceType, SimpleType} +import com.fasterxml.jackson.databind.`type`.{CollectionLikeType, MapLikeType, ReferenceType, SimpleType} import com.fasterxml.jackson.databind.cfg.MapperConfig import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator import com.fasterxml.jackson.databind.deser._ import com.fasterxml.jackson.databind.introspect._ -import com.fasterxml.jackson.databind.util.{AccessPattern, LRUMap, LookupCache} +import com.fasterxml.jackson.databind.util.{AccessPattern, LookupCache} import com.fasterxml.jackson.databind.{BeanDescription, DeserializationConfig, DeserializationContext, JavaType, MapperFeature} -import com.fasterxml.jackson.module.scala.JacksonModule +import com.fasterxml.jackson.module.scala.{DefaultLookupCacheFactory, JacksonModule, LookupCacheFactory} import com.fasterxml.jackson.module.scala.util.Implicits._ import java.lang.annotation.Annotation @@ -247,15 +247,39 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { this += { _.appendAnnotationIntrospector(ScalaAnnotationIntrospector) } this += { _.addValueInstantiators(ScalaAnnotationIntrospector) } + private var _lookupCacheFactory: LookupCacheFactory = DefaultLookupCacheFactory + private var _shouldSupportScala3Classes: Boolean = true + private var _descriptorCacheSize: Int = 100 + private var _scalaTypeCacheSize: Int = 1000 + private[introspect] var _descriptorCache: LookupCache[String, BeanDescriptor] = - new LRUMap[String, BeanDescriptor](16, 100) + _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) private[introspect] var _scalaTypeCache: LookupCache[String, Boolean] = - new LRUMap[String, Boolean](16, 1000) + _lookupCacheFactory.createLookupCache(16, _scalaTypeCacheSize) private[introspect] val overrideMap = MutableMap[String, ClassOverrides]() - private var _shouldSupportScala3Classes = true + def setLookupCacheFactory(lookupCacheFactory: LookupCacheFactory): Unit = { + _lookupCacheFactory = lookupCacheFactory + } + + private def recreateCaches(): Unit = { + _descriptorCache.clear() + _scalaTypeCache.clear() + _descriptorCache = _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) + _scalaTypeCache = _lookupCacheFactory.createLookupCache(16, _scalaTypeCacheSize) + } + + def setDescriptorCacheSize(size: Int): Unit = { + _descriptorCacheSize = size + _descriptorCache = _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) + } + + def setScalaTypeCacheSize(size: Int): Unit = { + _scalaTypeCacheSize = size + _scalaTypeCache = _lookupCacheFactory.createLookupCache(16, _scalaTypeCacheSize) + } /** * jackson-module-scala does not always properly handle deserialization of Options or Collections wrapping @@ -326,6 +350,7 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { overrideMap.clear() } + @deprecated("key type will change to String in v2.15.0 and this function will be removed in a later release", "2.14.3") def setDescriptorCache(cache: LookupCache[String, BeanDescriptor]): LookupCache[String, BeanDescriptor] = { val existingCache = _descriptorCache _descriptorCache = cache @@ -338,7 +363,9 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { * @param cache new cache instance * @return old cache instance * @since 2.14.0 + * @deprecated key type will change to String in v2.15.0 and this function will be removed in a later release */ + @deprecated("key type will change to String in v2.15.0 and this function will be removed in a later release", "2.14.3") def setScalaTypeCache(cache: LookupCache[String, Boolean]): LookupCache[String, Boolean] = { val existingCache = _scalaTypeCache _scalaTypeCache = cache From 4c61b90d75afd84b47e23197981d38cef696eaf6 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 17:51:22 +0100 Subject: [PATCH 3/8] start scaladoc --- .../jackson/module/scala/ScalaObjectMapper.scala | 6 +++--- .../jackson/module/scala/ClassTagExtensions.scala | 6 +++--- .../jackson/module/scala/LookupCacheFactory.scala | 2 +- .../ScalaAnnotationIntrospectorModule.scala | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/scala-2.+/com/fasterxml/jackson/module/scala/ScalaObjectMapper.scala b/src/main/scala-2.+/com/fasterxml/jackson/module/scala/ScalaObjectMapper.scala index 5122e049..fea05822 100644 --- a/src/main/scala-2.+/com/fasterxml/jackson/module/scala/ScalaObjectMapper.scala +++ b/src/main/scala-2.+/com/fasterxml/jackson/module/scala/ScalaObjectMapper.scala @@ -343,9 +343,9 @@ trait ScalaObjectMapper { * JSON. Same converters (serializers, deserializers) will be used as for * data binding, meaning same object mapper configuration works. * - * @throws IllegalArgumentException If conversion fails due to incompatible type; - * if so, root cause will contain underlying checked exception data binding - * functionality threw + * @throws java.lang.IllegalArgumentException If conversion fails due to incompatible type; + * if so, root cause will contain underlying checked exception data + * binding functionality threw */ def convertValue[T: Manifest](fromValue: Any): T = { convertValue(fromValue, constructType[T]) diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/ClassTagExtensions.scala b/src/main/scala/com/fasterxml/jackson/module/scala/ClassTagExtensions.scala index 49210303..cd55dea1 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/ClassTagExtensions.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/ClassTagExtensions.scala @@ -255,9 +255,9 @@ trait ClassTagExtensions { * JSON. Same converters (serializers, deserializers) will be used as for * data binding, meaning same object mapper configuration works. * - * @throws IllegalArgumentException If conversion fails due to incompatible type; - * if so, root cause will contain underlying checked exception data binding - * functionality threw + * @throws java.lang.IllegalArgumentException If conversion fails due to incompatible type; + * if so, root cause will contain underlying checked exception data + * binding functionality threw */ def convertValue[T: JavaTypeable](fromValue: Any): T = { convertValue(fromValue, constructType[T]) diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala b/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala index 3dfc7eab..e1730d18 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/LookupCacheFactory.scala @@ -3,7 +3,7 @@ package com.fasterxml.jackson.module.scala import com.fasterxml.jackson.databind.util.{LRUMap, LookupCache} /** - * Factory for creating {@link LookupCache} instances + * Factory for creating [[com.fasterxml.jackson.databind.util.LookupCache]] instances */ trait LookupCacheFactory { def createLookupCache[K, V](initialEntries: Int, maxEntries: Int): LookupCache[K, V] diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala index a9cc3ffd..8e6745d1 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala @@ -340,7 +340,7 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { } /** - * clears all the state associated with reference types + * Clears all the state associated with reference types * * @see [[registerReferencedValueType]] * @see [[clearRegisteredReferencedTypes(Class[_])]] @@ -350,6 +350,15 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { overrideMap.clear() } + /** + * Replace the Descriptor Cache. + * + * @param cache new cache instance + * @return the existing cache instance + * @see [[setDescriptorCacheSize]] + * @see [[setLookupCacheFactory]] + * @deprecated key type will change to String in v2.15.0 and this function will be removed in a later release + */ @deprecated("key type will change to String in v2.15.0 and this function will be removed in a later release", "2.14.3") def setDescriptorCache(cache: LookupCache[String, BeanDescriptor]): LookupCache[String, BeanDescriptor] = { val existingCache = _descriptorCache @@ -361,8 +370,10 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { * Override the default scalaTypeCache. * * @param cache new cache instance - * @return old cache instance + * @return existing cache instance * @since 2.14.0 + * @see [[setScalaTypeCacheSize]] + * @see [[setLookupCacheFactory]] * @deprecated key type will change to String in v2.15.0 and this function will be removed in a later release */ @deprecated("key type will change to String in v2.15.0 and this function will be removed in a later release", "2.14.3") From 33fa7d2121cde7c9d78f7568edbc789b0e0907d2 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 19:20:43 +0100 Subject: [PATCH 4/8] Update build.sbt --- build.sbt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.sbt b/build.sbt index 9bb10b39..4c821379 100644 --- a/build.sbt +++ b/build.sbt @@ -168,6 +168,12 @@ mimaBinaryIssueFilters ++= Seq( ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$_setter_$overrideMap_="), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_shouldSupportScala3Classes_="), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_shouldSupportScala3Classes"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_lookupCacheFactory"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_lookupCacheFactory_="), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_descriptorCacheSize"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_descriptorCacheSize_="), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_scalaTypeCacheSize"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_scalaTypeCacheSize_="), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.clearRegisteredReferencedTypes"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.registerReferencedValueType"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.getRegisteredReferencedValueType"), From 114b694a5c0bf032fe8255aaf0579668c8788e07 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 19:26:01 +0100 Subject: [PATCH 5/8] Update build.sbt --- build.sbt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.sbt b/build.sbt index 4c821379..39a839f7 100644 --- a/build.sbt +++ b/build.sbt @@ -174,6 +174,9 @@ mimaBinaryIssueFilters ++= Seq( ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_descriptorCacheSize_="), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_scalaTypeCacheSize"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.com$fasterxml$jackson$module$scala$introspect$ScalaAnnotationIntrospectorModule$$_scalaTypeCacheSize_="), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.setLookupCacheFactory"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.setDescriptorCacheSize"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.setScalaTypeCacheSize"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.clearRegisteredReferencedTypes"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.registerReferencedValueType"), ProblemFilters.exclude[ReversedMissingMethodProblem]("com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospectorModule.getRegisteredReferencedValueType"), From 29902d58d0e917488ee48ccdcb74f228e19f8289 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 19:56:10 +0100 Subject: [PATCH 6/8] more scaladoc changes --- .../ScalaAnnotationIntrospectorModule.scala | 59 ++++++++++++++++--- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala index 8e6745d1..4b1dc926 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorModule.scala @@ -260,24 +260,65 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { private[introspect] val overrideMap = MutableMap[String, ClassOverrides]() + /** + * Replaces the [[LookupCacheFactory]]. The default factory uses [[com.fasterxml.jackson.databind.util.LRUMap]]. + *

+ * Note that this clears the existing cache entries. It is best to set this up before you start using + * the Jackson Scala Module for serializing/deserializing. + *

+ * + * @param lookupCacheFactory new factory + * @see [[setDescriptorCacheSize]] + * @see [[setScalaTypeCacheSize]] + * @since 2.14.3 + */ def setLookupCacheFactory(lookupCacheFactory: LookupCacheFactory): Unit = { _lookupCacheFactory = lookupCacheFactory + recreateDescriptorCache() + recreateScalaTypeCache() } - private def recreateCaches(): Unit = { - _descriptorCache.clear() - _scalaTypeCache.clear() - _descriptorCache = _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) - _scalaTypeCache = _lookupCacheFactory.createLookupCache(16, _scalaTypeCacheSize) - } - + /** + * Resize the descriptorCache. The default size is 100. + *

+ * Note that this clears the existing cache entries. It is best to set this up before you start using + * the Jackson Scala Module for serializing/deserializing. + *

+ * + * @param size new size for the cache + * @see [[setScalaTypeCacheSize]] + * @see [[setLookupCacheFactory]] + * @since 2.14.3 + */ def setDescriptorCacheSize(size: Int): Unit = { _descriptorCacheSize = size - _descriptorCache = _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) + recreateDescriptorCache() } + /** + * Resize the scalaTypeCache. The default size is 1000. + *

+ * Note that this clears the existing cache entries. It is best to set this up before you start using + * the Jackson Scala Module for serializing/deserializing. + *

+ * + * @param size new size for the cache + * @see [[setDescriptorCacheSize]] + * @see [[setLookupCacheFactory]] + * @since 2.14.3 + */ def setScalaTypeCacheSize(size: Int): Unit = { _scalaTypeCacheSize = size + recreateScalaTypeCache() + } + + private def recreateDescriptorCache(): Unit = { + _descriptorCache.clear() + _descriptorCache = _lookupCacheFactory.createLookupCache(16, _descriptorCacheSize) + } + + private def recreateScalaTypeCache(): Unit = { + _scalaTypeCache.clear() _scalaTypeCache = _lookupCacheFactory.createLookupCache(16, _scalaTypeCacheSize) } @@ -351,7 +392,7 @@ trait ScalaAnnotationIntrospectorModule extends JacksonModule { } /** - * Replace the Descriptor Cache. + * Replace the descriptorCache Date: Fri, 17 Feb 2023 23:14:18 +0100 Subject: [PATCH 7/8] Update ScalaAnnotationIntrospectorTest.scala --- .../ScalaAnnotationIntrospectorTest.scala | 51 ++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala index 892d12a0..478217f6 100644 --- a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala +++ b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala @@ -37,18 +37,18 @@ object ScalaAnnotationIntrospectorTest { case class CaseClassWithDefault(a: String = "defaultParam", b: Option[String] = Some("optionDefault"), c: Option[String]) - class ConcurrentLookupCache[T]() extends LookupCache[String, T] { - final private val cache = TrieMap.empty[String, T] + class ConcurrentLookupCache[K, V]() extends LookupCache[K, V] { + final private val cache = TrieMap.empty[K, V] - override def put(key: String, value: T): T = - cache.put(key, value).getOrElse(None.orNull).asInstanceOf[T] + override def put(key: K, value: V): V = + cache.put(key, value).getOrElse(None.orNull).asInstanceOf[V] - override def putIfAbsent(key: String, value: T): T = - cache.putIfAbsent(key, value).getOrElse(None.orNull).asInstanceOf[T] + override def putIfAbsent(key: K, value: V): V = + cache.putIfAbsent(key, value).getOrElse(None.orNull).asInstanceOf[V] - override def get(key: Any): T = key match { - case classKey: String => cache.get(classKey).getOrElse(None.orNull).asInstanceOf[T] - case _ => None.orNull.asInstanceOf[T] + override def get(key: Any): V = key match { + case classKey: K => cache.get(classKey).getOrElse(None.orNull).asInstanceOf[V] + case _ => None.orNull.asInstanceOf[V] } override def clear(): Unit = { @@ -57,6 +57,11 @@ object ScalaAnnotationIntrospectorTest { override def size: Int = cache.size } + + object ConcurrentLookupCacheFactory extends LookupCacheFactory { + override def createLookupCache[K, V](initialEntries: Int, maxEntries: Int): LookupCache[K, V] = + new ConcurrentLookupCache[K, V] + } } class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { @@ -230,10 +235,10 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { } } - it should "allow descriptor cache to be replaced" in { _ => + it should "allow descriptor cache to be replaced (old style)" in { _ => val defaultCache = ScalaAnnotationIntrospectorModule._descriptorCache try { - val cache = new ConcurrentLookupCache[BeanDescriptor]() + val cache = new ConcurrentLookupCache[String, BeanDescriptor]() ScalaAnnotationIntrospectorModule.setDescriptorCache(cache) val builder = JsonMapper.builder().addModule(DefaultScalaModule) val mapper = builder.build() @@ -249,10 +254,32 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { } } + it should "allow descriptor cache to be replaced (new style)" in { _ => + val defaultCache = ScalaAnnotationIntrospectorModule._descriptorCache + try { + ScalaAnnotationIntrospectorModule.setLookupCacheFactory(ConcurrentLookupCacheFactory) + val builder = JsonMapper.builder().addModule(DefaultScalaModule) + val mapper = builder.build() + val jsonWithKey = """{"a": "notDefault"}""" + + val withoutDefault = mapper.readValue(jsonWithKey, classOf[CaseClassWithDefault]) + withoutDefault.a shouldEqual "notDefault" + + ScalaAnnotationIntrospectorModule._descriptorCache shouldBe a[ConcurrentLookupCache[String, BeanDescriptor]] + val cache = ScalaAnnotationIntrospectorModule._descriptorCache + .asInstanceOf[ConcurrentLookupCache[String, BeanDescriptor]] + cache.size shouldBe >=(1) + cache.get(classOf[CaseClassWithDefault].getName) should not be (null) + defaultCache.size() shouldEqual 0 + } finally { + ScalaAnnotationIntrospectorModule.setLookupCacheFactory(DefaultLookupCacheFactory) + } + } + it should "allow scala type cache to be replaced" in { _ => val defaultCache = ScalaAnnotationIntrospectorModule._scalaTypeCache try { - val cache = new ConcurrentLookupCache[Boolean]() + val cache = new ConcurrentLookupCache[String, Boolean]() ScalaAnnotationIntrospectorModule.setScalaTypeCache(cache) val builder = JsonMapper.builder().addModule(DefaultScalaModule) val mapper = builder.build() From 09cc458492e0fdc08e177b0a968b5807af5f00a2 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Feb 2023 23:18:38 +0100 Subject: [PATCH 8/8] extend test --- .../ScalaAnnotationIntrospectorTest.scala | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala index 478217f6..f7bb3ac2 100644 --- a/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala +++ b/src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala @@ -46,9 +46,8 @@ object ScalaAnnotationIntrospectorTest { override def putIfAbsent(key: K, value: V): V = cache.putIfAbsent(key, value).getOrElse(None.orNull).asInstanceOf[V] - override def get(key: Any): V = key match { - case classKey: K => cache.get(classKey).getOrElse(None.orNull).asInstanceOf[V] - case _ => None.orNull.asInstanceOf[V] + override def get(key: Any): V = { + cache.get(key.asInstanceOf[K]).getOrElse(None.orNull).asInstanceOf[V] } override def clear(): Unit = { @@ -276,7 +275,7 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { } } - it should "allow scala type cache to be replaced" in { _ => + it should "allow scala type cache to be replaced (old style)" in { _ => val defaultCache = ScalaAnnotationIntrospectorModule._scalaTypeCache try { val cache = new ConcurrentLookupCache[String, Boolean]() @@ -299,6 +298,33 @@ class ScalaAnnotationIntrospectorTest extends FixtureAnyFlatSpec with Matchers { } } + it should "allow scala type cache to be replaced (new style)" in { _ => + val defaultCache = ScalaAnnotationIntrospectorModule._scalaTypeCache + try { + ScalaAnnotationIntrospectorModule.setLookupCacheFactory(ConcurrentLookupCacheFactory) + val builder = JsonMapper.builder().addModule(DefaultScalaModule) + val mapper = builder.build() + val jsonWithKey = """{"a": "notDefault"}""" + + val withoutDefault = mapper.readValue(jsonWithKey, classOf[CaseClassWithDefault]) + withoutDefault.a shouldEqual "notDefault" + + ScalaAnnotationIntrospectorModule._scalaTypeCache shouldBe a[ConcurrentLookupCache[String, Boolean]] + val cache = ScalaAnnotationIntrospectorModule._scalaTypeCache + .asInstanceOf[ConcurrentLookupCache[String, Boolean]] + cache.size shouldBe >=(1) + cache.get(classOf[CaseClassWithDefault].getName) shouldBe true + + val javaValueHolder = mapper.readValue("\"2\"", classOf[ValueHolder]) + javaValueHolder should not be (null) + cache.get(classOf[ValueHolder].getName) shouldBe false + + defaultCache.size() shouldEqual 0 + } finally { + ScalaAnnotationIntrospectorModule.setLookupCacheFactory(DefaultLookupCacheFactory) + } + } + it should "allow scala3 check to be disabled" in { _ => ScalaAnnotationIntrospectorModule.shouldSupportScala3Classes() shouldBe true try {