mirror of
https://github.com/corda/corda.git
synced 2025-03-02 20:49:06 +00:00
CORDA-2314 Complete class-carpentry before attempting evolution
This commit is contained in:
parent
1c4542fed7
commit
dc8cbef334
@ -218,28 +218,34 @@ open class SerializerFactory(
|
||||
* Iterate over an AMQP schema, for each type ascertain whether it's on ClassPath of [classloader] and,
|
||||
* if not, use the [ClassCarpenter] to generate a class to use in it's place.
|
||||
*/
|
||||
private fun processSchema(schemaAndDescriptor: FactorySchemaAndDescriptor, sentinel: Boolean = false) {
|
||||
private fun processSchema(schemaAndDescriptor: FactorySchemaAndDescriptor) {
|
||||
val metaSchema = CarpenterMetaSchema.newInstance()
|
||||
for (typeNotation in schemaAndDescriptor.schemas.schema.types) {
|
||||
logger.debug { "descriptor=${schemaAndDescriptor.typeDescriptor}, typeNotation=${typeNotation.name}" }
|
||||
val notationByName = schemaAndDescriptor.schemas.schema.types.associate { it.name to it }
|
||||
val noCarpentryRequired = notationByName.mapNotNull { (name, notation) ->
|
||||
try {
|
||||
val serialiser = processSchemaEntry(typeNotation)
|
||||
// if we just successfully built a serializer for the type but the type fingerprint
|
||||
// doesn't match that of the serialised object then we are dealing with different
|
||||
// instance of the class, as such we need to build an EvolutionSerializer
|
||||
if (serialiser.typeDescriptor != typeNotation.descriptor.name) {
|
||||
getEvolutionSerializer(typeNotation, serialiser, schemaAndDescriptor.schemas)
|
||||
}
|
||||
name to processSchemaEntry(notation)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
if (sentinel) throw e
|
||||
metaSchema.buildFor(typeNotation, classloader)
|
||||
metaSchema.buildFor(notation, classloader)
|
||||
null
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
if (metaSchema.isNotEmpty()) {
|
||||
val mc = MetaCarpenter(metaSchema, classCarpenter)
|
||||
mc.build()
|
||||
processSchema(schemaAndDescriptor, true)
|
||||
}
|
||||
|
||||
val carpented = notationByName.minus(noCarpentryRequired.keys).mapValues { (name, notation) ->
|
||||
processSchemaEntry(notation)
|
||||
}
|
||||
|
||||
val allLocalSerializers = noCarpentryRequired + carpented
|
||||
|
||||
allLocalSerializers.forEach { (name, serializer) ->
|
||||
val typeNotation = notationByName[name]!!
|
||||
if (serializer.typeDescriptor != typeNotation.descriptor.name ) {
|
||||
getEvolutionSerializer(typeNotation, serializer, schemaAndDescriptor.schemas)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -665,4 +665,26 @@ class EvolvabilityTests {
|
||||
assertEquals(4, deserializedC.d)
|
||||
assertEquals(5, deserializedC.e)
|
||||
}
|
||||
|
||||
// Class as it was serialized, with additional enum field.
|
||||
// enum class NewEnum { ONE, TWO, BUCKLE_MY_SHOE }
|
||||
// data class Evolved(val fnord: String, val newEnum: NewEnum)
|
||||
|
||||
// Class before evolution
|
||||
data class Evolved(val fnord: String)
|
||||
|
||||
@Test
|
||||
fun evolutionWithCarpentry() {
|
||||
val resource = "EvolvabilityTests.evolutionWithCarpentry"
|
||||
val sf = testDefaultFactory()
|
||||
// Uncomment to recreate
|
||||
// File(URI("$localPath/$resource")).writeBytes(SerializationOutput(sf).serialize(Evolved("dronf", NewEnum.BUCKLE_MY_SHOE)).bytes)
|
||||
|
||||
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||
|
||||
val sc2 = url.readBytes()
|
||||
val deserialized = DeserializationInput(sf).deserialize(SerializedBytes<Evolved>(sc2))
|
||||
|
||||
assertEquals("dronf", deserialized.fnord)
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user