diff --git a/docs/source/developapps/application.md b/docs/source/developapps/application.md index a4298a13c2f..1ebae8b01f6 100644 --- a/docs/source/developapps/application.md +++ b/docs/source/developapps/application.md @@ -23,9 +23,8 @@ In this topic, we're going to cover: To help your understanding, we'll make reference to the commercial paper sample application provided with Hyperledger Fabric. You can [download it](../install.html) and [run it locally](../tutorial/commercial_paper.html). It -is written in JavaScript, but the logic is quite language independent, so you'll -be easily able to see what's going on! (The sample will become available for -Java and GOLANG as well.) +is written in both JavaScript and Java, but the logic is quite language independent, so you'll +be easily able to see what's going on! (The sample will become available for Go as well.) ## Basic Flow diff --git a/docs/source/developapps/smartcontract.md b/docs/source/developapps/smartcontract.md index 6a6a21a4b6a..e755f0c0d02 100644 --- a/docs/source/developapps/smartcontract.md +++ b/docs/source/developapps/smartcontract.md @@ -7,7 +7,7 @@ in the commercial paper smart contract defines the valid states for commercial paper, and the transaction logic that transition a paper from one state to another. In this topic, we're going to show you how to implement a real world smart contract that governs the process of issuing, buying and redeeming -commercial paper. +commercial paper. We're going to cover: @@ -19,9 +19,9 @@ We're going to cover: * [How to store and retrieve an object in the ledger](#access-the-ledger) If you'd like, you can [download the sample](../install.html) and even [run it -locally](../tutorial/commercial_paper.html). It is written in JavaScript, but +locally](../tutorial/commercial_paper.html). It is written in JavaScript and Java, but the logic is quite language independent, so you'll be easily able to see what's -going on! (The sample will become available for Java and GOLANG as well.) +going on! (The sample will become available for Go as well.) ## Smart Contract @@ -36,46 +36,101 @@ participants, such as MagnetoCorp and DigiBank. The same version of the smart contract must be used by all applications connected to the network so that they jointly implement the same shared business processes and data. +## Implementation Languages + +There are two runtimes that are supported, the Java Virtual Machine and Node.js. This +gives the opportunity to use one of JavaScript, TypeScript, Java or any other language +that can run on one of these supported runtimes. + +In Java and TypeScript, annotations or decorators are used to provide information about +the smart contract and it's structure. This allows for a richer development experience --- +for example, author information or return types can be enforced. Within JavaScript, +conventions must be followed, therefore, there are limitations around what can be +determined automatically. + +Examples here are given in both JavaScript and Java. + ## Contract class -A copy of the PaperNet commercial paper smart contract is contained in -`papercontract.js`. [View -it](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js) -with your browser, or open it in your favourite editor if you've downloaded it. +A copy of the PaperNet commercial paper smart contract is contained in a single +file. View it with your browser, or open it in your favorite editor if you've downloaded it. + - `papercontract.js` - [JavaScript version](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js) + - `CommercialPaperContract.java` - [Java version](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp//contract-java/src/main/java/org/example/CommercialPaperContract.java) + You may notice from the file path that this is MagnetoCorp's copy of the smart -contract. MagnetoCorp and DigiBank must agree the version of the smart contract +contract. MagnetoCorp and DigiBank must agree on the version of the smart contract that they are going to use. For now, it doesn't matter which organization's copy -you look at, they are all the same. +you use, they are all the same. Spend a few moments looking at the overall structure of the smart contract; -notice that it's quite short! Towards the top of `papercontract.js`, you'll see +notice that it's quite short! Towards the top of the file, you'll see that there's a definition for the commercial paper smart contract: - +
+JavaScript ```JavaScript class CommercialPaperContract extends Contract {...} ``` +
+ +
+Java +```Java +@Contract(...) +@Default +public class CommercialPaperContract implements ContractInterface {...} +``` +
-The `CommercialPaperContract` -[class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) -contains the transaction definitions for commercial paper -- **issue**, **buy** + +The `CommercialPaperContract` class contains the transaction definitions for commercial paper -- **issue**, **buy** and **redeem**. It's these transactions that bring commercial papers into existence and move them through their lifecycle. We'll examine these -[transactions](#transaction-definition) soon, but for now notice how +[transactions](#transaction-definition) soon, but for now notice for JavaScript, that the `CommericalPaperContract` extends the Hyperledger Fabric `Contract` [class](https://fabric-shim.github.io/release-1.4/fabric-contract-api.Contract.html). -This built-in class, and the `Context` class, were brought into scope earlier: +With Java, the class must be decorated with the `@Contract(...)` annotation. This provides the opportunity +to supply additional information about the contract, such as license and author. The `@Default()` annotation +indicates that this contract class is the default contract class. Being able to mark a contract class as the +default contract class is useful in some smart contracts which have multiple contract classes. + +If you are using a TypeScript implementation, there are similar `@Contract(...)` annotations that fulfill the same purpose as in Java. + +For more information on the available annotations, consult the available API documentation: +* [API documentation for Java smart contracts](https://fabric-chaincode-java.github.io/) +* [API documentation for Node.js smart contracts](https://fabric-shim.github.io/) + +These classes, annotations, and the `Context` class, were brought into scope earlier: + +
+JavaScript ```JavaScript const { Contract, Context } = require('fabric-contract-api'); ``` +
+ +
+Java +```Java +import org.hyperledger.fabric.contract.Context; +import org.hyperledger.fabric.contract.ContractInterface; +import org.hyperledger.fabric.contract.annotation.Contact; +import org.hyperledger.fabric.contract.annotation.Contract; +import org.hyperledger.fabric.contract.annotation.Default; +import org.hyperledger.fabric.contract.annotation.Info; +import org.hyperledger.fabric.contract.annotation.License; +import org.hyperledger.fabric.contract.annotation.Transaction; +``` +
+ Our commercial paper contract will use built-in features of these classes, such as automatic method invocation, a [per-transaction context](./transactioncontext.html), [transaction handlers](./transactionhandler.html), and class-shared state. -Notice also how the class constructor uses its +Notice also how the JavaScript class constructor uses its [superclass](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super) to initialize itself with an explicit [contract name](./contractname.html): @@ -85,6 +140,8 @@ constructor() { } ``` +With the Java class, the constructor is blank as the explicit contract name can be specified in the `@Contract()` annotation. If it's absent, then the name of the class is used. + Most importantly, `org.papernet.commercialpaper` is very descriptive -- this smart contract is the agreed definition of commercial paper for all PaperNet organizations. @@ -98,10 +155,27 @@ function. In such cases, smart contracts and transactions can be disambiguated. ## Transaction definition Within the class, locate the **issue** method. - +
+JavaScript ```JavaScript async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {...} ``` +
+ +
+Java +```Java +@Transaction +public CommercialPaper issue(CommercialPaperContext ctx, + String issuer, + String paperNumber, + String issueDateTime, + String maturityDateTime, + int faceValue) {...} +``` +
+ +The Java annotation `@Transaction` is used to mark this method as a transaction definition; TypeScript has an equivalent annotation. This function is given control whenever this contract is called to `issue` a commercial paper. Recall how commercial paper 00001 was created with the @@ -137,14 +211,29 @@ See how the smart contract extends the default transaction context by implementing its own `createContext()` method rather than accepting the default implementation: +
+JavaScript ```JavaScript createContext() { return new CommercialPaperContext() } ``` +
+ +
+Java +```Java +@Override +public Context createContext(ChaincodeStub stub) { + return new CommercialPaperContext(stub); +} +``` +
-This extended context adds a custom property `paperList` to the defaults: +This extended context adds a custom property `paperList` to the defaults: +
+JavaScript ```JavaScript class CommercialPaperContext extends Context { @@ -154,6 +243,20 @@ class CommercialPaperContext extends Context { this.paperList = new PaperList(this); } ``` +
+ +
+Java +```Java +class CommercialPaperContext extends Context { + public CommercialPaperContext(ChaincodeStub stub) { + super(stub); + this.paperList = new PaperList(this); + } + public PaperList paperList; +} +``` +
We'll soon see how `ctx.paperList` can be subsequently used to help store and retrieve all PaperNet commercial papers. @@ -164,10 +267,6 @@ see how they map to their corresponding commercial paper transactions. The **buy** transaction: -```JavaScript -async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseTime) {...} -``` - ``` Txn = buy Issuer = MagnetoCorp @@ -178,11 +277,28 @@ Purchase time = 31 May 2020 10:00:00 EST Price = 4.94M USD ``` -The **redeem** transaction: - +
+JavaScript ```JavaScript -async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) {...} +async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseTime) {...} +``` +
+ +
+Java +```Java +@Transaction +public CommercialPaper buy(CommercialPaperContext ctx, + String issuer, + String paperNumber, + String currentOwner, + String newOwner, + int price, + String purchaseDateTime) {...} ``` +
+ +The **redeem** transaction: ``` Txn = redeem @@ -192,12 +308,30 @@ Redeemer = DigiBank Redeem time = 31 Dec 2020 12:00:00 EST ``` +
+JavaScript +```JavaScript +async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) {...} +``` +
+ +
+Java +```Java +@Transaction +public CommercialPaper redeem(CommercialPaperContext ctx, + String issuer, + String paperNumber, + String redeemingOwner, + String redeemDateTime) {...} +``` +
+ In both cases, observe the 1:1 correspondence between the commercial paper -transaction and the smart contract method definition. And don't worry about the -`async` and `await` -[keywords](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) --- they allow asynchronous JavaScript functions to be treated like their -synchronous cousins in other programming languages. +transaction and the smart contract method definition. + +All of the JavaScript functions use the `async` and `await` +[keywords](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) which allow JavaScript functions to be treated as if they were synchronous function calls. ## Transaction logic @@ -217,7 +351,8 @@ Face value = 5M USD ``` It results in the **issue** method being passed control: - +
+JavaScript ```JavaScript async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { @@ -236,7 +371,43 @@ async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue // Must return a serialized paper to caller of smart contract return paper.toBuffer(); } - ``` +``` +
+ +
+Java +```Java +@Transaction +public CommercialPaper issue(CommercialPaperContext ctx, + String issuer, + String paperNumber, + String issueDateTime, + String maturityDateTime, + int faceValue) { + + System.out.println(ctx); + + // create an instance of the paper + CommercialPaper paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, + faceValue,issuer,""); + + // Smart contract, rather than paper, moves paper into ISSUED state + paper.setIssued(); + + // Newly issued paper is owned by the issuer + paper.setOwner(issuer); + + System.out.println(paper); + // Add the paper to the list of all similar commercial papers in the ledger + // world state + ctx.paperList.addPaper(paper); + + // Must return a serialized paper to caller of smart contract + return paper; +} +``` +
+ The logic is simple: take the transaction input variables, create a new commercial paper `paper`, add it to the list of all commercial papers using @@ -248,7 +419,8 @@ to the list of commercial papers. `issue()`, `buy()` and `redeem()` continually re-access `ctx.paperList` to keep the list of commercial papers up-to-date. The logic for the **buy** transaction is a little more elaborate: - +
+JavaScript ```JavaScript async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { @@ -278,6 +450,48 @@ async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateT return paper.toBuffer(); } ``` +
+ +
+Java +```Java +@Transaction +public CommercialPaper buy(CommercialPaperContext ctx, + String issuer, + String paperNumber, + String currentOwner, + String newOwner, + int price, + String purchaseDateTime) { + + // Retrieve the current paper using key fields provided + String paperKey = State.makeKey(new String[] { paperNumber }); + CommercialPaper paper = ctx.paperList.getPaper(paperKey); + + // Validate current owner + if (!paper.getOwner().equals(currentOwner)) { + throw new RuntimeException("Paper " + issuer + paperNumber + " is not owned by " + currentOwner); + } + + // First buy moves state from ISSUED to TRADING + if (paper.isIssued()) { + paper.setTrading(); + } + + // Check paper is not already REDEEMED + if (paper.isTrading()) { + paper.setOwner(newOwner); + } else { + throw new RuntimeException( + "Paper " + issuer + paperNumber + " is not trading. Current state = " + paper.getState()); + } + + // Update the paper + ctx.paperList.updatePaper(paper); + return paper; +} +``` +
See how the transaction checks `currentOwner` and that `paper` is `TRADING` before changing the owner with `paper.setOwner(newOwner)`. The basic flow is @@ -294,28 +508,70 @@ We've seen how to define and implement the **issue**, **buy** and **redeem** transactions using the `CommercialPaper` and `PaperList` classes. Let's end this topic by seeing how these classes work. -Locate the `CommercialPaper` class in the `paper.js` -[file](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/contract/lib/paper.js): +Locate the `CommercialPaper` class: + +
+JavaScript +In the +[paper.js file](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/contract/lib/paper.js): ```JavaScript class CommercialPaper extends State {...} ``` +
+ +
+Java +In the [CommercialPaper.java file](https://github.com/hyperledger/fabric-samples/blob/release-1.4/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaper.java): + + +```Java +@DataType() +public class CommercialPaper extends State {...} +``` +
+ This class contains the in-memory representation of a commercial paper state. See how the `createInstance` method initializes a new commercial paper with the provided parameters: +
+JavaScript ```JavaScript static createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { return new CommercialPaper({ issuer, paperNumber, issueDateTime, maturityDateTime, faceValue }); } ``` +
+ +
+Java +```Java +public static CommercialPaper createInstance(String issuer, String paperNumber, String issueDateTime, + String maturityDateTime, int faceValue, String owner, String state) { + return new CommercialPaper().setIssuer(issuer).setPaperNumber(paperNumber).setMaturityDateTime(maturityDateTime) + .setFaceValue(faceValue).setKey().setIssueDateTime(issueDateTime).setOwner(owner).setState(state); +} +``` +
Recall how this class was used by the **issue** transaction: +
+JavaScript ```JavaScript let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); ``` +
+ +
+Java +```Java +CommercialPaper paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, + faceValue,issuer,""); +``` +
See how every time the issue transaction is called, a new in-memory instance of a commercial paper is created containing the transaction data. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index b196aca91ee..6272d2b790d 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -19,21 +19,36 @@ Fabric binaries, we provide a script that will :doc:`install` to your system. The script also will download the Docker images to your local registry. -Hyperledger Fabric SDKs -^^^^^^^^^^^^^^^^^^^^^^^ +Hyperledger Fabric smart contract (chaincode) SDKs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Hyperledger Fabric offers a number of SDKs to support various programming -languages. There are two officially released SDKs for Node.js and Java: +Hyperledger Fabric offers a number of SDKs to support developing smart contracts (chaincode) +in various programming languages. There are three smart contract SDKs available for Go, Node.js, and Java: - * `Hyperledger Fabric Node SDK `__ and `Node SDK documentation `__. - * `Hyperledger Fabric Java SDK `__. + * `Go SDK documentation `__. + * `Node.js SDK `__ and `Node.js SDK documentation `__. + * `Java SDK `__ and `Java SDK documentation `__. -In addition, there are three more SDKs that have not yet been officially released -(for Python, Go and REST), but they are still available for downloading and testing: +Currently, Node.js and Java support the new smart contract programming model delivered in +Hyperledger Fabric v1.4. Support for Go is planned to be delivered in a later release. - * `Hyperledger Fabric Python SDK `__. - * `Hyperledger Fabric Go SDK `__. - * `Hyperledger Fabric REST SDK `__. +Hyperledger Fabric application SDKs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Hyperledger Fabric offers a number of SDKs to support developing applications +in various programming languages. There are two application SDKs available for Node.js and Java: + + * `Node.js SDK `__ and `Node.js SDK documentation `__. + * `Java SDK `__ and `Java SDK documentation `__. + +In addition, there are two more application SDKs that have not yet been officially released +(for Python and Go), but they are still available for downloading and testing: + + * `Python SDK `__. + * `Go SDK `__. + +Currently, Node.js and Java support the new application programming model delivered in +Hyperledger Fabric v1.4. Support for Go is planned to be delivered in a later release. Hyperledger Fabric CA ^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/source/whatsnew.rst b/docs/source/whatsnew.rst index 4af70fd77d6..2bd74179871 100644 --- a/docs/source/whatsnew.rst +++ b/docs/source/whatsnew.rst @@ -79,11 +79,13 @@ Improved programming model for developing applications ------------------------------------------------------ Writing decentralized applications has just gotten easier. Programming model -improvements in the Node.js SDK and Node.js chaincode makes the development +improvements for smart contracts (chaincode) and the SDKs makes the development of decentralized applications more intuitive, allowing you to focus -on your application logic. The existing npm packages are still available for -use, while the new npm packages provide a layer of abstraction to improve -developer productivity and ease of use. +on your application logic. These programming model enhancements are available +for Node.js (as of Fabric v1.4.0) and Java (as of Fabric v1.4.2). The existing +SDKs are still available for use and existing applications will continue to work. +It is recommended that developers migrate to the new SDKs, which provide a layer +of abstraction to improve developer productivity and ease of use. New documentation helps you understand the various aspects of creating a decentralized application for @@ -124,13 +126,13 @@ New tutorials ------------- * :doc:`write_first_app`: - This tutorial has been updated to leverage the improved Node.js SDK and chaincode - programming model. The tutorial has both JavaScript and Typescript examples of - the client application and chaincode. + This tutorial has been updated to leverage the improved smart contract (chaincode) + and SDK programming model. The tutorial has Java, JavaScript, and Typescript examples + of the client application and chaincode. * :doc:`tutorial/commercial_paper` As mentioned above, this is the tutorial that accompanies the new Developing - Applications documentation. + Applications documentation. This contains both Java and JavaScript code. * :doc:`upgrade_to_newest_version`: Leverages the network from :doc:`build_network` to demonstrate an upgrade from diff --git a/docs/source/write_first_app.rst b/docs/source/write_first_app.rst index 3538a434e2a..8d33cb51603 100644 --- a/docs/source/write_first_app.rst +++ b/docs/source/write_first_app.rst @@ -34,9 +34,8 @@ We’ll go through three principle steps: .. image:: images/AppConceptsOverview.png **2. Learning about a sample smart contract, FabCar.** - We use a smart contract written in **JavaScript**. We’ll - inspect the smart contract to learn about the transactions within them, and - how they are used by applications to query and update the ledger. + We’ll inspect the smart contract to learn about the transactions within them, + and how they are used by applications to query and update the ledger. **3. Develop a sample application which uses FabCar.** Our application will use the FabCar smart contract to query and update car assets on the ledger. @@ -92,9 +91,16 @@ Launch the network .. note:: This next section requires you to be in the ``fabcar`` subdirectory within your local clone of the ``fabric-samples`` repo. + This tutorial demonstrates the JavaScript versions of the ``FabCar`` + smart contract and application, but the ``fabric-samples`` repo also + contains Java and TypeScript versions of this sample. To try the + Java or TypeScript versions, change the ``javascript`` argument + for ``./startFabric.sh`` below to either ``java`` or ``typescript`` + and follow the instructions written to the terminal. + Launch your network using the ``startFabric.sh`` shell script. This command will spin up a blockchain network comprising peers, orderers, certificate -authorities and more. It will also install and instantiate a javascript version +authorities and more. It will also install and instantiate a JavaScript version of the ``FabCar`` smart contract which will be used by our application to access the ledger. We'll learn more about these components as we go through the tutorial.