Spring cleaning : Migrating your CorDapp away from the deprecated Corda Jetty web server
We’re currently in the depths of a cold and dark winter. Can’t wait for Spring? Either can I so let’s get ready! This is a post to guide you through migrating your CorDapp legacy Jetty web server to a standalone, client-side Spring Boot server coupled with some foundational knowledge on the technologies at hand as well as why we all must make the move. If you don’t know what Corda is get cracking. Although Corda 3 includes a legacy node web server, it was originally created to jumpstart initial development by allowing you not to think about writing a web server giving a positive and familiar first experience. As of 2019 it continues to exist only for demo purposes and with an increasing number of production use-cases in the mix you should aim to create your own production-ready web server employing existing technologies.
I recently worked on Springifying some CorDapps so I’ll use the CorDapp example as a guideline implementation throughout the post. But first let’s explore the principal reasons for moving away from a node legacy web server.
Why move away from the legacy web server?
- Focus: R3 is made up of distributed ledger experts, not web server experts. A web server is neither a State, Contract or Flow and thus shifts away from the Corda design philosophy. R3 aims to focus 100% on building out Corda rather than reinventing the server wheel. Since we’ve built a JVM based platform, there’s a plethora of tried-and-tested server frameworks you can use, just choose your favourite.
- Integration: Corda was designed to be an application layer on top of existing business infrastructure promoting business value. Within a corporation it is likely to be rare that a user will interact directly with the node. The chances are they will speak to it indirectly through a myriad existing services and regardless of if it’s a web-server, application, microservice, message queue, kafka consumer, ETL processor etc. you can use the RPC client to communicate with the node to leverage its full capabilities.
- Features: Not only is Spring a widely adopted, community validated, enterprise grade solution that has stood the test of time but it has many additional compelling features. For one, Spring is mature, being developed as a lightweight add-on to the Spring framework nearly 20 years ago as a replacement to Java Enterprise stack and has been a JVM based solution running mission critical software since then. Furthermore, it is stable, the core modules of Spring Boot are shared across the Spring ecosystem, battle hardened by years of rigorous testing.
- Developer Flexibility: If Corda is web server agnostic it encourages firms to explore find the right technologies that might better suit business needs.
Corda is web server agnostic so we encourage firms to use technologies they know and trust to better suit their business needs.
Before we delve into technical detail here’s what an architectural view of a typical network of Corda nodes coupled with their matching remote web servers would look like.
Spring Framework
For this post I’ll walk through migrating to a detached, stand-alone, client-side Java Spring Boot Web Server. Spring is a popular Java application framework. Spring Boot is an evolution of it that aids the development by providing out-of-the-box, automatic configuration to get up and running quickly as an isolated, production-grade web server. Spring Boot does not comply with the JAX-RS standard (a Java EE specification for implementing Java based web services which is really a collection of interfaces and annotations), unlike Jetty. Spring Boot can be viewed as Spring’s own alternative to the standard. Below I leveraged the Spring MVC module to build out the web service.
Spring vs. Jetty Annotation
You will discover that there are multiple annotation differences between Jetty and Spring. Spring has not standardised to JAX-RS annotations, since its solution came before the JAX-RS specification, although plugins exist for adding compliance. Here’s a table of the transformations I used updating the sample, there’s certainly more you can learn about in the documentation
Migrating the IOU Example
To start here’s the src
directory layout in the sample’s new clients
module. Within we have the Spring application Server.kt
, the Controller.kt
holding the API and aNodeRPConnection.kt
class that authors the connection from the server to the node. The resources
directory is where any front end components of the projects can live, for example a UI or javascript module.
$ tree
.
├── build.gradle
└── src
├── main
├── kotlin
│ └── com
│ └── example
│ ├── Controller.kt
│ └── NodeRPCConnection.kt
│ └── Server.kt
└── resources
├── application.properties
│ └── index.html
└── public
└── index.html
└── js
└── angular-module.js
The gradle build configurations script build.gradle
manages your project dependencies, you’ll need to add these lines to your dependencies block to use the Spring Boot framework in your project.
compile("org.springframework.boot:spring-boot-starter-websocket:$spring_boot_version")
{
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
}compile "org.springframework.boot:spring-boot-starter-log4j2:$spring_boot_version"
The Server
Much like any other Spring Boot app we define a main entry point with a SpringApplication
instance. A@SpringBootApplication
annotation must be added to the class the SpringApplication
instance consumes, which in this case is Server
. Since Corda uses a Jackson object type mapping we need to define a Java Spring @Bean
to bind the Corda Jackson object-mapper to the HTTP message types used by Spring.
Connecting to the Node
To allow the server to interact with the Corda node a long-lasting connection via RPC needs to be established. We can produce this via a class that forms an RPC connection to the Corda node via CordaRPCConnection
and CordaRPCClient
, which are are both essentially wrappers for the Java RPCConnection
and RPCClient
classes respectively. When invoked it returns an RPCConnection
containing a proxy
that lets you invoke RPC operations on the node. Proxies are thread safe and ca be used with many RPC connections in parallel. The design below was previously implemented by an R3 Engineer.
Defining your API
Each API is contained within a Spring Boot Rest Controller, annotated by @RestController
which is a type of Spring @Component
. Here we map the methods over to a Controller.kt
class. It is important to include the appropriate annotations throughout so that the application recognises the its various features, as detailed above.
What about other APIs?
We’ve learned by now how building and operating a decentralised network demands more that clean code. It’s often likely the participants you collaborate with will be part of several Business Networks. As a Business Network Member it will be paramount to have access to membership information. To coordinate this you may even decide to connect to your Business Network Membership Service CorDapp through an API on your remote server, which could, for example, be defined in it’s own BNMController.kt
.
Starting your Server
To enable you becoming more effective at web server development it can often found it helpful to configure some gradle
tasks to quickly spin-up and down your servers, especially when you have many of them, like one corresponding to each Corda node. Here’s some example tasks for your clients
module build.gradle
file. You can run these via ./gradlew runPartyXServer
in separate terminals and interact with them as you would normal Spring servers. The running Spring server will also serve the static content within the resources
folder, you can navigate to localhost:<spring-server-port>
to view the front end application of the example.
Wrap up!
Despite using Spring web server throughout this post, it is just one option. You could use another Java web server, a command-line client, JavaFX, etc. I hope you’ve grasped an understanding of how you can configure and connect a web service to your Corda node and now live happier with the flexibility of joining services you have confidence in to your Corda node.
P.S. We’re hiring! If you want to be a part of making blockchain real, check out this post from R3’s head of Solutions Engineering!