Updates tutorials (general fixes, link to solutions repos)

* Updates tutorial to make imports to be added clearer, and to reflect new repo structure.
* Adds links to the solution repos for tut 1.
* Further fixes based on dry-run.
This commit is contained in:
Joel Dudley 2017-12-13 16:22:40 +00:00 committed by GitHub
parent d1ea881aef
commit 929341e7ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 102 additions and 62 deletions

View File

@ -33,6 +33,7 @@ dependencies {
compile project(':core') compile project(':core')
compile project(':client:jfx') compile project(':client:jfx')
compile project(':node-driver') compile project(':node-driver')
compile project(':webserver')
testCompile project(':verifier') testCompile project(':verifier')
testCompile project(':test-utils') testCompile project(':test-utils')

View File

@ -1,4 +1,4 @@
package net.corda.docs.java.tutorial.helloworld; package com.template;
import net.corda.core.contracts.CommandData; import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract; import net.corda.core.contracts.Contract;

View File

@ -1,17 +1,21 @@
package net.corda.docs.java.tutorial.helloworld; package net.corda.docs.java.tutorial.helloworld;
// DOCSTART 01
import co.paralleluniverse.fibers.Suspendable; import co.paralleluniverse.fibers.Suspendable;
import com.template.TemplateContract;
import net.corda.core.flows.*;
// DOCSTART 01
// Add these imports:
import net.corda.core.contracts.Command; import net.corda.core.contracts.Command;
import net.corda.core.contracts.CommandData; import net.corda.core.contracts.CommandData;
import net.corda.core.flows.*;
import net.corda.core.identity.Party; import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction; import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder; import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker; import net.corda.core.utilities.ProgressTracker;
import static net.corda.docs.java.tutorial.helloworld.TemplateContract.TEMPLATE_CONTRACT_ID; import static com.template.TemplateContract.TEMPLATE_CONTRACT_ID;
// Replace TemplateFlow's definition with:
@InitiatingFlow @InitiatingFlow
@StartableByRPC @StartableByRPC
public class IOUFlow extends FlowLogic<Void> { public class IOUFlow extends FlowLogic<Void> {

View File

@ -1,13 +1,15 @@
package net.corda.docs.java.tutorial.helloworld; package net.corda.docs.java.tutorial.helloworld;
// DOCSTART 01
import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.ContractState; import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty; import net.corda.core.identity.AbstractParty;
import net.corda.core.identity.Party;
import java.util.List; import java.util.List;
// DOCSTART 01
// Add these imports:
import com.google.common.collect.ImmutableList;
import net.corda.core.identity.Party;
// Replace TemplateState's definition with:
public class IOUState implements ContractState { public class IOUState implements ContractState {
private final int value; private final int value;
private final Party lender; private final Party lender;

View File

@ -1,20 +1,25 @@
package net.corda.docs.java.tutorial.twoparty; package net.corda.docs.java.tutorial.twoparty;
// DOCSTART 01
import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.CommandData; import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.CommandWithParties;
import net.corda.core.contracts.Contract; import net.corda.core.contracts.Contract;
import net.corda.core.identity.Party;
import net.corda.core.transactions.LedgerTransaction; import net.corda.core.transactions.LedgerTransaction;
// DOCSTART 01
// Add these imports:
import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.CommandWithParties;
import net.corda.core.identity.Party;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.List; import java.util.List;
import static net.corda.core.contracts.ContractsDSL.requireSingleCommand; import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
import static net.corda.core.contracts.ContractsDSL.requireThat; import static net.corda.core.contracts.ContractsDSL.requireThat;
// Replace TemplateContract's definition with:
public class IOUContract implements Contract { public class IOUContract implements Contract {
public static final String IOU_CONTRACT_ID = "com.template.IOUContract";
// Our Create command. // Our Create command.
public static class Create implements CommandData { public static class Create implements CommandData {
} }

View File

@ -45,15 +45,14 @@ public class IOUFlow extends FlowLogic<Void> {
// We retrieve the notary identity from the network map. // We retrieve the notary identity from the network map.
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
// DOCSTART 02
// We create a transaction builder. // We create a transaction builder.
final TransactionBuilder txBuilder = new TransactionBuilder(); final TransactionBuilder txBuilder = new TransactionBuilder();
txBuilder.setNotary(notary); txBuilder.setNotary(notary);
// DOCSTART 02
// We create the transaction components. // We create the transaction components.
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty); IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
String outputContract = IOUContract.class.getName(); StateAndContract outputContractAndState = new StateAndContract(outputState, IOUContract.IOU_CONTRACT_ID);
StateAndContract outputContractAndState = new StateAndContract(outputState, outputContract);
List<PublicKey> requiredSigners = ImmutableList.of(getOurIdentity().getOwningKey(), otherParty.getOwningKey()); List<PublicKey> requiredSigners = ImmutableList.of(getOurIdentity().getOwningKey(), otherParty.getOwningKey());
Command cmd = new Command<>(new IOUContract.Create(), requiredSigners); Command cmd = new Command<>(new IOUContract.Create(), requiredSigners);

View File

@ -1,16 +1,16 @@
package net.corda.docs.java.tutorial.twoparty; package net.corda.docs.java.tutorial.twoparty;
// DOCSTART 01 // DOCSTART 01
// Add these imports:
import co.paralleluniverse.fibers.Suspendable; import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.contracts.ContractState; import net.corda.core.contracts.ContractState;
import net.corda.core.flows.*; import net.corda.core.flows.*;
import net.corda.core.transactions.SignedTransaction; import net.corda.core.transactions.SignedTransaction;
import net.corda.core.utilities.ProgressTracker; import net.corda.core.utilities.ProgressTracker;
import net.corda.docs.java.tutorial.helloworld.IOUFlow;
import net.corda.docs.java.tutorial.helloworld.IOUState;
import static net.corda.core.contracts.ContractsDSL.requireThat; import static net.corda.core.contracts.ContractsDSL.requireThat;
// Define IOUFlowResponder:
@InitiatedBy(IOUFlow.class) @InitiatedBy(IOUFlow.class)
public class IOUFlowResponder extends FlowLogic<Void> { public class IOUFlowResponder extends FlowLogic<Void> {
private final FlowSession otherPartySession; private final FlowSession otherPartySession;

View File

@ -1,16 +1,19 @@
package net.corda.docs.tutorial.helloworld package net.corda.docs.tutorial.helloworld
// DOCSTART 01
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Command
import net.corda.core.flows.FinalityFlow import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC import net.corda.core.flows.StartableByRPC
// DOCSTART 01
// Add these imports:
import net.corda.core.contracts.Command
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
// Replace TemplateFlow's definition with:
@InitiatingFlow @InitiatingFlow
@StartableByRPC @StartableByRPC
class IOUFlow(val iouValue: Int, class IOUFlow(val iouValue: Int,

View File

@ -1,9 +1,12 @@
package net.corda.docs.tutorial.helloworld package net.corda.docs.tutorial.helloworld
// DOCSTART 01
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
// DOCSTART 01
// Add these imports:
import net.corda.core.identity.Party import net.corda.core.identity.Party
// Replace TemplateState's definition with:
class IOUState(val value: Int, class IOUState(val value: Int,
val lender: Party, val lender: Party,
val borrower: Party) : ContractState { val borrower: Party) : ContractState {

View File

@ -1,12 +1,16 @@
package net.corda.docs.tutorial.twoparty package net.corda.docs.tutorial.twoparty
// DOCSTART 01
import net.corda.core.contracts.CommandData import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract import net.corda.core.contracts.Contract
import net.corda.core.contracts.requireSingleCommand
import net.corda.core.contracts.requireThat
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
// DOCSTART 01
// Add these imports:
import net.corda.core.contracts.*
// Replace IOUContract's contract ID and definition with:
val IOU_CONTRACT_ID = "com.template.IOUContract"
class IOUContract : Contract { class IOUContract : Contract {
// Our Create command. // Our Create command.
class Create : CommandData class Create : CommandData
@ -20,7 +24,7 @@ class IOUContract : Contract {
"There should be one output state of type IOUState." using (tx.outputs.size == 1) "There should be one output state of type IOUState." using (tx.outputs.size == 1)
// IOU-specific constraints. // IOU-specific constraints.
val out = tx.outputsOfType<net.corda.docs.tutorial.helloworld.IOUState>().single() val out = tx.outputsOfType<IOUState>().single()
"The IOU's value must be non-negative." using (out.value > 0) "The IOU's value must be non-negative." using (out.value > 0)
"The lender and the borrower cannot be the same entity." using (out.lender != out.borrower) "The lender and the borrower cannot be the same entity." using (out.lender != out.borrower)

View File

@ -6,9 +6,17 @@ import net.corda.core.contracts.Command
import net.corda.core.contracts.StateAndContract import net.corda.core.contracts.StateAndContract
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.serialization.SerializationWhitelist
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import kotlin.reflect.jvm.jvmName import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
// DOCEND 01 // DOCEND 01
@InitiatingFlow @InitiatingFlow
@ -25,14 +33,13 @@ class IOUFlow(val iouValue: Int,
// We retrieve the notary identity from the network map. // We retrieve the notary identity from the network map.
val notary = serviceHub.networkMapCache.notaryIdentities[0] val notary = serviceHub.networkMapCache.notaryIdentities[0]
// We create a transaction builder // DOCSTART 02
// We create a transaction builder.
val txBuilder = TransactionBuilder(notary = notary) val txBuilder = TransactionBuilder(notary = notary)
// DOCSTART 02
// We create the transaction components. // We create the transaction components.
val outputState = IOUState(iouValue, ourIdentity, otherParty) val outputState = IOUState(iouValue, ourIdentity, otherParty)
val outputContract = IOUContract::class.jvmName val outputContractAndState = StateAndContract(outputState, IOU_CONTRACT_ID)
val outputContractAndState = StateAndContract(outputState, outputContract)
val cmd = Command(IOUContract.Create(), listOf(ourIdentity.owningKey, otherParty.owningKey)) val cmd = Command(IOUContract.Create(), listOf(ourIdentity.owningKey, otherParty.owningKey))
// We add the items to the builder. // We add the items to the builder.

View File

@ -1,16 +1,19 @@
package net.corda.docs.tutorial.twoparty package net.corda.docs.tutorial.twoparty
// DOCSTART 01
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.requireThat
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.SignTransactionFlow import net.corda.core.flows.SignTransactionFlow
import net.corda.core.transactions.SignedTransaction
import net.corda.docs.tutorial.helloworld.IOUFlow import net.corda.docs.tutorial.helloworld.IOUFlow
import net.corda.docs.tutorial.helloworld.IOUState import net.corda.docs.tutorial.helloworld.IOUState
// DOCSTART 01
// Add these imports:
import net.corda.core.contracts.requireThat
import net.corda.core.transactions.SignedTransaction
// Define IOUFlowResponder:
@InitiatedBy(IOUFlow::class) @InitiatedBy(IOUFlow::class)
class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() { class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() {
@Suspendable @Suspendable

View File

@ -6,8 +6,8 @@
Writing the flow Writing the flow
================ ================
A flow encodes a sequence of steps that a node can run to achieve a specific ledger update. By installing new flows on A flow encodes a sequence of steps that a node can perform to achieve a specific ledger update. By installing new flows
a node, we allow the node to handle new business processes. The flow we define will allow a node to issue an on a node, we allow the node to handle new business processes. The flow we define will allow a node to issue an
``IOUState`` onto the ledger. ``IOUState`` onto the ledger.
Flow outline Flow outline
@ -40,8 +40,8 @@ FlowLogic
--------- ---------
All flows must subclass ``FlowLogic``. You then define the steps taken by the flow by overriding ``FlowLogic.call``. All flows must subclass ``FlowLogic``. You then define the steps taken by the flow by overriding ``FlowLogic.call``.
Let's define our ``IOUFlow`` in either ``TemplateFlow.java`` or ``App.kt``. Delete both the existing flows in the Let's define our ``IOUFlow`` in either ``TemplateFlow.java`` or ``App.kt``. Delete the two existing flows in the
template, and replace them with the following: template (``Initiator`` and ``Responder``), and replace them with the following:
.. container:: codeset .. container:: codeset

View File

@ -107,9 +107,15 @@ commands.
We want to create an IOU of 100 with PartyB. We start the ``IOUFlow`` by typing: We want to create an IOU of 100 with PartyB. We start the ``IOUFlow`` by typing:
.. code:: bash .. container:: codeset
start IOUFlow iouValue: 99, otherParty: "O=PartyB,L=New York,C=US" .. code-block:: java
start IOUFlow arg0: 99, arg1: "O=PartyB,L=New York,C=US"
.. code-block:: kotlin
start IOUFlow iouValue: 99, otherParty: "O=PartyB,L=New York,C=US"
This single command will cause PartyA and PartyB to automatically agree an IOU. This is one of the great advantages of This single command will cause PartyA and PartyB to automatically agree an IOU. This is one of the great advantages of
the flow framework - it allows you to reduce complex negotiation and update processes into a single function call. the flow framework - it allows you to reduce complex negotiation and update processes into a single function call.
@ -118,13 +124,7 @@ If the flow worked, it should have recorded a new IOU in the vaults of both Part
We can check the contents of each node's vault by running: We can check the contents of each node's vault by running:
.. container:: codeset .. code-block:: base
.. code-block:: java
run vaultQuery contractStateType: com.template.state.IOUState
.. code-block:: kotlin
run vaultQuery contractStateType: com.template.IOUState run vaultQuery contractStateType: com.template.IOUState
@ -174,6 +174,11 @@ parts:
* The ``IOUState``, representing IOUs on the ledger * The ``IOUState``, representing IOUs on the ledger
* The ``IOUFlow``, orchestrating the process of agreeing the creation of an IOU on-ledger * The ``IOUFlow``, orchestrating the process of agreeing the creation of an IOU on-ledger
After completing this tutorial, your CorDapp should look like this:
* Java: https://github.com/corda/corda-tut1-solution-java
* Kotlin: https://github.com/corda/corda-tut1-solution-kotlin
Next steps Next steps
---------- ----------
There are a number of improvements we could make to this CorDapp: There are a number of improvements we could make to this CorDapp:
@ -183,4 +188,4 @@ There are a number of improvements we could make to this CorDapp:
* We could add an API, to make it easier to interact with the CorDapp * We could add an API, to make it easier to interact with the CorDapp
But for now, the biggest priority is to add an ``IOUContract`` imposing constraints on the evolution of each But for now, the biggest priority is to add an ``IOUContract`` imposing constraints on the evolution of each
``IOUState`` over time. This will be the focus of our next tutorial. ``IOUState`` over time. This will be the focus of our next tutorial.

View File

@ -24,7 +24,6 @@ interface is defined as follows:
val participants: List<AbstractParty> val participants: List<AbstractParty>
} }
<<<<<<< HEAD
The first thing you'll probably notice about this interface declaration is that its not written in Java or another The first thing you'll probably notice about this interface declaration is that its not written in Java or another
common language. The core Corda platform, including the interface declaration above, is entirely written in Kotlin. common language. The core Corda platform, including the interface declaration above, is entirely written in Kotlin.
@ -70,7 +69,7 @@ later is often as simple as adding an additional property to your class definiti
Defining IOUState Defining IOUState
----------------- -----------------
Let's get started by opening ``TemplateState.java`` (for Java) or ``App.kt`` (for Kotlin) and updating Let's get started by opening ``TemplateState.java`` (for Java) or ``StatesAndContracts.kt`` (for Kotlin) and updating
``TemplateState`` to define an ``IOUState``: ``TemplateState`` to define an ``IOUState``:
.. container:: codeset .. container:: codeset

View File

@ -41,34 +41,33 @@ https://docs.corda.net/tutorial-cordapp.html#opening-the-example-cordapp-in-inte
Template structure Template structure
------------------ ------------------
The template has a number of files, but we can ignore most of them. To implement our IOU CorDapp in Java, we'll only The template has a number of files, but we can ignore most of them. We will only be modifying the following files:
need to modify two files. For Kotlin, we'll simply be modifying the ``App.kt`` file:
.. container:: codeset .. container:: codeset
.. code-block:: java .. code-block:: java
// 1. The state // 1. The state
src/main/java/com/template/TemplateState.java cordapp-contracts-states/src/main/java/com/template/TemplateState.java
// 2. The flow // 2. The flow
src/main/java/com/template/TemplateFlow.java cordapp/src/main/java/com/template/TemplateFlow.java
.. code-block:: kotlin .. code-block:: kotlin
src/main/kotlin/com/template/App.kt // 1. The state
cordapp-contracts-states/src/main/kotlin/com/template/StatesAndContracts.kt
// 2. The flow
cordapp/src/main/kotlin/com/template/App.kt
Clean up Clean up
-------- --------
To prevent build errors later on, we should delete the following files before we begin: To prevent build errors later on, we should delete the following files before we begin:
* Java: * Java: ``cordapp/src/main/java/com/template/TemplateClient.java``
* ``src/main/java/com/template/TemplateClient.java``
* ``src/test/java/com/template/FlowTests.java``
* Kotlin: * Kotlin: ``cordapp/src/main/kotlin/com/template/TemplateClient.kt``
* ``src/main/kotlin/com/template/TemplateClient.kt``
* ``src/test/kotlin/com/template/FlowTests.kt``
Progress so far Progress so far
--------------- ---------------

View File

@ -77,7 +77,7 @@ We can picture this transaction as follows:
Defining IOUContract Defining IOUContract
-------------------- --------------------
Let's write a contract that enforces these constraints. We'll do this by modifying either ``TemplateContract.java`` or Let's write a contract that enforces these constraints. We'll do this by modifying either ``TemplateContract.java`` or
``App.kt`` and updating ``TemplateContract`` to define an ``IOUContract``: ``StatesAndContracts.kt`` and updating ``TemplateContract`` to define an ``IOUContract``:
.. container:: codeset .. container:: codeset

View File

@ -17,7 +17,7 @@ We'll do this by modifying the flow we wrote in the previous tutorial.
Verifying the transaction Verifying the transaction
------------------------- -------------------------
In ``IOUFlow.java``/``IOUFlow.kt``, change the imports block to the following: In ``IOUFlow.java``/``App.kt``, change the imports block to the following:
.. container:: codeset .. container:: codeset
@ -31,7 +31,8 @@ In ``IOUFlow.java``/``IOUFlow.kt``, change the imports block to the following:
:start-after: DOCSTART 01 :start-after: DOCSTART 01
:end-before: DOCEND 01 :end-before: DOCEND 01
And update ``IOUFlow.call`` by changing the code following the creation of the ``TransactionBuilder`` as follows: And update ``IOUFlow.call`` by changing the code following the retrieval of the notary's identity from the network as
follows:
.. container:: codeset .. container:: codeset
@ -138,6 +139,11 @@ Our CorDapp now imposes restrictions on the issuance of IOUs. Most importantly,
from both the lender and the borrower before an IOU can be created on the ledger. This prevents either the lender or from both the lender and the borrower before an IOU can be created on the ledger. This prevents either the lender or
the borrower from unilaterally updating the ledger in a way that only benefits themselves. the borrower from unilaterally updating the ledger in a way that only benefits themselves.
After completing this tutorial, your CorDapp should look like this:
* Java: https://github.com/corda/corda-tut2-solution-java
* Kotlin: https://github.com/corda/corda-tut2-solution-kotlin
You should now be ready to develop your own CorDapps. You can also find a list of sample CorDapps You should now be ready to develop your own CorDapps. You can also find a list of sample CorDapps
`here <https://www.corda.net/samples/>`_. As you write CorDapps, you'll also want to learn more about the `here <https://www.corda.net/samples/>`_. As you write CorDapps, you'll also want to learn more about the
:doc:`Corda API <corda-api>`. :doc:`Corda API <corda-api>`.