November 06, 2020
This blog is to help Corda developers with some basic features of Gradle for developing CorDapps on the Corda DLT. If you’ve ever peeked through a Gradle script, all the cryptic entries may seem overwhelming at first — but it’s actually not so scary. This is an attempt to demystify some of what’s going on and help you confidently manage your CorDapps.
Note: This brief overview is focused on the most useful knowledge base for productive development. Gradle is a very robust system, so for more advanced topics, please check out the official documentation.
Maybe the best answer to this should come straight from the elephant’s mouth (Gradle’s website):
Gradle is an open-source build automation tool focused on flexibility and performance. Gradle build scripts are written using a Groovy or Kotlin DSL. Read about Gradle features to learn what is possible with Gradle.
Corda projects use Gradle scripts to streamline dependency management and build environments, regardless of the operating system, platform, or choice of editor.
When you clone an existing CorDapp project from a repository or create a new one (with a build.gradle script), all you need to build, package, and test your CorDapp will auto-magically download and link to your project during initial synchronization. 🥳
Let’s get started by looking at build.gradle scripts contained in a simple project template. The code snippets used here are from the cordapp-template-java repository.
. ├── LICENCE ├── README.md ├── TRADEMARK ├── build.gradle ⬅️ Spec for the entire project ├── clients │ ├── build.gradle ️️️⬅️ Spec for spring server │ └── src ├── config ├── constants.properties ├── contracts │ ├── build.gradle ⬅️ Spec for contracts │ └── src ├── gradle ├── gradle.properties ├── gradlew ├── gradlew.bat ├── repositories.gradle ├── settings.gradle ├── tree.txt └── workflows ├── build.gradle ⬅️ Spec for workflows └── src
Above you can see there are four build.gradle files. Don’t worry; it’s not your eyes going fuzzy — it’s standard to have one top-level specification and then an additional per-module script.
😎 Cool hint: Before Corda 4.0, many CorDapps would be developed in a single module structure and might only contain a single build.gradle . However, for all modern CorDapps (4.0+) it’s best practice to split your project into at least two modules; contracts including contract and state definitions, and workflows for your flows — so you will generally see at least threebuild.gradle files (root + contracts + workflows).
To understand how these scripts affect and manage the project, let’s take a look first at the root build.gradle, and then one of the module level scripts.
The buildscript block defines the dependencies for the build script process:
More information on Corda Gradle plugins is available at the official repository.
Remember how we have multiple modules in a Corda project, each with their own build.gradle? Well, if you have common settings and properties, you can define them here, and they will inject into all sub-modules, simplifying maintenance of your project.
Inside the allprojects block are:
Below the allprojects block we now have statements that apply to this specific root level. A question worth asking now — if all the project code, you’ve written are in submodules (contracts/workflows), and they have their own build.gradle scripts, then what do the following statements apply to? 🤔
In the case of our example, they will be used to build and configure the internal Cordform task deployNodes (we will go over this in the next block), which will be compiling and deploying your submodules to a local persistent test network.
From the snippet above:
Note:cordaCompile and cordaRuntime are Gradle configurations added by the cordformation plugin, which extend compile and runtime. They indicate dependencies that should not be included in the CorDapp JAR. These configurations prevent a dependency from being included twice (once in the CorDapp JAR/your project, and once in the Corda JARs/platform).
Finally, you can see a deployNodes task which is the configuration for local testing during CorDapp development. You can execute this task through your IDE (if it supports Gradle) or by running the command ./gradlew deployNodes from the terminal in your project directory. The task will compile your project, invoke a Network Bootstrapper, and provide you with a runnodes script to boot it all up after.
The network deployed is PERSISTENT. A folder ./build/nodes/NodeX is created for each node defined in the task definition, and vaults and settings will remain until the file structure is either deleted or over-written (usually by either a clean operation or re-executing deployNodes. You can shutdown or restart your nodes as you please.
The code above has two basic components:
That’s it for the root level build.gradle. Just to recap, the project level script defined plugins and build parameters. It then had a block where we could save time and apply properties to all the submodules in the project.
Next, we set up dependencies and declarations for a task in this script called deployNodes(). This task made use of some libraries and also used the TWO submodules contracts and workflows. Woot woot! 🙌
We’re now well on our way to becoming Gradle masters! The only thing left to discuss is how to configure and read a MODULE level build.gradle scripts. In many cases, there will be similarities — let’s start with the contract module. Then we will trace through the workflows, as it’s the ‘slightly’ more complicated case — but we can master it, don’t fret!
Let’s do all of the source at once since we are more familiar now with the different blocks.
Next, we have the workflows module, which is very similar to the contract script. It includes some specific additions related to testing or the execution of Corda FlowLogic.
❗️Important: Gradle doesn’t allow circular dependencies. In Corda design, flows will orchestrate usage of the contracts module, but rarely the other way *— you would NOT put project(‘:modules’) in your ./contracts/build.gradle, that would introduce a dependency cycle.
You will have noticed a lot of configuration in the workflows module revolved around integrationTest. These are optional and provided in the template to make things easy for developers. If you create your build.gradle from scratch you could omit this module if you intend to rely on deployNodes; additionally, you may also choose to merge your integrationTest classes and unit test classes in the same module — and again would avoid the additional scripting. Learn more about testing here.
In general, there are three primary methods to test your CorDapps in a local environment (of course there are more but these are most common).
Suppose you want to add an advanced tooling package such as confidential-identities , accounts , or tokenSDK to your project. You will need to add the dependencies accordingly to the relevant modules. Shown below is an example of additional dependencies. Full instructions on utilising the Accounts or TokenSDK libraries and required dependencies are available at docs.corda.net.
Now that you have your project set up the way you want, it’s time to think about running tasks or compiling or building, and generally making use of your project. Here’s how:
If you are on an IDE such as IntelliJ, which includes built-in Gradle support, there will be a tab on the right menu bar. You can execute tasks from the expandable menu.
Additionally, running through code blocks or default IDE operations can be set to go through Gradle without a run-configuration. To do this, set your Build/Run/Test operations for the project to Gradle — as shown in the screenshots below.
To utilize Gradle through the command line, the entry is ./gradlew from within your project directory. Here are some common commands:
./gradlew build — builds the project, including submodules and runs tests.
./gradlew clean — deletes build files
./gradlew bootJar — creates a JAR
./gradlew test— runs all tests. (Optional: — tests “<package.class>” will run a single test class).
./gradlew clean deployNodes — chains a clean command with a deployNodes task.
./gradlew tasks –all — lists all available tasks in the project.
./gradlew workflows:bootJar — prefixing a task with a module name will execute it ONLY relative to that module.
Above is just a sampling, check out the official Gradle user guide for more.
You’ve now acquired the knowledge needed to manage and work with both simple and complex Corda projects managed by Gradle. By taking a few minutes to work through this blog post, you have likely saved A LOT of time staring at build.gradle files in awe and wonder. When I first started with Corda the dependency management was one of the most confusing areas to learn.
However, after some simple guidance, Gradle becomes a joy to use. And who doesn’t love elephants? 🐘
If you would like to level up even more and get techniques and instruction on how to make your envisioned CorDapp project a reality. Your next stop should be to visit the free online Corda training.
Hope you’ll feel inspired to share this post with your friends and drop me a line sometime, I’d love to hear what you’re working on!
Want to learn more about building awesome blockchain applications on Corda? Be sure to visit corda.net, check out our community page to learn how to connect with other Corda developers, and sign up for one of our newsletters for the latest updates.
This article was written with input and ideas from Peter Li, a Developer Evangelist at R3. Follow him for even more great Corda content.
— Anthony Nixon is a Developer Evangelist at R3, an enterprise blockchain software firm working with a global ecosystem of more than 350 participants across multiple industries from both the private and public sectors to develop on Corda, its open-source blockchain platform, and Corda Enterprise, a commercial version of Corda for enterprise usage.
Share this post
December 02, 2020
November 30, 2020
November 26, 2020
Stay up to date on the latest news and articles related to Corda.