Upgrade to Corda OS 4.6 — The Database Migration
By: Neal Shah
Tags: Blockchain, Migration, Corda, Database, Development

Getting Started

Github

For ease, I’ve create a Github repository containing a start and end code base. I encourage you to follow along from the start, so that you can better understand the steps involved for the upgrade.

I have added sample CorDapp code from the IOU example and added client endpoint to run a loop which will create IOU states in both PartyA and PartyB nodes.

Clone the repository using the following command:

➜ git clone git@github.com:neal-shah/corda-4.6-upgrade.git

Checking dependency versions

Import the cordapp-4.4-start code into IntelliJ IDEA CE and allow Gradle to retrieve the required dependencies.

This is a good time to quickly review the constants.properties file in the root of the project:

cordaReleaseGroup=net.corda

cordaCoreReleaseGroup=net.corda

cordaVersion=4.4

cordaCoreVersion=4.4

gradlePluginsVersion=5.0.12

kotlinVersion=1.2.71

junitVersion=4.12

quasarVersion=0.7.10

log4jVersion=2.11.2

platformVersion=6

slf4jVersion=1.7.25

nettyVersion=4.1.22.Final

Lines 3–4 specify Corda OS version 4.4 and line 10 specifies platform version 6. Read more about Corda platform versions in the documentation.

Custom IOUSchema overview

Take a look at the custom schema that creates the IOU_States table in Corda 4.4:

object IOUSchema object IOUSchemaV1 : MappedSchema(

schemaFamily = IOUSchema.javaClass,

version = 1,

mappedTypes = listOf(PersistentIOU::class.java)) { override val migrationResource: String?

get() = "iou.changelog-master"; @Entity

@Table(name = "iou_states")

class PersistentIOU( @Column(name = "lender")

var lenderName: String, @Column(name = "borrower")

var borrowerName: String, @Column(name = "value")

var value: Int, @Column(name = "linear_id")

var linearId: UUID ) : PersistentState() {

constructor(): this("", "", 0, UUID.randomUUID())

}

}

This forms part of the app schema upgrade that you will see later on in this guide.

Deploying and running nodes

In your IntelliJ terminal, run the following command to deploy the Corda development nodes:

➜ ./gradlew deployNodes

You will see three Corda node directories under the ./build/nodes directory:

Notary

PartyA

PartyB

Open a system terminal window (for example, Terminal in MacOS or CMD in Windows), and navigate to the project ./build/nodes directory.

Execute the following command:

➜ ./runnodes

You should see three tabs created, each with one of the nodes starting up. Here’s an example:

Listening for transport dt_socket at address: 5005

Jolokia: Agent started with URL http://127.0.0.1:7005/jolokia/ ______ __

/ ____/ _________/ /___ _

/ / __ / ___/ __ / __ `/

/ /___ /_/ / / / /_/ / /_/ /

\____/ /_/ \__,_/\__,_/ --- Corda Open Source 4.4 (21e8c4f) -------------------------------------------------------------

Logs can be found in : /path/to/cordapp-4.4-start/build/nodes/Notary/logs

⚠️ ATTENTION: This node is running in development mode! 👩‍💻 This is not safe for production deployment.

Advertised P2P messaging addresses : localhost:10022

RPC connection address : localhost:10023

RPC admin connection address : localhost:10043

Loaded 2 CorDapp(s) : Contract CorDapp: Template Contracts version 1 by vendor Corda Open Source with licence Apache License, Version 2.0, Workflow CorDapp: Template Flows version 1 by vendor Corda Open Source with licence Apache License, Version 2.0

Node for "Notary" started up and registered in 23.36 sec

Running P2PMessaging loop

Welcome to the Corda interactive shell.

You can see the available commands by typing 'help'. Wed Nov 18 15:01:57 GMT 2020>>>

Seeding the nodes with data

In the source code of the clients , you will see a very simple GET request which executes a loop:

@GetMapping(value = ["/iou"], produces = ["text/plain"])

private fun startBatch(): String {

val otherParty = proxy.wellKnownPartyFromX500Name(CordaX500Name.parse("O=PartyB,L=New York,C=US"))

for (x in 0..50) {

val flow = proxy.startFlowDynamic(IOUFlow.Initiator::class.java, x, otherParty)

println("$x - ${flow.id} - Flow Complete.")

}

return "Complete"

}

To run the server, open the ./clients/build.gradle and run the task runTemplateServer . This will create a Spring Boot server for the PartyA node and successful RPC connection will look like this:

I 15:07:20 1 ServerKt.logStarted - Started ServerKt in 4.679 seconds (JVM running for 5.297)

I 15:07:37 53 [/].log - Initializing Spring FrameworkServlet 'dispatcherServlet'

I 15:07:37 53 DispatcherServlet.initServletBean - FrameworkServlet 'dispatcherServlet': initialization started

I 15:07:37 53 DispatcherServlet.initServletBean - FrameworkServlet 'dispatcherServlet': initialization completed in 16 ms

Next, open up a terminal window and run the following command:

The request will return a string: “Complete”

Shutdown the nodes by entering bye in each of the CRaSH shell windows.