[CORDA-2473] - Remove AMQP system property (#5112)

This commit is contained in:
Dimos Raptis 2019-05-14 13:22:23 +01:00 committed by Shams Asari
parent ab8d4a312a
commit a468bee0ed
4 changed files with 18 additions and 73 deletions

View File

@ -23,7 +23,6 @@ import net.corda.serialization.internal.amqp.SerializationFactoryCacheKey
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import java.time.Duration import java.time.Duration
import java.util.ServiceLoader import java.util.ServiceLoader
import java.net.URLClassLoader
/** /**
* This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically. * This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically.
@ -300,14 +299,11 @@ class CordaRPCClient private constructor(
try { try {
val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap() val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap()
// If the client has provided a classloader, the associated classpath is checked for available custom serializers and serialization whitelists. // If the client has explicitly provided a classloader use this one to scan for custom serializers, otherwise use the current one.
if (classLoader != null) { val serializationClassLoader = this.classLoader ?: this.javaClass.classLoader
val customSerializers = createInstancesOfClassesImplementing(classLoader, SerializationCustomSerializer::class.java) val customSerializers = createInstancesOfClassesImplementing(serializationClassLoader, SerializationCustomSerializer::class.java)
val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, classLoader).toSet() val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, serializationClassLoader).toSet()
AMQPClientSerializationScheme.initialiseSerialization(classLoader, customSerializers, serializationWhitelists, cache) AMQPClientSerializationScheme.initialiseSerialization(serializationClassLoader, customSerializers, serializationWhitelists, cache)
} else {
AMQPClientSerializationScheme.initialiseSerialization(classLoader, serializerFactoriesForContexts = cache)
}
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
// Race e.g. two of these constructed in parallel, ignore. // Race e.g. two of these constructed in parallel, ignore.
} }

View File

@ -27,10 +27,7 @@ Serializers must
* Inherit from ``net.corda.core.serialization.SerializationCustomSerializer`` * Inherit from ``net.corda.core.serialization.SerializationCustomSerializer``
* Provide a proxy class to transform the object to and from * Provide a proxy class to transform the object to and from
* Implement the ``toProxy`` and ``fromProxy`` methods * Implement the ``toProxy`` and ``fromProxy`` methods
* Be either included into the CorDapp Jar or made known to the running process via the ``amqp.custom.serialization.scanSpec`` * Be either included into the CorDapp Jar or made available in the system class path of the running process
system property. This system property may be necessary to be able to discover custom serializer in the classpath.
At a minimum the value of the property should include comma separated set of packages where custom serializers located.
Full syntax includes scanning specification as defined by: `<http://github.com/lukehutch/fast-classpath-scanner/wiki/2.-Constructor#scan-spec>`
Serializers inheriting from ``SerializationCustomSerializer`` have to implement two methods and two types. Serializers inheriting from ``SerializationCustomSerializer`` have to implement two methods and two types.

View File

@ -2,7 +2,6 @@
package net.corda.serialization.internal.amqp package net.corda.serialization.internal.amqp
import io.github.classgraph.ClassGraph
import net.corda.core.DeleteForDJVM import net.corda.core.DeleteForDJVM
import net.corda.core.KeepForDJVM import net.corda.core.KeepForDJVM
import net.corda.core.StubOutForDJVM import net.corda.core.StubOutForDJVM
@ -10,7 +9,6 @@ import net.corda.core.cordapp.Cordapp
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.core.utilities.contextLogger
import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.DefaultWhitelist import net.corda.serialization.internal.DefaultWhitelist
import net.corda.serialization.internal.MutableClassWhitelist import net.corda.serialization.internal.MutableClassWhitelist
@ -57,44 +55,8 @@ abstract class AbstractAMQPSerializationScheme(
maybeNotConcurrentSerializerFactoriesForContexts maybeNotConcurrentSerializerFactoriesForContexts
} }
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
companion object { companion object {
const val SCAN_SPEC_PROP_NAME = "amqp.custom.serialization.scanSpec" private val serializationWhitelists: List<SerializationWhitelist> by lazy { listOf(DefaultWhitelist) }
private val logger = contextLogger()
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
ServiceLoader.load(SerializationWhitelist::class.java, this::class.java.classLoader).toList() + DefaultWhitelist
}
private val customSerializers: List<SerializationCustomSerializer<*, *>> by lazy {
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
if (scanSpec == null) {
logger.debug("scanSpec not set, not scanning for Custom Serializers")
emptyList()
} else {
logger.debug("scanSpec = \"$scanSpec\", scanning for Custom Serializers")
scanClasspathForSerializers(scanSpec)
}
}
@StubOutForDJVM
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
this::class.java.classLoader.let { cl ->
ClassGraph()
.whitelistPackages(scanSpec)
.addClassLoader(cl)
.enableAllInfo()
.pooledScan()
.use {
val serializerClass = SerializationCustomSerializer::class.java
it.getClassesImplementing(serializerClass.name).loadClasses(serializerClass)
}
.filterNot { it.isAbstractClass }
.map { it.kotlin.objectOrNewInstance() }
}
@DeleteForDJVM @DeleteForDJVM
val List<Cordapp>.customSerializers val List<Cordapp>.customSerializers
@ -140,26 +102,16 @@ abstract class AbstractAMQPSerializationScheme(
registerNonDeterministicSerializers(factory) registerNonDeterministicSerializers(factory)
} }
// If we're passed in an external list we trust that, otherwise revert to looking at the scan of the // This step is registering custom serializers, which have been added after node initialisation (i.e. via attachments during transaction verification).
// classpath to find custom serializers. // Note: the order between the registration of customSerializers and cordappCustomSerializers must be preserved as-is. The reason is the following:
if (cordappCustomSerializers.isEmpty()) { // Currently, the serialization infrastructure does not support multiple versions of a class (the first one that is registered dominates).
for (customSerializer in customSerializers) { // As a result, when inside a context with attachments class loader, we prioritize serializers loaded on-demand from attachments to serializers that had been
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory)) // loaded during node initialisation, by scanning the cordapps folder.
} context.customSerializers.forEach { customSerializer ->
} else { factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
// This step is registering custom serializers, which have been added after node initialisation (i.e. via attachments during transaction verification). }
// Note: the order between the registration of customSerializers and cordappCustomSerializers must be preserved as-is. The reason is the following: cordappCustomSerializers.forEach { customSerializer ->
// Currently, the serialization infrastructure does not support multiple versions of a class (the first one that is registered dominates). factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
// As a result, when inside a context with attachments class loader, we prioritize serializers loaded on-demand from attachments to serializers that had been
// loaded during node initialisation, by scanning the cordapps folder.
context.customSerializers.forEach { customSerializer ->
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
}
logger.debug("Custom Serializer list loaded - not scanning classpath")
cordappCustomSerializers.forEach { customSerializer ->
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
}
} }
context.properties[ContextPropertyKeys.SERIALIZERS]?.apply { context.properties[ContextPropertyKeys.SERIALIZERS]?.apply {

View File

@ -802,7 +802,7 @@ class DriverDSLImpl(
) )
} }
private val propertiesInScope = setOf("java.io.tmpdir", AbstractAMQPSerializationScheme.SCAN_SPEC_PROP_NAME) private val propertiesInScope = setOf("java.io.tmpdir")
private fun inheritFromParentProcess(): Iterable<Pair<String, String>> { private fun inheritFromParentProcess(): Iterable<Pair<String, String>> {
return propertiesInScope.flatMap { propName -> return propertiesInScope.flatMap { propName ->