diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt index 97a925a5c..f229cec8a 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt @@ -5,13 +5,19 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMember import com.fasterxml.jackson.databind.introspect.AnnotatedMethod import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams import com.fasterxml.jackson.databind.util.LRUMap +import java.io.Serializable import java.lang.reflect.Constructor import java.lang.reflect.Executable import java.lang.reflect.Method import kotlin.reflect.KFunction import kotlin.reflect.jvm.kotlinFunction -internal class ReflectionCache(reflectionCacheSize: Int) { +internal class ReflectionCache(reflectionCacheSize: Int) : Serializable { + companion object { + // Increment is required when properties that use LRUMap are changed. + private const val serialVersionUID = 1L + } + sealed class BooleanTriState(val value: Boolean?) { class True : BooleanTriState(true) class False : BooleanTriState(false) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/JDKSerializabilityTestHelper.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/JDKSerializabilityTestHelper.kt new file mode 100644 index 000000000..a5af1dbdf --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/JDKSerializabilityTestHelper.kt @@ -0,0 +1,28 @@ +package com.fasterxml.jackson.module.kotlin + +import junit.framework.TestCase +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream + +fun jdkSerialize(o: Any): ByteArray { + val bytes = ByteArrayOutputStream(1000) + val obOut = ObjectOutputStream(bytes) + obOut.writeObject(o) + obOut.close() + return bytes.toByteArray() +} + +fun jdkDeserialize(raw: ByteArray): T? { + val objIn = ObjectInputStream(ByteArrayInputStream(raw)) + return try { + @Suppress("UNCHECKED_CAST") + objIn.readObject() as T + } catch (e: ClassNotFoundException) { + TestCase.fail("Missing class: " + e.message) + null + } finally { + objIn.close() + } +} diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModuleTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModuleTest.kt index fe2e07cd7..6968c835c 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModuleTest.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModuleTest.kt @@ -11,6 +11,7 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test +import kotlin.test.assertNotNull class KotlinModuleTest { /** @@ -103,4 +104,27 @@ class KotlinModuleTest { assertTrue(module.strictNullChecks) } + + @Test + fun jdkSerializabilityTest() { + val module = KotlinModule.Builder().apply { + withReflectionCacheSize(123) + enable(NullToEmptyCollection) + enable(NullToEmptyMap) + enable(NullIsSameAsDefault) + enable(SingletonSupport) + enable(StrictNullChecks) + }.build() + + val serialized = jdkSerialize(module) + val deserialized = jdkDeserialize(serialized) + + assertNotNull(deserialized) + assertEquals(123, deserialized.reflectionCacheSize) + assertTrue(deserialized.nullToEmptyCollection) + assertTrue(deserialized.nullToEmptyMap) + assertTrue(deserialized.nullIsSameAsDefault) + assertEquals(CANONICALIZE, deserialized.singletonSupport) + assertTrue(deserialized.strictNullChecks) + } } diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCacheTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCacheTest.kt new file mode 100644 index 000000000..7914a402a --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCacheTest.kt @@ -0,0 +1,30 @@ +package com.fasterxml.jackson.module.kotlin + +import org.junit.Test +import kotlin.test.assertNotNull + +class ReflectionCacheTest { + @Test + fun serializeEmptyCache() { + val cache = ReflectionCache(100) + val serialized = jdkSerialize(cache) + val deserialized = jdkDeserialize(serialized) + + assertNotNull(deserialized) + // Deserialized instance also do not raise exceptions + deserialized.kotlinFromJava(ReflectionCacheTest::class.java.getDeclaredMethod("serializeEmptyCache")) + } + + @Test + fun serializeNotEmptyCache() { + val method = ReflectionCacheTest::class.java.getDeclaredMethod("serializeNotEmptyCache") + + val cache = ReflectionCache(100).apply { kotlinFromJava(method) } + val serialized = jdkSerialize(cache) + val deserialized = jdkDeserialize(serialized) + + assertNotNull(deserialized) + // Deserialized instance also do not raise exceptions + deserialized.kotlinFromJava(method) + } +}