CORDA-540: Add a property to make sending stacktraces optional in AMQP mode (#1458)

This commit is contained in:
Viktor Kolomeyko 2017-09-08 17:25:42 +01:00 committed by GitHub
parent 628d94c070
commit 0edaea81d2
4 changed files with 34 additions and 11 deletions

View File

@ -60,7 +60,7 @@ abstract class SerializationFactory {
* Allow subclasses to temporarily mark themselves as the current factory for the current thread during serialization/deserialization.
* Will restore the prior context on exiting the block.
*/
protected fun <T> asCurrent(block: SerializationFactory.() -> T): T {
fun <T> asCurrent(block: SerializationFactory.() -> T): T {
val priorContext = _currentFactory.get()
_currentFactory.set(this)
try {

View File

@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.primitives.Primitives
import com.google.common.reflect.TypeToken
import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.codec.Data
import java.beans.IndexedPropertyDescriptor
import java.beans.Introspector
@ -229,4 +230,11 @@ internal fun Type.isSubClassOf(type: Type): Boolean {
internal fun suitableForObjectReference(type: Type): Boolean {
val clazz = type.asClass()
return type != ByteArray::class.java && (clazz != null && !clazz.isPrimitive && !Primitives.unwrap(clazz).isPrimitive)
}
/**
* Common properties that are to be used in the [SerializationContext.properties] to alter serialization behavior/content
*/
internal enum class CommonPropertyNames {
IncludeInternalInfo,
}

View File

@ -2,11 +2,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.CordaRuntimeException
import net.corda.core.CordaThrowable
import net.corda.core.serialization.SerializationFactory
import net.corda.core.utilities.loggerFor
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
import net.corda.nodeapi.internal.serialization.amqp.constructorForDeserialization
import net.corda.nodeapi.internal.serialization.amqp.propertiesForSerialization
import net.corda.nodeapi.internal.serialization.amqp.*
import java.io.NotSerializableException
class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Throwable, ThrowableSerializer.ThrowableProxy>(Throwable::class.java, ThrowableProxy::class.java, factory) {
@ -33,7 +31,14 @@ class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<T
} else {
obj.message
}
return ThrowableProxy(obj.javaClass.name, message, obj.stackTrace, obj.cause, obj.suppressed, extraProperties)
val stackTraceToInclude = if (shouldIncludeInternalInfo()) obj.stackTrace else emptyArray()
return ThrowableProxy(obj.javaClass.name, message, stackTraceToInclude, obj.cause, obj.suppressed, extraProperties)
}
private fun shouldIncludeInternalInfo(): Boolean {
val currentContext = SerializationFactory.currentFactory?.currentContext
val includeInternalInfo = currentContext?.properties?.get(CommonPropertyNames.IncludeInternalInfo)
return true == includeInternalInfo
}
override fun fromProxy(proxy: ThrowableProxy): Throwable {

View File

@ -9,6 +9,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowException
import net.corda.core.identity.AbstractParty
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationFactory
import net.corda.core.transactions.LedgerTransaction
import net.corda.nodeapi.RPCException
import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme
@ -18,6 +19,7 @@ import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion
import net.corda.testing.BOB_IDENTITY
import net.corda.testing.MEGA_CORP
import net.corda.testing.MEGA_CORP_PUBKEY
import net.corda.testing.withTestSerialization
import org.apache.qpid.proton.amqp.*
import org.apache.qpid.proton.codec.DecoderImpl
import org.apache.qpid.proton.codec.EncoderImpl
@ -418,10 +420,18 @@ class SerializationOutputTests {
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val t = IllegalAccessException("message").fillInStackTrace()
val desThrowable = serdes(t, factory, factory2, false) as Throwable
val desThrowable = serdesThrowableWithInternalInfo(t, factory, factory2, false)
assertSerializedThrowableEquivalent(t, desThrowable)
}
private fun serdesThrowableWithInternalInfo(t: Throwable, factory: SerializerFactory, factory2: SerializerFactory, expectedEqual: Boolean = true): Throwable = withTestSerialization {
val newContext = SerializationFactory.defaultFactory.defaultContext.withProperty(CommonPropertyNames.IncludeInternalInfo, true)
val deserializedObj = SerializationFactory.defaultFactory.asCurrent { withCurrentContext(newContext) { serdes(t, factory, factory2, expectedEqual) } }
return deserializedObj
}
@Test
fun `test complex throwables serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
@ -437,7 +447,7 @@ class SerializationOutputTests {
throw IllegalStateException("Layer 2", t)
}
} catch(t: Throwable) {
val desThrowable = serdes(t, factory, factory2, false)
val desThrowable = serdesThrowableWithInternalInfo(t, factory, factory2, false)
assertSerializedThrowableEquivalent(t, desThrowable)
}
}
@ -469,7 +479,7 @@ class SerializationOutputTests {
throw e
}
} catch(t: Throwable) {
val desThrowable = serdes(t, factory, factory2, false)
val desThrowable = serdesThrowableWithInternalInfo(t, factory, factory2, false)
assertSerializedThrowableEquivalent(t, desThrowable)
}
}
@ -483,7 +493,7 @@ class SerializationOutputTests {
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val obj = FlowException("message").fillInStackTrace()
serdes(obj, factory, factory2)
serdesThrowableWithInternalInfo(obj, factory, factory2)
}
@Test
@ -495,7 +505,7 @@ class SerializationOutputTests {
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val obj = RPCException("message").fillInStackTrace()
serdes(obj, factory, factory2)
serdesThrowableWithInternalInfo(obj, factory, factory2)
}
@Test