2

When running Corda contract tests in IntelliJ, tests written in Java sometimes fail with the following exception:

[ERROR] 17:02:51,821 [main] (Schema.kt:437) amqp.Schema.fingerprintForType - Constructor parameter arg0 doesn't refer to a property of class 'class mypackage.MyState' -> class mypackage.MyState {} java.io.NotSerializableException: Constructor parameter arg0 doesn't refer to a property of class 'class mypackage.MyState' at net.corda.nodeapi.internal.serialization.amqp.SerializationHelperKt.propertiesForSerializationFromConstructor(SerializationHelper.kt:249) ~[corda-node-api-corda-3.0.jar:?]

How can I fix this?

Joel
  • 22,762
  • 5
  • 26
  • 41

2 Answers2

7

As explained by Joel, by default, compiled Java classes will use default names for their constructor parameters. In Corda case, we should to use the same name for parameter names, not because is better to identify each of them or they are so beautiful to keep the same name, but because there is a validation during the serialization and deserialization realized by AMQP through a component customized and re-write specifically to Corda (corda-node-api). This component checks each attribute involved during the Transaction (ContractState). Reminder that in Corda all serialization and deserialization is controlled and can be fail if something is conflicting.

To solve this problem, there are different forms, it depends on which tool you are using to automate the compilation - gradle, maven, etc. This is a solution independently of IDE (Eclipse, IntelliJ, etc).

Maven - pom.xml

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
                <compilerArgs>
                    <arg>-verbose</arg>
                    <arg>-parameters</arg> <!-- To keep parameter names-->
                    <arg>-Xlint:all,-options,-path</arg>
                </compilerArgs>
            </configuration>
        </plugin>

For more information about Pass Compiler Arguments Maven https://maven.apache.org/plugins/maven-compiler-plugin/examples/pass-compiler-arguments.html

build.gradle - Gradle

tasks.withType(JavaCompile) {
    options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-Xlint:-options" << "-parameters"
}

For more information about CompileOptions Gradle https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html

You can see a StackOverflow post on how to set compileOptions here How can I set the compileOptions for my Gradle Java plugin?

Austin Moothart
  • 378
  • 2
  • 13
Thiago Ferreira
  • 165
  • 2
  • 5
4

By default, compiled Java classes will use default names for their constructor parameters (arg0, arg1, etc.). However, we require the actual parameter names for serialisation purposes. You need to make Java compile with the actual parameter names.

In IntelliJ:

If running the nodes/tests via IntelliJ, you can do this by adding the following block to your .idea/compiler.xml file:

<component name="JavacSettings">
    <option name="ADDITIONAL_OPTIONS_STRING" value="-parameters" />
</component>

Or by going to IntelliJ IDEA > Preferences > Build, Execution, Deployment > Compiler > Java Compiler and adding -parameters to the Additional command line parameters: box.

To make IntelliJ pick up the change in the compiler settings, do Build > Rebuild Project.

From the command line:

If running the nodes/tests via the command line, you need to add the following snippet to the build.gradle file of each of your CorDapp's modules:

tasks.withType(JavaCompile) {
    options.compilerArgs << "-parameters" // Required for shell commands.
}

You can see an example here.

Joel
  • 22,762
  • 5
  • 26
  • 41