diff --git a/docs/source/clientrpc.rst b/docs/source/clientrpc.rst index 546744e8a6..a2db1469a9 100644 --- a/docs/source/clientrpc.rst +++ b/docs/source/clientrpc.rst @@ -1,27 +1,52 @@ -Client RPC -========== +.. highlight:: kotlin +.. raw:: html + + + + +Interacting with a node +======================= .. contents:: Overview -------- -Corda provides a client library that allows you to easily write clients in a JVM-compatible language to interact -with a running node. The library connects to the node using a message queue protocol and then provides a simple RPC -interface to interact with the node. You make calls on a Java object as normal, and the marshalling back and forth is -handled for you. +You should interact with your node using the `CordaRPCClient`_ library. This library that allows you to easily +write clients in a JVM-compatible language to interact with a running node. The library connects to the node using a +message queue protocol and then provides a simple RPC interface to interact with the node. You make calls on a JVM +object as normal, and the marshalling back and forth is handled for you. -The starting point for the client library is the `CordaRPCClient`_ class. `CordaRPCClient`_ provides a ``start`` method -that returns a `CordaRPCConnection`_. A `CordaRPCConnection`_ allows you to access an implementation of the -`CordaRPCOps`_ interface with ``proxy`` in Kotlin or ``getProxy()`` in Java. The observables that are returned by RPC -operations can be subscribed to in order to receive an ongoing stream of updates from the node. More detail on this -functionality is provided in the docs for the ``proxy`` method. +.. warning:: The built-in Corda webserver is deprecated and unsuitable for production use. If you want to interact with + your node via HTTP, you will need to stand up your own webserver, then create an RPC connection between your node + and this webserver using the `CordaRPCClient`_ library. You can find an example of how to do this + `here `_. + +Connecting to a node via RPC +---------------------------- +`CordaRPCClient`_ provides a ``start`` method that takes the node's RPC address and returns a `CordaRPCConnection`_. +`CordaRPCConnection`_ provides a ``proxy`` method that takes an RPC username and password and returns a `CordaRPCOps`_ +object that you can use to interact with the node. + +Here is an example of using `CordaRPCClient`_ to connect to a node and log the current time on its internal clock: + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcExample.kt + :language: kotlin + :start-after: START 1 + :end-before: END 1 + + .. literalinclude:: example-code/src/main/java/net/corda/docs/ClientRpcExampleJava.java + :language: java + :start-after: START 1 + :end-before: END 1 .. warning:: The returned `CordaRPCConnection`_ is somewhat expensive to create and consumes a small amount of server side resources. When you're done with it, call ``close`` on it. Alternatively you may use the ``use`` method on `CordaRPCClient`_ which cleans up automatically after the passed in lambda finishes. Don't create a new proxy for every call you make - reuse an existing one. -For a brief tutorial on using the RPC API, see :doc:`tutorial-clientrpc-api`. +For further information on using the RPC API, see :doc:`tutorial-clientrpc-api`. RPC permissions --------------- @@ -276,7 +301,7 @@ will be freed automatically. is non-deterministic. .. note:: Observables can only be used as return arguments of an RPC call. It is not currently possible to pass -Observables as parameters to the RPC methods. + Observables as parameters to the RPC methods. Futures ------- @@ -306,7 +331,7 @@ side as if it was thrown from inside the called RPC method. These exceptions can Connection management --------------------- -It is possible to not be able to connect to the server on the first attempt. In that case, the ``CordaRPCCLient.start()`` +It is possible to not be able to connect to the server on the first attempt. In that case, the ``CordaRPCClient.start()`` method will throw an exception. The following code snippet is an example of how to write a simple retry mechanism for such situations: diff --git a/docs/source/corda-configuration-file.rst b/docs/source/corda-configuration-file.rst index dfef436e7a..d21076eed4 100644 --- a/docs/source/corda-configuration-file.rst +++ b/docs/source/corda-configuration-file.rst @@ -1,4 +1,4 @@ -Node configuration +Configuring a node ================== .. contents:: diff --git a/docs/source/cordapp-build-systems.rst b/docs/source/cordapp-build-systems.rst index 1548cf0085..7d3a4a8cb7 100644 --- a/docs/source/cordapp-build-systems.rst +++ b/docs/source/cordapp-build-systems.rst @@ -1,5 +1,5 @@ -Building a CorDapp -================== +Building and installing a CorDapp +================================= .. contents:: diff --git a/docs/source/cordapp-overview.rst b/docs/source/cordapp-overview.rst index 36c845036a..7c59ed6701 100644 --- a/docs/source/cordapp-overview.rst +++ b/docs/source/cordapp-overview.rst @@ -3,20 +3,38 @@ What is a CorDapp? CorDapps (Corda Distributed Applications) are distributed applications that run on the Corda platform. The goal of a CorDapp is to allow nodes to reach agreement on updates to the ledger. They achieve this goal by defining flows that -Corda node owners can invoke through RPC calls: +Corda node owners can invoke over RPC: .. image:: resources/node-diagram.png + :scale: 25% + :align: center -CorDapps are made up of the following key components: +CorDapp components +------------------ +CorDapps take the form of a set of JAR files containing class definitions written in Java and/or Kotlin. -* States, defining the facts over which agreement is reached (see :doc:`Key Concepts - States `) +These class definitions will commonly include the following elements: + +* Flows: Define a routine for the node to run, usually to update the ledger + (see :doc:`Key Concepts - Flows `). They subclass ``FlowLogic`` +* States: Define the facts over which agreement is reached (see :doc:`Key Concepts - States `). + They implement the ``ContractState`` interface * Contracts, defining what constitutes a valid ledger update (see - :doc:`Key Concepts - Contracts `) -* Services, providing long-lived utilities within the node -* Serialisation whitelists, restricting what types your node will receive off the wire + :doc:`Key Concepts - Contracts `). They implement the ``Contract`` interface +* Services, providing long-lived utilities within the node. They subclass ``SingletonSerializationToken`` +* Serialisation whitelists, restricting what types your node will receive off the wire. They implement the + ``SerializationWhitelist`` interface -Each CorDapp is installed at the level of the individual node, rather than on the network itself. For example, a node -owner may choose to install the Bond Trading CorDapp, with the following components: +But the CorDapp JAR can also include other class definitions. These may include: + +* APIs and static web content: These are served by Corda's built-in webserver. This webserver is not + production-ready, and should be used for testing purposes only +* Utility classes + +An example +---------- +Suppose a node owner wants their node to be able to trade bonds. They may choose to install a Bond Trading CorDapp with +the following components: * A ``BondState``, used to represent bonds as shared facts on the ledger * A ``BondContract``, used to govern which ledger updates involving ``BondState`` states are valid diff --git a/docs/source/example-code/src/main/java/net/corda/docs/ClientRpcExampleJava.java b/docs/source/example-code/src/main/java/net/corda/docs/ClientRpcExampleJava.java new file mode 100644 index 0000000000..2a7bdb4d9b --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/ClientRpcExampleJava.java @@ -0,0 +1,34 @@ +package net.corda.docs; + +// START 1 +import net.corda.client.rpc.CordaRPCClient; +import net.corda.client.rpc.CordaRPCConnection; +import net.corda.core.messaging.CordaRPCOps; +import net.corda.core.utilities.NetworkHostAndPort; +import org.apache.activemq.artemis.api.core.ActiveMQException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutionException; + +class ExampleRpcClientJava { + private static final Logger logger = LoggerFactory.getLogger(ExampleRpcClient.class); + + public static void main(String[] args) throws ActiveMQException, InterruptedException, ExecutionException { + if (args.length != 3) { + throw new IllegalArgumentException("Usage: TemplateClient "); + } + final NetworkHostAndPort nodeAddress = NetworkHostAndPort.parse(args[0]); + String username = args[1]; + String password = args[2]; + + final CordaRPCClient client = new CordaRPCClient(nodeAddress); + final CordaRPCConnection connection = client.start(username, password); + final CordaRPCOps cordaRPCOperations = connection.getProxy(); + + logger.info(cordaRPCOperations.currentNodeTime().toString()); + + connection.notifyServerAndClose(); + } +} +// END 1 \ No newline at end of file diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcExample.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcExample.kt new file mode 100644 index 0000000000..e41eb2ed18 --- /dev/null +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcExample.kt @@ -0,0 +1,31 @@ +@file:Suppress("unused") + +package net.corda.docs + +// START 1 +import net.corda.client.rpc.CordaRPCClient +import net.corda.core.utilities.NetworkHostAndPort.Companion.parse +import net.corda.core.utilities.loggerFor +import org.slf4j.Logger + +class ExampleRpcClient { + companion object { + val logger: Logger = loggerFor() + } + + fun main(args: Array) { + require(args.size == 3) { "Usage: TemplateClient " } + val nodeAddress = parse(args[0]) + val username = args[1] + val password = args[2] + + val client = CordaRPCClient(nodeAddress) + val connection = client.start(username, password) + val cordaRPCOperations = connection.proxy + + logger.info(cordaRPCOperations.currentNodeTime().toString()) + + connection.notifyServerAndClose() + } +} +// END 1 \ No newline at end of file diff --git a/docs/source/shell.rst b/docs/source/shell.rst index aa824f3e76..73ef8f0a6d 100644 --- a/docs/source/shell.rst +++ b/docs/source/shell.rst @@ -4,8 +4,8 @@ -Shell -===== +Node shell +========== .. contents:: diff --git a/docs/source/tutorial-clientrpc-api.rst b/docs/source/tutorial-clientrpc-api.rst index ff6739b70a..597e8a96f9 100644 --- a/docs/source/tutorial-clientrpc-api.rst +++ b/docs/source/tutorial-clientrpc-api.rst @@ -1,3 +1,9 @@ +.. highlight:: kotlin +.. raw:: html + + + + .. _graphstream: http://graphstream-project.org/ Using the client RPC API diff --git a/docs/source/writing-a-cordapp.rst b/docs/source/writing-a-cordapp.rst index bda4f2977a..02bca02c2b 100644 --- a/docs/source/writing-a-cordapp.rst +++ b/docs/source/writing-a-cordapp.rst @@ -1,58 +1,70 @@ -Writing a CorDapp +CorDapp structure ================= .. contents:: -Overview --------- -CorDapps can be written in either Java, Kotlin, or a combination of the two. Each CorDapp component takes the form -of a JVM class that subclasses or implements a Corda library type: - -* Flows subclass ``FlowLogic`` -* States implement ``ContractState`` -* Contracts implement ``Contract`` -* Services subclass ``SingletonSerializationToken`` -* Serialisation whitelists implement ``SerializationWhitelist`` - -Web content and RPC clients ---------------------------- -For testing purposes, CorDapps may also include: - -* **APIs and static web content**: These are served by Corda's built-in webserver. This webserver is not - production-ready, and should be used for testing purposes only - -* **RPC clients**: These are programs that automate the process of interacting with a node via RPC - -In production, a production-ready webserver should be used, and these files should be moved into a different module or -project so that they do not bloat the CorDapp at build time. - .. _cordapp-structure: -Structure and dependencies --------------------------- -You should base your project on the Java template (for CorDapps written in Java) or the Kotlin template (for CorDapps -written in Kotlin): +Modules +------- +The source code for a CorDapp is divided into one or more modules, each of which will be compiled into a separate JAR. +Together, these JARs represent a single CorDapp. Typically, a Cordapp contains all the classes required for it to be +used standalone. However, some Cordapps are only libraries for other Cordapps and cannot be run standalone. -* `Java Template CorDapp `_ -* `Kotlin Template CorDapp `_ +A common pattern is to have: -Please checkout the branch of the template that corresponds to the version of Corda you are using. For example, someone -building a CorDapp on Corda 3 should use the ``release-V3`` branch of the template. +* One module containing only the CorDapp's contracts and/or states, as well as any required dependencies +* A second module containing the remaining classes that depend on these contracts and/or states -The required dependencies are defined by the ``build.gradle`` file in the root directory of the template. +This is because each time a contract is used in a transaction, the entire JAR containing the contract's definition is +attached to the transaction. This is to ensure that the exact same contract and state definitions are used when +verifying this transaction at a later date. Because of this, you will want to keep this module, and therefore the +resulting JAR file, as small as possible to reduce the size of your transactions and keep your node performant. -The project should be split into two modules: +However, this two-module structure is not prescriptive: -* A ``cordapp-contracts-states`` module containing classes such as contracts and states that will be sent across the - wire as part of a flow -* A ``cordapp`` module containing the remaining classes +* A library CorDapp containing only contracts and states would only need a single module -Each module will be compiled into its own CorDapp. This minimises the size of the JAR that has to be sent across the -wire when nodes are agreeing ledger updates. +* In a CorDapp with multiple sets of contracts and states that **do not** depend on each other, each independent set of + contracts and states would go in a separate module to reduce transaction size + +* In a CorDapp with multiple sets of contracts and states that **do** depend on each other, either keep them in the + same module or create separate modules that depend on each other + +* The module containing the flows and other classes can be structured in any way because it is not attached to + transactions + +Template CorDapps +----------------- +You should base your project on one of the following templates: + +* `Java Template CorDapp `_ (for CorDapps written in Java) +* `Kotlin Template CorDapp `_ (for CorDapps written in Kotlin) + +Please use the branch of the template that corresponds to the major version of Corda you are using. For example, +someone building a CorDapp on Corda 3.2 should use the ``release-V3`` branch of the template. + +Build system +^^^^^^^^^^^^ + +The templates are built using Gradle. A Gradle wrapper is provided in the ``wrapper`` folder, and the dependencies are +defined in the ``build.gradle`` files. See :doc:`cordapp-build-systems` for more information. + +No templates are currently provided for Maven or other build systems. + +Modules +^^^^^^^ +The templates are split into two modules: + +* A ``cordapp-contracts-states`` module containing the contracts and states +* A ``cordapp`` module containing the remaining classes that depends on the ``cordapp-contracts-states`` module + +These modules will be compiled into two JARs - a ``cordapp-contracts-states`` JAR and a ``cordapp`` JAR - which +together represent the Template CorDapp. Module one - cordapp-contracts-states -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Here is the structure of the ``src`` directory for the ``cordapp-contracts-states`` module: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Here is the structure of the ``src`` directory for the ``cordapp-contracts-states`` module of the Java template: .. parsed-literal:: @@ -73,8 +85,8 @@ These are definitions for classes that we expect to have to send over the wire. CorDapp. Module two - cordapp -^^^^^^^^^^^^^^^^^^^^ -Here is the structure of the ``src`` directory for the ``cordapp`` module: +~~~~~~~~~~~~~~~~~~~~ +Here is the structure of the ``src`` directory for the ``cordapp`` module of the Java template: .. parsed-literal:: @@ -116,37 +128,27 @@ The ``src`` directory is structured as follows: Within ``main``, we have the following directories: -* ``resources/META-INF/services`` contains registries of the CorDapp's serialisation whitelists and web plugins -* ``resources/certificates`` contains dummy certificates for test purposes -* ``resources/templateWeb`` contains a dummy front-end -* ``java`` (or ``kotlin`` in the Kotlin template), which includes the source-code for our CorDapp +* ``java``, which contains the source-code for our CorDapp: -The source-code for our CorDapp breaks down as follows: + * ``TemplateFlow.java``, which contains a template ``FlowLogic`` subclass + * ``TemplateState.java``, which contains a template ``ContractState`` implementation + * ``TemplateContract.java``, which contains a template ``Contract`` implementation + * ``TemplateSerializationWhitelist.java``, which contains a template ``SerializationWhitelist`` implementation + * ``TemplateApi.java``, which contains a template API for the deprecated Corda webserver + * ``TemplateWebPlugin.java``, which registers the API and front-end for the deprecated Corda webserver + * ``TemplateClient.java``, which contains a template RPC client for interacting with our CorDapp -* ``TemplateFlow.java``, which contains a dummy ``FlowLogic`` subclass -* ``TemplateState.java``, which contains a dummy ``ContractState`` implementation -* ``TemplateContract.java``, which contains a dummy ``Contract`` implementation -* ``TemplateSerializationWhitelist.java``, which contains a dummy ``SerializationWhitelist`` implementation +* ``resources/META-INF/services``, which contains various registries: -In developing your CorDapp, you should start by modifying these classes to define the components of your CorDapp. A -single CorDapp can define multiple flows, states, and contracts. + * ``net.corda.core.serialization.SerializationWhitelist``, which registers the CorDapp's serialisation whitelists + * ``net.corda.webserver.services.WebServerPluginRegistry``, which registers the CorDapp's web plugins -The template also includes a web API and RPC client: +* ``resources/templateWeb``, which contains a template front-end -* ``TemplateApi.java`` -* ``TemplateClient.java`` -* ``TemplateWebPlugin.java`` +In a production CorDapp: -These are for testing purposes and would be removed in a production CorDapp. +* We would remove the files related to the deprecated Corda webserver (``TemplateApi.java``, + ``TemplateWebPlugin.java``, ``resources/templateWeb``, and ``net.corda.webserver.services.WebServerPluginRegistry``) + and replace them with a production-ready webserver -Resources ---------- -In writing a CorDapp, these pages may be particularly helpful: - -* :doc:`getting-set-up`, to set up your development environment. -* The :doc:`hello-world-introduction` tutorial to write your first CorDapp. -* :doc:`cordapp-build-systems` to build and run your CorDapp. -* The `API docs `_ to read about the API available in developing CorDapps. -* There is also a :doc:`cheat-sheet` recapping the key types. -* The :doc:`flow-cookbook` to see code examples of how to perform common flow tasks. -* `Sample CorDapps `_ showing various parts of Corda's functionality. \ No newline at end of file +* We would also move ``TemplateClient.java`` into a separate module so that it is not included in the CorDapp \ No newline at end of file