Skip to content

Commit e69dd23

Browse files
authored
Merge pull request #78 from ProjectMapK/module-to-serializable
Fix ReflectionCache to be serializable
2 parents 293ebd1 + 856b32d commit e69dd23

File tree

4 files changed

+108
-1
lines changed

4 files changed

+108
-1
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@ import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.Meth
77
import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueCreator
88
import com.fasterxml.jackson.module.kotlin.ser.ValueClassBoxConverter
99
import kotlinx.metadata.KmClass
10+
import java.io.Serializable
1011
import java.lang.reflect.Constructor
1112
import java.lang.reflect.Executable
1213
import java.lang.reflect.Method
1314
import java.util.Optional
1415

15-
internal class ReflectionCache(reflectionCacheSize: Int) {
16+
internal class ReflectionCache(reflectionCacheSize: Int) : Serializable {
17+
companion object {
18+
// Increment is required when properties that use LRUMap are changed.
19+
private const val serialVersionUID = 1L
20+
}
21+
1622
// This cache is used for both serialization and deserialization, so reserve a larger size from the start.
1723
private val classCache = LRUMap<Class<*>, Optional<KmClass>>(reflectionCacheSize, reflectionCacheSize)
1824
private val creatorCache: LRUMap<Executable, ValueCreator<*>>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.fasterxml.jackson.module.kotlin
2+
3+
import org.junit.jupiter.api.Assertions.fail
4+
import java.io.ByteArrayInputStream
5+
import java.io.ByteArrayOutputStream
6+
import java.io.ObjectInputStream
7+
import java.io.ObjectOutputStream
8+
9+
fun jdkSerialize(o: Any): ByteArray {
10+
val bytes = ByteArrayOutputStream(1000)
11+
val obOut = ObjectOutputStream(bytes)
12+
obOut.writeObject(o)
13+
obOut.close()
14+
return bytes.toByteArray()
15+
}
16+
17+
fun <T> jdkDeserialize(raw: ByteArray): T {
18+
val objIn = ObjectInputStream(ByteArrayInputStream(raw))
19+
return try {
20+
@Suppress("UNCHECKED_CAST")
21+
objIn.readObject() as T
22+
} catch (e: ClassNotFoundException) {
23+
fail("Missing class: " + e.message)
24+
} finally {
25+
objIn.close()
26+
}
27+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.fasterxml.jackson.module.kotlin
2+
3+
import org.junit.jupiter.api.Assertions.assertEquals
4+
import org.junit.jupiter.api.Assertions.assertNotNull
5+
import org.junit.jupiter.api.Assertions.assertTrue
6+
import org.junit.jupiter.api.Test
7+
import org.junit.jupiter.api.assertDoesNotThrow
8+
9+
class KotlinModuleTest {
10+
@Test
11+
fun jdkSerializabilityTest() {
12+
val module = KotlinModule.Builder().apply {
13+
withReflectionCacheSize(123)
14+
enable(KotlinFeature.NullToEmptyCollection)
15+
enable(KotlinFeature.NullToEmptyMap)
16+
enable(KotlinFeature.NullIsSameAsDefault)
17+
enable(KotlinFeature.SingletonSupport)
18+
enable(KotlinFeature.StrictNullChecks)
19+
}.build()
20+
21+
val serialized = jdkSerialize(module)
22+
23+
assertDoesNotThrow {
24+
val deserialized = jdkDeserialize<KotlinModule>(serialized)
25+
26+
assertNotNull(deserialized)
27+
assertEquals(123, deserialized.reflectionCacheSize)
28+
assertTrue(deserialized.nullToEmptyCollection)
29+
assertTrue(deserialized.nullToEmptyMap)
30+
assertTrue(deserialized.nullIsSameAsDefault)
31+
assertTrue(deserialized.singletonSupport)
32+
assertTrue(deserialized.strictNullChecks)
33+
}
34+
}
35+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.fasterxml.jackson.module.kotlin
2+
3+
import org.junit.jupiter.api.Assertions.assertNotNull
4+
import org.junit.jupiter.api.Nested
5+
import org.junit.jupiter.api.Test
6+
import org.junit.jupiter.api.assertDoesNotThrow
7+
8+
class ReflectionCacheTest {
9+
@Nested
10+
inner class JDKSerializabilityTest {
11+
@Test
12+
fun emptyCache() {
13+
val cache = ReflectionCache(100)
14+
val serialized = jdkSerialize(cache)
15+
16+
assertDoesNotThrow {
17+
val deserialized = jdkDeserialize<ReflectionCache>(serialized)
18+
19+
assertNotNull(deserialized)
20+
// Deserialized instance also do not raise exceptions
21+
deserialized.getKmClass(this::class.java)
22+
}
23+
}
24+
25+
@Test
26+
fun notEmptyCache() {
27+
val cache = ReflectionCache(100).apply { getKmClass(this::class.java) }
28+
val serialized = jdkSerialize(cache)
29+
30+
assertDoesNotThrow {
31+
val deserialized = jdkDeserialize<ReflectionCache>(serialized)
32+
33+
assertNotNull(deserialized)
34+
// Deserialized instance also do not raise exceptions
35+
deserialized.getKmClass(this::class.java)
36+
}
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)