How to resolve a “NotSerializableException” thrown when unit testing a plain implementation of “LinearState”

五迷三道 提交于 2019-12-10 12:23:13

问题


I have a plain implementation of "LinearState" where the only parameter is a UniqueIdentifier. I have a simple Contract to go with it.

When I try to put it through unit testing, however, I keep getting "NotSerializabeException".

I'm using the Corda v4 java template. Testing setup with Gradle Runner on IntelliJ.

I've tried annotating the class with @CordaSerializable, and the constructor with @ConstructorForDeserialization

@CordaSerializable
public class InvestorState implements LinearState {

    private final UniqueIdentifier linearId;

    @ConstructorForDeserialization
    public InvestorState(UniqueIdentifier id) {
        this.linearId = id;
    }
...
}
Error log:
data(net.corda.core.contracts.ContractState) -> Trying to build an object serializer for com.mycordapp.states.InvestorState, but it is not constructible from its public properties, and so requires a custom serialiser.

java.io.NotSerializableException: data(net.corda.core.contracts.ContractState) -> Trying to build an object serializer for com.mycordapp.states.InvestorState, but it is not constructible from its public properties, and so requires a custom serialiser.

at net.corda.serialization.internal.amqp.ObjectSerializer$Companion.make(ObjectSerializer.kt:18)
at net.corda.serialization.internal.amqp.DefaultLocalSerializerFactory.makeNonCustomSerializer(LocalSerializerFactory.kt:240)
...

回答1:


I found out that the arguments listed in the constructor must be identical to the declared variables.

My corrected code:

@BelongsToContract(InvestorContract.class) // note this is required for Corda v4
@CordaSerializable // not strictly necessary as this class implements LinearState
public class InvestorState implements LinearState {

    private final UniqueIdentifier linearId;

    @ConstructorForDeserialization // only necessary if there are multiple constructors
    public InvestorState(UniqueIdentifier linearId) {
        this.linearId = linearId;
    }
...
}

In my case, changing the constructor argument 'id' to 'linearId' as it was first declared solved the problem




回答2:


Just my two cents for future reference: From Corda documentation:

It is recommended that serializable objects in Corda adhere to the following rules, as they allow immutable state objects to be deserialised:

  • A Java Bean getter for each of the properties in the constructor, with a name of the form getX. For example, for a constructor parameter foo, there must be a getter called getFoo().

If foo is a boolean, the getter may optionally be called isFoo() (this is why the class must be compiled with parameter names turned on)

  • A constructor which takes all of the properties that you wish to record in the serialized form.

This is required in order for the serialization framework to reconstruct an instance of your class.

If more than one constructor is provided, the serialization framework needs to know which one to use. The @ConstructorForDeserialization annotation can be used to indicate which one.

For a Kotlin class, without the @ConstructorForDeserialization annotation, the primary constructor will be selected.



来源:https://stackoverflow.com/questions/55501303/how-to-resolve-a-notserializableexception-thrown-when-unit-testing-a-plain-imp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!