Updates CorDapp template docs to reflect inclusion of java source files and new info on running nodes across machines. (#52)

Updates CorDapp template docs to reflect inclusion of java source files.
This commit is contained in:
Joel Dudley 2016-12-12 18:48:35 +00:00 committed by GitHub
parent a4201c7152
commit 7d79f3d6d2

View File

@ -22,6 +22,25 @@ We recommend you read the non-technical white paper and technical white paper be
intended design from beginning to end. It is the kind of document that you should read, or at least, read parts of. Note
that because the technical white paper describes the intended end state, it does not always align with the implementation.
Background
----------
The Example CorDapp implements a basic scenario where a buyer wishes to submit purchase orders to a seller. The scenario
defines four nodes:
* **Controller** which hosts the network map service and validating notary service.
* **NodeA** who is the buyer.
* **NodeB** who is the seller.
* **NodeC** an unrelated third party.
NodeA can generate purchase orders for lists and quantities of items and associated metadata such as delivery address
and delivery date. The flows used to facilitate the agreement process always results in an agreement with the seller as
long as the purchase order meets the contract constraints which are defined in ``PurchaseOrderContract.kt``.
All agreed purchase orders between NodeA and NodeB become "shared facts" between NodeA and NodeB. But note that NodeC
won't see any of these transactions or have copies of any of the resulting ``PurchaseOrderState`` objects. This is
because data is only propagated on a need-to-know basis.
Getting started
---------------
@ -201,14 +220,14 @@ Next, IntelliJ will show a bunch of pop-up windows. One of which requires our at
.. image:: resources/unlinked-gradle-project.png
:width: 400
Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now begin obtianing all the
Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now obtain all the
project dependencies and perform some indexing. It usually takes a minute or so. If you miss the 'import gradle project'
dialogue, simply close and re-open IntelliJ again to see it again.
**Alternative approach**
Alternatively, one can instruct IntelliJ to create a new project through cloning a repository. From the IntelliJ welcome
dialogue (shown above), opt to 'check out from version control', then select git and enter the git url for the CorDpp tempalte
dialogue (shown above), opt to 'check out from version control', then select git and enter the git URL for the CorDapp template
(https://github.com/corda/cordapp-template). You'll then need to import the Gradle project when prompted, as explained above.
**If you already have IntelliJ open**
@ -245,9 +264,13 @@ Unix/Mac OSX: ``./gradlew deployNodes``
Windows: ``gradlew.bat deployNodes``
Building straight away will build the example CorDapp defined the the CorDapp template source. For more information on the example
CorDapp see "The Example CorDapp" section below. Gradle will then grab all the dependencies for you and build the
example CorDapp.
This build process will build the example CorDapp defined in the CorDapp template source. CorDapps can be written in
any language targeting the JVM. In our case, we've provided the template source in both Kotlin (``/kotlin/src``) and
Java (``/java/src``) Since both sets of source files are functionally identical, we will refer to the Kotlin build
throughout the documentation.
For more information on the example CorDapp see "The Example CorDapp" section below. Gradle will then grab all the
dependencies for you and build the example CorDapp.
The ``deployNodes`` Gradle task allows you easily create a formation of Corda nodes. In the case of the example CorDapp
we are creating ``four`` nodes.
@ -294,11 +317,11 @@ Open the Gradle window by selecting ``View > Tool windows > Gradle`` from the ma
open on the right hand side of the IDE. Expand `tasks` and then expand `other`. Double click on `deployNodes`. Gradle will
start the build process and output progress to a console window in the IDE.
Running the Sample CorDapp
==========================
Running the CorDapp template
============================
Running the Sample CorDapp from the command line
------------------------------------------------
Running the CorDapp template from the command line
--------------------------------------------------
To run the sample CorDapp navigate to the ``kotlin/build/nodes`` folder and execute the ``runnodes`` shell script with:
@ -320,7 +343,7 @@ message and some pertinent config information, see below:
--- DEVELOPER SNAPSHOT ------------------------------------------------------------
Logs can be found in : /Users/rogerwillis/Documents/Corda/cordapp-template/kotlin/build/nodes/nodea/logs
Database connection url is : jdbc:h2:tcp://10.18.0.196:50661/node
Database connection URL is : jdbc:h2:tcp://10.18.0.196:50661/node
Node listening on address : localhost:10004
Loaded plugins : com.example.plugin.ExamplePlugin
Embedded web server is listening on : http://10.18.0.196:10005/
@ -405,30 +428,11 @@ To stop the nodes, press the red "stop" button at the top right-hand side of the
The node driver can also be used to as a basis for `debugging your CorDapp`_
Using the sample CorDapp
========================
Interacting with the CorDapp template
=====================================
Background
----------
The Example CorDapp implements a basic scenario where a buyer wishes to submit purchase orders to a seller. The scenario
defines four nodes:
* **Controller** which hosts the network map service and validating notary service.
* **NodeA** who is the buyer.
* **NodeB** who is the seller.
* **NodeC** an unrelated third party.
NodeA can generate purchase orders for lists and quantities of items and associated metadata such as delivery address
and delivery date. The flows used to facilitate the agreement process always results in an agreement with the seller as
long as the purchase order meets the contract constraints which are defined in ``PurchaseOrderContract.kt``.
All agreed purchase orders between NodeA and NodeB become "shared facts" between NodeA and NodeB. But note that NodeC
won't see any of these transactions or have copies of any of the resulting ``PurchaseOrderState`` objects. This is
because data is only propagated on a need-to-know basis.
Interfaces
----------
Via HTTP
--------
The CorDapp defines a few HTTP API end-points and also serves some static web content. The end-points allow you to
list purchase orders and add purchase orders.
@ -465,7 +469,7 @@ To create a purchase order from NodeA to NodeB, use:
.. sourcecode:: bash
echo '{"orderNumber": "1","deliveryDate": "2018-09-15","deliveryAddress": {"city": "London","country": "UK"},"items" : [{"name": "widget","amount": "3"},{"name": "thing","amount": "4"}]}' | curl -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-purchase-order
echo '{"orderNumber": "1","deliveryDate": "2018-09-15","deliveryAddress": {"city": "London","country": "UK"},"items" : [{"name": "widget","amount": "3"},{"name": "thing","amount": "4"}]}' | cURL -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-purchase-order
Note the port number ``10005`` (NodeA) and NodeB referenced in the API end-point path. This command instructs NodeA to
create and send a purchase order to NodeB. Upon verification and completion of the process, both nodes (but not NodeC) will
@ -550,7 +554,8 @@ navigate to http://localhost:10007/api/example/purchase-orders.
Navigate to http://localhost:10005/web/example the refresh button in the top left-hand side of the page. You should
see the newly created agreement on the page.
**Accessing the h2 database via h2 web console:**
Using the h2 web console
------------------------
You can connect to the h2 database to see the current state of the ledger, among other data such as the current state of
the network map cache. Firstly, navigate to the folder where you downloaded the h2 web console as part of the pre-requisites
@ -572,13 +577,14 @@ The h2 web console should start up in a web browser tab. To connect we first nee
node outputs its connection string in the terminal window as it starts up. In a terminal window where a node is running,
look for the following string:
``Database connection url is : jdbc:h2:tcp://10.18.0.150:56736/node``
``Database connection URL is : jdbc:h2:tcp://10.18.0.150:56736/node``
you can use the string on the right to connect to the h2 database: just paste it in to the JDBC URL field and click Connect.
You will be presented with a web application that enumerates all the available tables and provides an interface for you to
query them using SQL.
**Using the Example RPC client:**
Using the Example RPC client
----------------------------
The ``/src/main/kotlin/com/example/client/ExampleClientRPC.kt`` file is a simple utility which uses the client RPC library
to connect to a node and log the 'placed' purchase orders. It will log any existing purchase orders and listen for any future
@ -606,6 +612,9 @@ application see:
* :doc:`Client RPC documentation <clientrpc>`
* :doc:`Client RPC tutorial <tutorial-clientrpc-api>`
Extending the CorDapp template
==============================
CorDapp-template Project Structure
----------------------------------
@ -627,48 +636,90 @@ The CorDapp template has the following directory structure:
├── lib
│   ├── ...
├── settings.gradle
└── src
├── main
   │   ├── java
   │   ├── kotlin
   │   │   └── com
   │   │   └── example
   │   │   ├── Main.kt
   │   │   ├── api
   │   │   │   └── ExampleApi.kt
   │   │   ├── client
   │   │   │   └── ExampleClientRPC.kt
   │   │   ├── contract
   │   │   │   ├── PurchaseOrderContract.kt
   │   │   │   └── PurchaseOrderState.kt
   │   │   ├── model
   │   │   │   └── PurchaseOrder.kt
   │   │   ├── plugin
   │   │   │   └── ExamplePlugin.kt
   │   │   └── flow
   │   │   └── ExampleFlow.kt
   │   │   └── service
   │   │   └── ExampleService.kt
│   ├── python
│   └── resources
│   ├── META-INF
│   │   └── services
│   │   └── net.corda.core.node.CordaPluginRegistry
│   ├── certificates
│   │   ├── readme.txt
│   │   ├── sslkeystore.jks
│   │   └── truststore.jks
│   └── exampleWeb
│   ├── index.html
│   └── js
│   └── example.js
└── test
├── java
├── kotlin
│   └── com
│   └── example
│   └── ExampleTest.kt
   └── resources
├── kotlin
│ └── src
│ ├── main
   │   ├── kotlin
   │   │   └── com
   │   │   └── example
   │   │   ├── Main.kt
   │   │   ├── api
   │   │   │   └── ExampleApi.kt
   │   │   ├── client
   │   │   │   └── ExampleClientRPC.kt
   │   │   ├── contract
   │   │   │   ├── PurchaseOrderContract.kt
   │   │   │   └── PurchaseOrderState.kt
   │   │   ├── model
   │   │   │   └── PurchaseOrder.kt
   │   │   ├── plugin
   │   │   │   └── ExamplePlugin.kt
   │   │   └── flow
   │   │   └── ExampleFlow.kt
   │   │   └── service
   │   │   └── ExampleService.kt
│ │   ├── python
│ │   └── resources
│ │   ├── META-INF
│ │   │   └── services
│ │   │   └── net.corda.core.node.CordaPluginRegistry
│ │   ├── certificates
│ │   │   ├── readme.txt
│ │   │   ├── sslkeystore.jks
│ │   │   └── truststore.jks
│ │   └── exampleWeb
│ │   ├── index.html
│ │   └── js
│ │   └── example.js
│ └── test
│ ├── java
│ ├── kotlin
│ │   └── com
│ │   └── example
│ │   └── ExampleTest.kt
   └── resources
└── java
└── src
├── main
   │   ├── java
   │   │   └── com
   │   │   └── example
   │   │   ├── Main.java
   │   │   ├── api
   │   │   │   └── ExampleApi.java
   │   │   ├── client
   │   │   │   └── ExampleClientRPC.java
   │   │   ├── contract
   │   │   │   ├── PurchaseOrderContract.java
   │   │   │   └── PurchaseOrderState.java
   │   │   ├── model
   │   │   │   └── PurchaseOrder.java
   │   │   ├── plugin
   │   │   │   └── ExamplePlugin.java
   │   │   └── flow
   │   │   └── ExampleFlow.java
   │   │   └── service
   │   │   └── ExampleService.java
│   ├── python
│   └── resources
│   ├── META-INF
│   │   └── services
│   │   └── net.corda.core.node.CordaPluginRegistry
│   ├── certificates
│   │   ├── readme.txt
│   │   ├── sslkeystore.jks
│   │   └── truststore.jks
│   └── exampleWeb
│   ├── index.html
│   └── js
│   └── example.js
└── test
├── java
├── kotlin
│   └── com
│   └── example
│   └── ExampleTest.kt
   └── resources
In the file structure above, the most important files and directories to note are:
@ -677,15 +728,18 @@ In the file structure above, the most important files and directories to note ar
* **gradle** contains the gradle wrapper, which allows the use of Gradle without installing it yourself and worrying
about which version is required.
* **lib** contains the Quasar.jar which is required for runtime instrumentation of classes by Quasar.
* **src/main/kotlin** contains the source code for the example CorDapp.
* **src/main/python** contains a python script which accesses nodes via RPC.
* **src/main/resources** contains the certificate store, some static web content to be served by the nodes and the
PluginServiceRegistry file.
* **src/test/kotlin** contains unit tests for protocols, contracts, etc.
* **kotlin** contains the source code for the example CorDapp written in Kotlin.
* **kotlin/src/main/kotlin** contains the source code for the example CorDapp.
* **kotlin/src/main/python** contains a python script which accesses nodes via RPC.
* **kotlin/src/main/resources** contains the certificate store, some static web content to be served by the nodes and the
PluginServiceRegistry file.
* **kotlin/src/test/kotlin** contains unit tests for protocols, contracts, etc.
* **java** contains the same source code, but written in java. This is an aid for users who do not want to develop in
Kotlin, and serves as an example of how CorDapps can be developed in any language targeting the JVM.
Some elements are covered in more detail below.
The build.gradle File
The build.gradle file
---------------------
It is usually necessary to make a couple of changes to the ``build.gradle`` file. Here will cover the most pertinent bits.
@ -813,6 +867,39 @@ Unix/Mac OSX: ``./gradlew deployNodes``
Windows: ``gradlew.bat deployNodes``
Running Nodes Across Machines
-----------------------------
The nodes can also be set up to communicate between separate machines on the
same subnet.
After deploying the nodes, navigate to the build folder (`kotlin/build/
nodes` or `java/build/nodes`) and move some of the individual node folders to
separate machines on the same subnet (e.g. using a USB key). It is important
that no nodes - including the controller node - end up on more than one
machine. Each computer should also have a copy of `runnodes` and
`runnodes.bat`.
For example, you may end up with the following layout:
* Machine 1: `controller`, `nodea`, `runnodes`, `runnodes.bat`
* Machine 2: `nodeb`, `nodec`, `runnodes`, `runnodes.bat`
You must now edit the configuration file for each node, including the
controller. Open each node's config file (`[nodeName]/node.conf`), and make
the following changes:
* Change the artemis address to the machine's ip address (e.g.
`artemisAddress="10.18.0.166:10006"`)
* Change the network map address to the ip address of the machine where the
controller node is running (e.g. `networkMapAddress="10.18.0.166:10002"`)
(please note that the controller will not have a network map address)
Each machine should now run its nodes using `runnodes` or `runnodes.bat`
files. Once they are up and running, the nodes should be able to place
purchase orders among themselves in the same way as when they were running on
the same machine.
Debugging your CorDapp
----------------------