Added corda and cordaRuntime configurations and documentation on integrating with Corda (#1103)

* Added new corda and cordaRuntime configurations for cordapps to be able to explicitly depend on Corda and exclude corda dependencies from the fatjar

* Added corda integration section to docsite to describe how to integrate with Corda.

* Updated more of the documentation to reflect the new method of specifying core corda dependencies.

* Reorganised document logic to move all build system related documentation to the cordapp build systems page.

* Renamed cordapp build systems doc to match actual purpose.

* Improved the warning for building against a net.corda dependency in a cordapp

* Added a line of dialogue to show further reading for those reading about writing cordapps.
This commit is contained in:
Clinton 2017-07-25 17:54:36 +01:00 committed by GitHub
parent 2e480f8420
commit 68d05eee04
13 changed files with 194 additions and 99 deletions

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=0.13.3
gradlePluginsVersion=0.13.4
kotlinVersion=1.1.1
guavaVersion=21.0
bouncycastleVersion=1.57

View File

@ -6,6 +6,7 @@ Building a CorDapp
cordapp-overview
writing-cordapps
cordapp-build-systems
api-index
flow-cookbook
cheat-sheet

View File

@ -50,6 +50,13 @@ UNRELEASED
* Kotlin utilities that we deemed useful enough to keep public have been moved out of ``net.corda.core.Utils`` and into
``net.corda.core.utilities.KotlinUtils``. The other utilities have been marked as internal.
* Changes to ``Cordformation``/ cordapp building:
* ``Cordformation`` modifies the JAR task to make cordapps build as semi fat JARs containing all dependencies
except other cordapps and Corda core dependencies.
* ``Cordformation`` adds a ``corda`` and ``cordaRuntime`` configuration to projects which cordapp developers should
use to exclude core Corda JARs from being built into Cordapp fat JARs.
Milestone 13
------------

View File

@ -0,0 +1,116 @@
Cordapp Build Systems
=====================
Cordapps run on the Corda platform and integrate with it and each other. To learn more about the basics of a Cordapp
please read :doc:`cordapp-overview`. To learn about writing a Cordapp as a developer please read :doc:`writing-cordapps`.
This article will specifically deal with how to build cordapps, specifically with Gradle.
Cordapp JAR Format
------------------
The first step to integrating a Cordapp with Corda is to ensure it is in the correct format. The correct format of a JAR
is a semi-fat JAR that contains all of its own dependencies *except* the Corda core libraries and other Cordapps.
For example if your Cordapp depends on ``corda-core``, ``your-other-cordapp`` and ``apache-commons`` then the Cordapp
JAR will contain all classes and resources from the ``apache-commons`` JAR and its dependencies and *nothing* from the
other two JARs.
.. note:: The rest of this tutorial assumes you are using ``gradle``, the ``cordformation`` plugin and have forked from
one of our cordapp templates.
The ``jar`` task included by default in the cordapp templates will automatically build your JAR in this format as long
as your dependencies are correctly set.
Building against Corda
----------------------
To build against Corda you must do the following to your ``build.gradle``;
* Add the ``net.corda:corda:<version>`` JAR as a ``cordaRuntime`` dependency.
* Add each compile dependency (eg ``corda-core``) as a ``corda`` dependency.
To make use of the Corda test facilities you must;
* Add ``net.corda:corda-test-utils:<version>`` as a ``testCompile`` dependency (eg; a default Java/Kotlin compile task).
.. warning:: Never include ``corda-test-utils`` as a ``compile`` or ``corda`` dependency.
These configurations work by the ``cordformation`` plugin adding ``corda`` as a new configuration that ``compile``
extends from, and ``cordaRuntime`` which ``runtime`` extends from.
Choosing your Corda version
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following two lines of the ``build.gradle`` file define the Corda version used to build your CorDapp:
.. sourcecode:: groovy
ext.corda_release_version = '0.13.0'
ext.corda_gradle_plugins_version = '0.13.3'
In this case, our CorDapp will use the Milestone 13 release of Corda, and version 13.3 of the Corda gradle plugins. You
can find the latest published version of both here: https://bintray.com/r3/corda.
``corda_gradle_plugins_versions`` are given in the form ``major.minor.patch``. You should use the same ``major`` and
``minor`` versions as the Corda version you are using, and the latest ``patch`` version. A list of all the available
versions can be found here: https://bintray.com/r3/corda/cordformation.
In certain cases, you may also wish to build against the unstable Master branch. See :doc:`building-against-master`.
Building against Cordapps
-------------------------
To build against a Cordapp you must add it as a ``cordapp`` dependency to your ``build.gradle``.
Other Dependencies
------------------
If your CorDapps have any additional external dependencies, they can be specified like normal Kotlin/Java dependencies
in Gradle. See the example below, specifically the ``apache-commons`` include.
For further information about managing dependencies, see
`the Gradle docs <https://docs.gradle.org/current/userguide/dependency_management.html>`_.
Installing CorDapps
-------------------
At runtime, nodes will load any plugins present in their ``plugins`` folder. Therefore in order to install a cordapp to
a node the cordapp JAR must be added to the ``<node_dir>/plugins/`` folder, where ``node_dir`` is the folder in which the
node's JAR and configuration files are stored).
The ``deployNodes`` gradle task, if correctly configured, will automatically place your cordapp JAR as well as any
dependent cordapp JARs specified into the directory automatically.
Example
-------
The following is a sample of what a gradle dependencies block for a cordapp could look like. The cordapp template
is already correctly configured and this is for reference only;
.. container:: codeset
.. sourcecode:: groovy
dependencies {
// Corda integration dependencies
corda "net.corda:corda-core:$corda_release_version"
corda "net.corda:corda-finance:$corda_release_version"
corda "net.corda:corda-jackson:$corda_release_version"
corda "net.corda:corda-rpc:$corda_release_version"
corda "net.corda:corda-node-api:$corda_release_version"
corda "net.corda:corda-webserver-impl:$corda_release_version"
cordaRuntime "net.corda:corda:$corda_release_version"
cordaRuntime "net.corda:corda-webserver:$corda_release_version"
testCompile "net.corda:corda-test-utils:$corda_release_version"
// Corda Plugins: dependent flows and services
cordapp "net.corda:bank-of-corda-demo:1.0"
// Some other dependencies
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "junit:junit:$junit_version"
compile "org.apache.commons:commons-lang3:3.6"
}

View File

@ -605,4 +605,4 @@ Debugging is done via IntelliJ as follows:
4. Edit the “Debug CorDapp” run configuration with the port of the node you wish to connect to
5. Run the “Debug CorDapp” run configuration
6. Set your breakpoints and start using your node. When your node hits a breakpoint, execution will pause
6. Set your breakpoints and start using your node. When your node hits a breakpoint, execution will pause

View File

@ -60,51 +60,6 @@ The ``src`` directory of the Template CorDapp, where we define our CorDapp's sou
└── contract
└── TemplateTests.java
The build file
--------------
At the root of the Template CorDapp, you will also find a ``build.gradle`` file. This file is useful for several
reasons:
Choosing your CorDapp version
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following two lines of the ``build.gradle`` file define the Corda version used to build your CorDapp:
.. sourcecode:: groovy
ext.corda_release_version = '0.13.0'
ext.corda_gradle_plugins_version = '0.13.3'
In this case, our CorDapp will use the Milestone 13 release of Corda, and version 13.3 of the Corda gradle plugins. You
can find the latest published version of both here: https://bintray.com/r3/corda.
``corda_gradle_plugins_versions`` are given in the form ``major.minor.patch``. You should use the same ``major`` and
``minor`` versions as the Corda version you are using, and the latest ``patch`` version. A list of all the available
versions can be found here: https://bintray.com/r3/corda/cordformation.
In certain cases, you may also wish to build against the unstable Master branch. See :doc:`building-against-master`.
Project dependencies
^^^^^^^^^^^^^^^^^^^^
If your CorDapps have any additional external dependencies, they should be added to the ``dependencies`` section:
.. sourcecode:: groovy
dependencies {
...
// Cordapp dependencies
// Specify your cordapp's dependencies below, including dependent cordapps
}
For further information about managing dependencies, see
`the Gradle docs <https://docs.gradle.org/current/userguide/dependency_management.html>`_.
Build tasks
^^^^^^^^^^^
The build file also defines a number of build tasks that will allow us to package up our plugin. We will discuss these
later.
Defining plugins
----------------
Your CorDapp may need to define two types of plugins:
@ -138,3 +93,6 @@ The ``WebServerPluginRegistry`` class defines the following:
started
* The static web content itself should be placed inside the ``src/main/resources`` directory
To learn about how to use gradle to build your cordapp against Corda and generate an artifact please read
:doc:`cordapp-build-systems`.

View File

@ -10,13 +10,22 @@ import org.gradle.api.artifacts.Configuration
*/
class Cordformation implements Plugin<Project> {
void apply(Project project) {
Configuration cordappConf = project.configurations.create("cordapp")
cordappConf.transitive = false
project.configurations.compile.extendsFrom cordappConf
createCompileConfiguration("cordapp", project)
createCompileConfiguration("corda", project)
Configuration configuration = project.configurations.create("cordaRuntime")
configuration.transitive = false
project.configurations.runtime.extendsFrom configuration
configureCordappJar(project)
}
private void createCompileConfiguration(String name, Project project) {
Configuration configuration = project.configurations.create(name)
configuration.transitive = false
project.configurations.compile.extendsFrom configuration
}
/**
* Configures this project's JAR as a Cordapp JAR
*/
@ -47,26 +56,30 @@ class Cordformation implements Plugin<Project> {
}, filePathInJar).asFile()
}
private static def getDirectNonCordaDependencies(Project project) {
def coreCordaNames = ['jfx', 'mock', 'rpc', 'core', 'corda', 'cordform-common', 'corda-webserver', 'finance', 'node', 'node-api', 'node-schemas', 'test-utils', 'jackson', 'verifier', 'webserver', 'capsule', 'webcapsule']
def excludes = coreCordaNames.collect { [group: 'net.corda', name: it] } + [
private static Set<File> getDirectNonCordaDependencies(Project project) {
def excludes = [
[group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib'],
[group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jre8'],
[group: 'co.paralleluniverse', name: 'quasar-core']
]
// The direct dependencies of this project
def cordappDeps = project.configurations.cordapp.allDependencies
def directDeps = project.configurations.runtime.allDependencies - cordappDeps
// We want to filter out anything Corda related or provided by Corda, like kotlin-stdlib and quasar
def filteredDeps = directDeps.findAll { excludes.collect { exclude -> (exclude.group == it.group) && (exclude.name == it.name) }.findAll { it }.isEmpty() }
filteredDeps.each {
// net.corda may be a core dependency which shouldn't be included in this cordapp so give a warning
if(it.group.contains('net.corda')) {
project.logger.warn("Including a dependency with a net.corda group: $it")
} else {
project.logger.trace("Including dependency: $it")
project.with {
// The direct dependencies of this project
def excludeDeps = configurations.cordapp.allDependencies + configurations.corda.allDependencies + configurations.cordaRuntime.allDependencies
def directDeps = configurations.runtime.allDependencies - excludeDeps
// We want to filter out anything Corda related or provided by Corda, like kotlin-stdlib and quasar
def filteredDeps = directDeps.findAll { excludes.collect { exclude -> (exclude.group == it.group) && (exclude.name == it.name) }.findAll { it }.isEmpty() }
filteredDeps.each {
// net.corda may be a core dependency which shouldn't be included in this cordapp so give a warning
if(it.group.contains('net.corda')) {
logger.warn("You appear to have included a Corda platform component ($it) using a 'compile' or 'runtime' dependency." +
"This can cause node stability problems. Please use 'corda' instead." +
"See http://docs.corda.net/cordapp-build-systems.html")
} else {
logger.trace("Including dependency: $it")
}
}
return filteredDeps.collect { configurations.runtime.files it }.flatten().toSet()
}
return filteredDeps.collect { project.configurations.runtime.files it }.flatten().toSet()
}
}

View File

@ -26,11 +26,11 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':webserver')
compile project(':test-utils')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':webserver')
corda project(':test-utils')
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {

View File

@ -26,14 +26,14 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':client:jfx')
compile project(':client:rpc')
compile project(':finance')
compile project(':webserver')
compile project(':test-utils')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':client:jfx')
corda project(':client:rpc')
corda project(':finance')
corda project(':webserver')
corda project(':test-utils')
// Javax is required for webapis
compile "org.glassfish.jersey.core:jersey-server:${jersey_version}"

View File

@ -28,11 +28,11 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':finance')
compile project(':webserver')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':finance')
corda project(':webserver')
// Javax is required for webapis
compile "org.glassfish.jersey.core:jersey-server:${jersey_version}"

View File

@ -18,13 +18,13 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':client:jfx')
compile project(':client:rpc')
compile project(':test-utils')
compile project(':cordform-common')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':client:jfx')
corda project(':client:rpc')
corda project(':test-utils')
corda project(':cordform-common')
}
idea {

View File

@ -29,11 +29,11 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':webserver')
compile project(':finance')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':webserver')
corda project(':finance')
// Cordapp dependencies
// Specify your cordapp's dependencies below, including dependent cordapps

View File

@ -25,10 +25,10 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
// Corda integration dependencies
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':finance')
corda project(path: ":node:capsule", configuration: 'runtimeArtifacts')
corda project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
corda project(':core')
corda project(':finance')
// Corda Plugins: dependent flows and services
cordapp project(':samples:bank-of-corda-demo')