From 3606cef0a1d981794749cedf4be071d9d20ae28a Mon Sep 17 00:00:00 2001 From: Katelyn Baker Date: Thu, 15 Feb 2018 09:00:48 +0000 Subject: [PATCH] CORDA-1032 - unnamed ctor param serialization issue (#2535) --- .../serialization/amqp/SerializationHelper.kt | 9 ++++++-- .../amqp/JavaSerializationOutputTests.java | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt index 4ce172cc78..c9f41fcf22 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt @@ -213,8 +213,13 @@ internal fun propertiesForSerializationFromConstructor( return mutableListOf().apply { kotlinConstructor.parameters.withIndex().forEach { param -> - val name = param.value.name ?: throw NotSerializableException( - "Constructor parameter of $clazz has no name.") + // If a parameter doesn't have a name *at all* then chances are it's a synthesised + // one. A good example of this is non static nested classes in Java where instances + // of the nested class require access to the outer class without breaking + // encapsulation. Thus a parameter is inserted into the constructor that passes a + // reference to the enclosing class. In this case we can't do anything with + // it so just ignore it as it'll be supplied at runtime anyway on invocation + val name = param.value.name ?: return@forEach val propertyReader = if (name in classProperties) { if (classProperties[name]!!.getter != null) { diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java index 4379718003..b234fce399 100644 --- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java +++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java @@ -1,5 +1,8 @@ package net.corda.nodeapi.internal.serialization.amqp; +import com.google.common.collect.ImmutableList; +import net.corda.core.contracts.ContractState; +import net.corda.core.identity.AbstractParty; import net.corda.nodeapi.internal.serialization.AllWhitelist; import net.corda.core.serialization.SerializedBytes; import org.apache.qpid.proton.codec.DecoderImpl; @@ -9,6 +12,7 @@ import org.junit.Test; import javax.annotation.Nonnull; import java.io.NotSerializableException; import java.nio.ByteBuffer; +import java.util.List; import java.util.Objects; import static org.junit.Assert.assertTrue; @@ -234,4 +238,23 @@ public class JavaSerializationOutputTests { BoxedFooNotNull obj = new BoxedFooNotNull("Hello World!", 123); serdes(obj); } + + protected class DummyState implements ContractState { + @Override + public List getParticipants() { + return ImmutableList.of(); + } + } + + @Test + public void dummyStateSerialize() throws NotSerializableException { + SerializerFactory factory1 = new SerializerFactory( + AllWhitelist.INSTANCE, + ClassLoader.getSystemClassLoader(), + new EvolutionSerializerGetter()); + + SerializationOutput serializer = new SerializationOutput(factory1); + + serializer.serialize(new DummyState()); + } }