Upgrading CorDapps to newer platform versions

These notes provide information on upgrading your CorDapps from previous versions. Corda 4 provides stability for public, non-experimental APIs that have been committed to. A list can be found in the API stability guarantees page.

This means that you can upgrade your node across versions without recompiling or adjusting your CorDapps. You just have to upgrade your node and restart.

However, there are usually new features and other opt-in changes that may improve the security, performance or usability of your application that are worth considering for any actively maintained software.

Corda releasePlatform version
4.12140
4.1113
4.1012
4.911
4.810
4.79
4.68
4.57
4.46
4.35
4.24
4.14
4.04
3.33

Platform version 140 which represents Corda 4.12 is a major platform upgrade. In this version, Corda has been upgraded to run on Java 17 and to use Kotlin 1.9.20. This also means that you must recompile Corda 4.12 CorDapps with Java 17 and Kotlin 1.9.20. Once recompiled and fully tested, you must sign CorDapps with the same key used to sign the 4.11 CorDapps.

Additionally, if a CorDapp has been updated to platform version 140, you must upgrade Corda nodes to Corda 4.12. For instructions on how to upgrade Corda nodes, see Corda Open Source Edition 4.11 to 4.12 upgrade guide.

No manual upgrade steps are required.

The operational improvements around database schema harmonisation that we have made in Corda 4.6 require a number of manual steps when upgrading to Corda 4.6 from a previous version. For more information, see the Corda Open Source 4.6 release notes available in the archived-docs directory of the corda/corda-docs-portal repo. The required steps for each upgrade path are described below.

  1. Remove any entries of transactionIsolationLevel, initialiseSchema, or initialiseAppSchema from the database section of your node configuration file.
  2. Update any missing core schema changes by running the node in run-migration-scripts mode: java -jar corda.jar run-migration-scripts --core-schemas.
  3. Add Liquibase resources to CorDapps. In Corda 4.6, CorDapps that introduce custom schema need Liquibase migration scripts allowing them to create the schema upfront. For existing CorDapps that do not have migration scripts in their resources, they can be added as an external migration JAR file, as documented in the Corda Enterprise 4.6 database management scripts documentation (available in the archived-docs directory of the corda/corda-docs-portal repo).
  4. Update the changelog for existing schemas. After upgrading the Corda JAR file and adding Liquibase scripts to the CorDapp(s), any custom schemas from the apps are present in the database, but the changelog entries in the Liquibase changelog table are missing (as they have been created by Liquibase). This will cause issues when starting the node, and also when running run-migration-scripts as tables that already exist cannot be recreated. By running the new sub-command sync-app-schemas, changelog entries are created for all existing mapped schemas from CorDapps: java -jar corda.jar sync-app-schemas.

Corda 4.6 drops the support for retro-fitting the database changelog when migrating from Corda versions older than 4.0. Thus it is required to migrate to a previous 4.x version before migrating to Corda 4.6 - for example, 3.3 to 4.5, and then 4.5 to 4.6.

To successfully build a CorDapp against Platform Version 8 and Corda 4.6, you need to use version 5.1.1 of the Corda Gradle Plugins:

ext.corda_gradle_plugins_version = '5.1.1'

No manual upgrade steps are required.

This section provides instructions for upgrading your CorDapps from previous versions to take advantage of features and enhancements introduced in platform version 5.

The following code, which compiled in Platform Version 4, will not compile in Platform Version 5:

data class Obligation(val amount: Amount<Currency>, val lender: AbstractParty, val borrower: AbstractParty)

val (lenderId, borrowerId) = if (anonymous) {
    val anonymousIdentitiesResult = subFlow(SwapIdentitiesFlow(lenderSession))
    Pair(anonymousIdentitiesResult[lenderSession.counterparty]!!, anonymousIdentitiesResult[ourIdentity]!!)
} else {
    Pair(lender, ourIdentity)
}

val obligation = Obligation(100.dollars, lenderId, borrowerId)

Compiling this code against Platform Version 5 will result in the following error:

Type mismatch: inferred type is Any but AbstractParty was expected

The issue here is that a new Destination interface introduced in Platform Version 5 can cause type inference failures when a variable is used as an AbstractParty but has an actual value that is one of Party or AnonymousParty. These subclasses implement Destination, while the superclass does not. Kotlin must pick a type for the variable, and so chooses the most specific ancestor of both AbstractParty and Destination. This is Any, which is not a valid type for use as an AbstractParty later. For more information on Destination, see the KDocs for the interface here.

Note that this is a Kotlin-specific issue. Java can instead choose ? extends AbstractParty & Destination here, which can later be used as AbstractParty.

To fix this, an explicit type hint must be provided to the compiler:

data class Obligation(val amount: Amount<Currency>, val lender: AbstractParty, val borrower: AbstractParty)

val (lenderId, borrowerId) = if (anonymous) {
    val anonymousIdentitiesResult = subFlow(SwapIdentitiesFlow(lenderSession))
    Pair(anonymousIdentitiesResult[lenderSession.counterparty]!!, anonymousIdentitiesResult[ourIdentity]!!)
} else {
    // This Pair now provides a type hint to the compiler
    Pair<AbstractParty, AbstractParty>(lender, ourIdentity)
}

val obligation = Obligation(100.dollars, lenderId, borrowerId)

This stops type inference from occurring and forces the variable to be of type AbstractParty.

Platform Version 5 requires Gradle 5.4 to build. If you use the Gradle wrapper, you can upgrade by running:

./gradlew wrapper --gradle-version 5.4.1

Otherwise, upgrade your installed copy in the usual manner for your operating system.

Additionally, you’ll need to add https://repo.gradle.org/gradle/libs-releases as a repository to your project, in order to pick up the gradle-api-tooling dependency. You can do this by adding the following to the repositories in your Gradle file:

maven { url 'https://repo.gradle.org/gradle/libs-releases' }

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.