问题
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