3. Getting Started With Hyperledger Fabric (Blockchain)
Page 3 of 51
Table of Contents
Pre requisites 4
Part 1 - Use Blockchain as a Service on Bluemix Cloud and start a network
locally 5
a) Use Blockchain as a Service on the Cloud 5
b) Start a network locally 7
Part 2 - Create a smart contract in Java 14
a) Create a contract 15
1. Implementing overridden methods 22
2. Implementing initialization and invocation methods 24
b) Deployment and testing 27
1. Local testing 27
2. Deployment 28
3. Interact more with your chaincode 30
Part 3 – Develop the client side application 33
a) Initialization 33
b) Deployment 42
c) Queries 44
d) Invocations 45
e) Testing it ! 46
4. Getting Started With Hyperledger Fabric (Blockchain)
Page 4 of 51
Pre requisites
For Part 1:
• Bluemix account: https://console.ng.bluemix.net/registration
• Docker: https://docs.docker.com/engine/installation/#platform-support-
matrix
• Docker compose: https://docs.docker.com/compose/install
• Postman: https://www.getpostman.com
For Part 2:
• Java 8:
http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-
138363.html
• Eclipse: https://www.eclipse.org/downloads
• Eclipse Maven plugin: (you can use the one embedded on Eclipse)
• Eclipse Gradle plugin: (depending on the version, it can be already
included or https://projects.eclipse.org/projects/tools.buildship)
For Part 3:
• (same as part2)
5. Getting Started With Hyperledger Fabric (Blockchain)
Page 5 of 51
Part 1 - Use Blockchain as a Service on Bluemix
Cloud and start a network locally
a) Use Blockchain as a Service on the Cloud
You can go to Bluemix and use a Blockchain as a Service
If you do not have a Bluemix access yet, please register for a free 30 days
account here (https://console.ng.bluemix.net/registration)
Go to Bluemix console > Catalog (https://console.ng.bluemix.net/catalog)
And search for service named “Blockchain” on the filter area
6. Getting Started With Hyperledger Fabric (Blockchain)
Page 6 of 51
Click on the service, give it a unique name and click on Create button
When finished, click on Launch Dashboard
Bluemix has created for you a Blockchain network of 4 peers to let you focus
on developing smart contract applications on top of it.
Scroll the menu to explore:
- Network: 4 validating peers + Certificate Authority
- Blockchain: local view on the Blockchain for peer 0
- Demo Chaincode: Ready to deploy demos
7. Getting Started With Hyperledger Fabric (Blockchain)
Page 7 of 51
- APIs: Swagger-like HTTP call interactions with Blockchain
network/peers
- Logs: server logs on each peer
- Service Status: service info to let you know maintenance and service
upgrades
- Support: helpful links
Now that you have a blockchain network running, go to the menu Demo
Chaincode to play with one demo
b) Start a network locally
Now that you have tested a Blockchain on the Cloud, let’s do the same on
your machine. We will explain a little bit more the way to deploy your own
Blockchain network
Install Docker on your machine:
https://docs.docker.com/engine/installation/#platform-support-matrix
8. Getting Started With Hyperledger Fabric (Blockchain)
Page 8 of 51
We will use Hyperledger official Docker images to start a Blockchain network
of 4 peers + 1 CA (Certificate Authority)
Images are available here : https://hub.docker.com/u/hyperledger
If you encounter any problem during this lab, you can find links at the end of
this document pointing to the correction. There you can verify if you have
done any mistake.
All commands below are for Unix machines (Linux, MacOs, Debian, Ubuntu,
etc… ). If you use another OS like Windows, just transcript the command. We
are using very basic commands that exists on all OS.
1. Create a Docker file from the official image. Open a console and type
theses commands (choose any workspace folder on your machine)
mkdir baseimage
touch baseimage/Dockerfile
echo "FROM hyperledger/fabric-peer:x86_64-0.6.1-preview" >
baseimage/Dockerfile
2. Create the file for Docker compose
touch four-peer-ca.yaml
3. Open this new file on an editor (can double click on it from the file
explorer) and type the beginning of the file
version: '2'
services:
baseimage:
build: ./baseimage
image: hyperledger/fabric-baseimage:latest
membersrvc:
image: hyperledger/fabric-membersrvc:x86_64-0.6.1-preview
extends:
file: base/membersrvc.yaml
service: membersrvc
vp0:
image: hyperledger/fabric-peer:x86_64-0.6.1-preview
extends:
file: base/peer-unsecure-base.yaml
service: peer-unsecure-base
9. Getting Started With Hyperledger Fabric (Blockchain)
Page 9 of 51
ports:
- "7050:7050" # REST
- "7051:7051" # Grpc
- "7053:7053" # Peer callback events
environment:
- CORE_PEER_ID=vp0
links:
- membersrvc
volumes:
- /Users/benjaminfuentes/git:/chaincode
Save the file and leave it open
As you can see we refer to the base image, we declare a membersrvc peer
that is the Certificate Authority and only 1 peer named vp0.
We will write the file base/membersrvc.yaml on the next steps
Now, have a look on the peer vp0 configuration:
- We are going to write the base file for all validating peer on base/peer-
unsecure-base.yaml. We are not going to use security enabled for
this demo in order to simplify all API requests, also we will use the
NOOPS consensus (i.e autovalidating consensus for development).
You can have a look on Fabric options to enable security and configure
PBFT (see http://hyperledger-
fabric.readthedocs.io/en/v0.6/Setup/Network-setup )
- We are translating inside containers ports to outside using “ports:” You
can read it like this “insidePort:outsidePort”
- We name the first peer vp0 (for the block section and the parameter
CORE_PEER_ID)
- Finally, we add a dependency on service named membersrvc (which
need to be started before)
- Parameter volumes will be used for vp0 only in order to deploy
chaincode based on a file path. Please change
/Users/benjaminfuentes/git path with our own workspace path!
YAML files are really boring strict with space indentation, be very
careful. Copy/paste from correction files on links at the end of this
document if you have any problem
4. Now that you have understood the configuration, you can add 3 more
peers at the end of this file four-peer-ca.yaml: vp1, vp2, and vp3.
Copy paste vp0 block, rename peer name, CORE_PEER_ID, and
translate outside ports with 1000 offset (i.e. vp1 from 8050 to 8053,
vp2 from 9050 to 9053 and vp4 from 10050 to 10053). Inside ports are
kept the same obviously. You do not need to mount a volume as we
will deploy chaincode only on vp0.
10. Getting Started With Hyperledger Fabric (Blockchain)
Page 10 of 51
Also you will need to add this on the environment section to refer to
the first node :
- CORE_PEER_DISCOVERY_ROOTNODE=vp0:7051
Finally on the links section, add a dependency to vp0
- vp0
Save and close file.
5. As that the main file is done, let’s create the common peer file
base/peer-unsecure-base.yaml
mkdir base
touch base/peer-unsecure-base.yaml
and edit the file
version: '2'
services:
peer-unsecure-base:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- CORE_PEER_DISCOVERY_PERIOD=300s
- CORE_PEER_DISCOVERY_TOUCHPERIOD=301s
- CORE_PEER_ADDRESSAUTODETECT=true
- CORE_VM_ENDPOINT=unix:///var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_PKI_ECA_PADDR=membersrvc:7054
- CORE_PEER_PKI_TCA_PADDR=membersrvc:7054
- CORE_PEER_PKI_TLSCA_PADDR=membersrvc:7054
- CORE_SECURITY_ENABLED=false
command: sh -c "sleep 10; peer node start"
Save and close
Here we have mounted Docker socket to dialog with Docker deamon and set
security enabled to false
6. Create the file for the Certificate Authority
touch base/membersrvc.yaml
and then edit it
version: '2'
services:
11. Getting Started With Hyperledger Fabric (Blockchain)
Page 11 of 51
membersrvc:
ports:
- "7054:7054"
command: membersrvc
environment:
- MEMBERSRVC_CA_LOGGING_SERVER=INFO
- MEMBERSRVC_CA_LOGGING_CA=INFO
- MEMBERSRVC_CA_LOGGING_ECA=INFO
- MEMBERSRVC_CA_LOGGING_ECAP=INFO
- MEMBERSRVC_CA_LOGGING_ECAA=INFO
- MEMBERSRVC_CA_LOGGING_ACA=INFO
- MEMBERSRVC_CA_LOGGING_ACAP=INFO
- MEMBERSRVC_CA_LOGGING_TCA=INFO
- MEMBERSRVC_CA_LOGGING_TCAP=INFO
- MEMBERSRVC_CA_LOGGING_TCAA=INFO
- MEMBERSRVC_CA_LOGGING_TLSCA=INFO
Save and close file
7. All is set now, let’s start the network using the command
docker-compose -f four-peer-ca.yaml up
To see containers running, open another terminal and send command
docker ps
8. If you want to stop the network, escape the running docker compose
(Ctrl + C) or use the command
docker-compose -f four-peer-ca.yaml stop
This will stop all containers
To see containers stopped:
docker ps -a
9. If you want to destroy all containers, just run. (if case you did a mistake
and want to start from scratch from the docker-compose config files)
docker-compose -f four-peer-ca.yaml down
Finally test your Blockchain network with Postman.
12. Getting Started With Hyperledger Fabric (Blockchain)
Page 12 of 51
To install Postman : https://www.getpostman.com
Launch it from the menu bar and import the file (that you will download at this
URL) : https://github.com/zamrokk/JavaCDD/blob/master/postman.json
Click on Raw
13. Getting Started With Hyperledger Fabric (Blockchain)
Page 13 of 51
Save the page (Ctrl+S)
Import the file on Postman. Click on Import
14. Getting Started With Hyperledger Fabric (Blockchain)
Page 14 of 51
Drop the file, or browse folder
On the Collections tab, click on the first line named CHAIN V0.6. Click on
button Send, you should have a response 200 OK with chain height equals to
1
Part 2 - Create a smart contract in Java
In the following sections you will discover how Blockchain technology can be
used to sign contract between a farmer and an insurer and then to trigger
changes on the contract’s state. CDD derivative is an insurance for farmers
to hedge against poor harvests caused by failing rains during the growing
15. Getting Started With Hyperledger Fabric (Blockchain)
Page 15 of 51
period, excessive rain during harvesting, high winds in case of plantations or
temperature variabilities in case of greenhouse crops. In a CDD case, every
time the average day degree passes under a threshold, a client could receive
a payment, smoothing earnings.
• Creating a contract between a farmer and an insurer
• Executing a contract based on a specific location
• Querying the contract State to know if the farmer has received
a payment
In this business scenario each participant has entered into a business
agreement with each other and all parties are known and trusted by each
other. For each contract deployment, one instance of the java project is
running on the Blockchain. For our example, we will create only one contract
between two people, but you can do as many as you want.
This demo has been simplified in the way:
• No security has been enabled and configured.
• We trust and assume that calls to Weather API will send back always
the same value for each peer. We also trust Weather API data as a
trustable oracle. (This is NOT deterministic => Bad bad bad!)
• We can do unlimited calls. Normally in a real case, the contract
should be executed once relatively to a period corresponding to the
average temperature of the previous month
• The contract should contain a start and end date validity. You can
do it as an extra exercise
a) Create a contract
In the following section you will code a CDD derivative chaincode contract in
Java using Hyperledger.
Farmer Insurer
16. Getting Started With Hyperledger Fabric (Blockchain)
Page 16 of 51
Install Eclipse : https://www.eclipse.org/downloads
1. Open Eclipse and create a new Maven Project
Click next
17. Getting Started With Hyperledger Fabric (Blockchain)
Page 17 of 51
2. You need to copy some configuration files and pojos java class to help
you start and let us focus on the important files.
Recreate the project structure as it:
18. Getting Started With Hyperledger Fabric (Blockchain)
Page 18 of 51
To create the com.ibm package, you do it like this:
Copy theses files from the project url into its correct folder
(https://github.com/zamrokk/JavaCDD):
• build.gradle
• pom.xml
19. Getting Started With Hyperledger Fabric (Blockchain)
Page 19 of 51
• /src/main/java/com/ibm/ContractRecord.java
• /src/main/java/com/ibm/WeatherObservationResponse.java
• /src/test/java/com/ibm/JavaCDDTest.java
3. Have a look on the project structure. You have the choice to use
Maven or Gradle for development but Gradle will be mandatory when
the code will be deployed as Gradle file will be only run by Hyperledger
on version V0.6.1
At the moment, you have 2 POJOs class files:
• ContractRecord
• WeatherObservationResponse
You have a test class available: JavaCDDTest
You will be asked to code a JavaCDD class file that extends
ChaincodeBase
4. Create a new class JavaCDD on package com.ibm that’s extends
ChaincodeBase. You will write later a main method. You can see that
some methods need to be implemented too.
5. Look at dependencies to see from which package is coming
ChaincodeBase class. The fabric-sdk-java jar will be downloaded
automatically during compilation. Open pom.xml and build.gradle
Maven
<dependency>
<groupId>org.hyperledger.fabric-sdk-java</groupId>
<artifactId>fabric-sdk-java</artifactId>
<version>0.6</version>
</dependency>
Gradle
compile 'org.hyperledger.fabric-sdk-java:fabric-sdk-java:0.6'
This jar is available on m2 central repository so no problem J
6. Click on the red cross of the class, and click on Add unimplemented
methods. Now you can do a maven compile or gradle compileJava.
Both should compile fine.
20. Getting Started With Hyperledger Fabric (Blockchain)
Page 20 of 51
To do so, open Run Configurations…
For Maven
21. Getting Started With Hyperledger Fabric (Blockchain)
Page 21 of 51
For Gradle
Now your project should not have any red errors. Compilation is done
22. Getting Started With Hyperledger Fabric (Blockchain)
Page 22 of 51
1. Implementing overridden methods
Eclipse TIP: To auto-indent files, go to top menu Source > Format
(Shift+Ctrl+F)
1. First step is to start a main thread and name your chaincode. Edit it as
follow:
private static Log log =LogFactory.getLog(JavaCDD.class);
public static void main(String[] args) throws Exception {
new JavaCDD().start(args);
}
@Override
public String getChaincodeID() {
return "JavaCDD";
}
2. Start coding the entry point method run. It is the dispatcher entry point
for INVOKE and DEPLOY API.
init function is used while deployment only and all others for normal
invocations.
@Override
/**
* Entry point of invocation interaction
*
* @param stub
* @param function
* @param args
*/
public String run(ChaincodeStub stub, String function, String[] args) {
log.info("In run, function:" + function);
switch (function) {
case "init":
init(stub, function, args);
break;
case "executeContract":
String re = executeContract(stub, args);
log.info("Return of executeContract : " + re);
return re;
default:
String warnMessage = "{"Error":"Error function " +
function + " not found"}";
log.warn(warnMessage);
return warnMessage;
23. Getting Started With Hyperledger Fabric (Blockchain)
Page 23 of 51
}
return null;
}
3. Last overridden method is query. We will have to retrieve the contract
state and return it back to the client. Do it as below
/**
* This function can query the current State of the contract
* @param stub
* @param function
* @param args
* client name
* @return total amount received for this client
*/
@Override
public String query(ChaincodeStub stub, String function, String[] args)
{
if (args.length != 1) {
return "{"Error":"Incorrect number of arguments.
Expecting name of the client to query"}";
}
String clientName = stub.getState(args[0]);
log.info("Called " + function + " on client : " + clientName);
if (clientName != null && !clientName.isEmpty()) {
try {
ObjectMapper mapper = new ObjectMapper();
ContractRecord contractRecord =
mapper.readValue(clientName, ContractRecord.class);
return "" + contractRecord.totalAmountReceived;
} catch (Exception e) {
return "{"Error":"Failed to parse state for client "
+ args[0] + " : " + e.getMessage() + ""}";
}
} else {
return "{"Error":"Failed to get state for client " + args[0]
+ ""}";
}
}
24. Getting Started With Hyperledger Fabric (Blockchain)
Page 24 of 51
2. Implementing initialization and invocation methods
1. At deployment we will need to initialize the contract. Copy the code
below
/**
* This function initializes the contract
* @param stub
* @param function
* @param args
* client name, temperature threshold, amount received when
* contract is activated
* @return
*/
public String init(ChaincodeStub stub, String function, String[] args) {
if (args.length != 3) {
return "{"Error":"Incorrect number of arguments.
Expecting 3 : client name, temperature threshold, amount received
when contract is activated "}";
}
try {
ContractRecord contractRecord = new
ContractRecord(args[0],
Integer.parseInt(args[1]),Integer.parseInt(args[2]));
stub.putState(args[0], contractRecord.toString());
} catch (NumberFormatException e) {
return "{"Error":"Expecting integer value for
temperature threshold and amount received"}";
}
return null;
}
2. Then, here is the main piece. We are coding the contract for a specific
location passed as parameters. We have an API call to Weather API
that will return the current temperature and will compare it against the
threshold of the contract.
If the temperature is below, then the client will have its account
credited with the redemption agreement amount of the contract,
otherwise nothing happens.
(Credentials of the service API have been hardcoded, you can change this
value with your own credentials on Bluemix)
25. Getting Started With Hyperledger Fabric (Blockchain)
Page 25 of 51
/**
* This function calls Weather API to check if the temperature on a location
* is inferior to the contract's threshold. If yes, the client is redeemed
* for the value agreed on the contract
*
* @param stub
* @param args
* client name, postal Code, country Code
* @return
*/
public String executeContract(ChaincodeStub stub, String[] args) {
log.info("in executeContract");
Boolean contractExecuted = false;
if (args.length != 3) {
String errorMessage = "{"Error":"Incorrect number of
arguments. Expecting 3: client name, postal Code, country Code"}";
log.error(errorMessage);
return errorMessage;
}
ObjectMapper mapper = new ObjectMapper();
ContractRecord contractRecord;
try {
contractRecord = mapper.readValue(stub.getState(args[0]),
ContractRecord.class);
} catch (Exception e1) {
String errorMessage = "{"Error":" Problem retrieving state of
client contract : " + e1.getMessage()+ " "}";
log.error(errorMessage);
return errorMessage;
}
String postalCode = args[1];
String countryCode = args[2];
// weather service
String url = "https://twcservice.mybluemix.net/api/weather/v1/location/"
+ postalCode + "%3A4%3A" + countryCode
+ "/observations.json?language=en-GB";
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
SSLSocketFactory sf;
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
26. Getting Started With Hyperledger Fabric (Blockchain)
Page 26 of 51
sslContext.init(null, null, null);
sf = new SSLSocketFactory(sslContext);
} catch (Exception e1) {
String errorMessage = "{"Error":" Problem with
SSLSocketFactory : " + e1.getMessage() + " "}";
log.error(errorMessage);
return errorMessage;
}
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME
_VERIFIER);
Scheme sch = new Scheme("https", sf, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
((AbstractHttpClient)
httpclient).getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT),
new UsernamePasswordCredentials("dfa7551a-
2613-4f5c-bff7-339649770aa5", "gvbmK5JsGO"));
HttpResponse response;
try {
response = httpclient.execute(httpget);
log.info("Called Weather service");
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity httpEntity = response.getEntity();
String responseString = EntityUtils.toString(httpEntity);
if (statusCode == HttpStatus.SC_OK) {
log.info("Weather service call OK");
WeatherObservationResponse
weatherObservationResponse =
mapper.readValue(responseString,WeatherObservationResponse.class);
if
(weatherObservationResponse.getObservation().getTemp() <
contractRecord.temperatureThreshold) {
// then please redeem the client
contractRecord.totalAmountReceived +=
contractRecord.amountReceivedWhenContractIsActivated;
27. Getting Started With Hyperledger Fabric (Blockchain)
Page 27 of 51
stub.putState(contractRecord.clientName,
contractRecord.toString());
log.info("Contract condition
valid " + weatherObservationResponse.getObservation().getTemp() + " < "
+
contractRecord.temperatureThreshold);
contractExecuted=true;
} else {
log.info("Contract condition invalid " +
weatherObservationResponse.getObservation().getTemp()+ " > " +
contractRecord.temperatureThreshold);
}
} else {
String errorMessage = "{"Error":"Problem while calling
Weather API : " + statusCode + " : "+ responseString + ""}";
log.error(errorMessage);
return errorMessage;
}
} catch (Exception e) {
String errorMessage = "{"Error":"Problem while calling
Weather API : " + e.getMessage() + ""}";
log.error(errorMessage);
try {
log.error(new
ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(e.getStac
kTrace()));
} catch (JsonProcessingException e2) {
e2.printStackTrace();
}
return errorMessage;
}
return contractExecuted.toString();
}
b) Deployment and testing
1. Local testing
We will use Mockito to mock the Blockchain and detect any problem in our
code before deploying it.
28. Getting Started With Hyperledger Fabric (Blockchain)
Page 28 of 51
For more info about mockito : http://site.mockito.org
3. On your project, go to folder /src/test/java. You will find a class named
JavaCDDTest
There are two Junit test cases on it.
Nice test case should always execute the contract but not increment
the client’s account
Fairbanks should increment (as it is very cold there!)
Logs and Eclipse debug mode should be enough for you to check if the
redeem amount has changed.
4. Launch the Junit tests. Right click on project or test file and click Run
as > JUnit Test or Debug as > JUnit Test
All tests should have passed green. Check then the logs, to see if
scenarios have run as expected. If you are not sure, run on debug
mode and add breakpoints to your code
2. Deployment
As your chaincode is running correctly locally with a mocked Blockchain, it is
time to deploy it on the real one.
To deploy a chaincode we will use the HTTP API with Postman
1. Open Postman and run DEPLOY V0.6
29. Getting Started With Hyperledger Fabric (Blockchain)
Page 29 of 51
(Optional)
Be sure that your Blockchain network is running (see Part 1)
Also check that your project name is corresponding to the mounted
path /chaincode/JavaCDD. Use docker to list files on mounted folder
(replace in red by your vp0 container id)
[Remember this path as you will need it in Part 3 too].
docker exec -i PEERVP0CONTAINERID /bin/bash
ls /chaincode
(Optional)
There is another way to deploy a chaincode using not a path by an
url, just replace the path value by the url.
You should have a 200 OK
In the returned Json, copy the value of result>message. It is the
unique identifier of your chaincode, you will need it for after
The deployment is asynchronous. Even if Hyperledger send you back
a correct response, it just means that your request was correct and
has been processed. To be sure that the new smart contract has been
started, go to a console and do a docker ps. If you see a container
name containing the chaincode ID of your request, it means the smart
contract is running. Speed depends on the performance of your
machine and the size of the code, it can take from 2s to few minutes
2. Call the query you coded to see if the default amount has been
initialized
30. Getting Started With Hyperledger Fabric (Blockchain)
Page 30 of 51
You should have a zero amount on the message returned
On the request body, do not forget to change
params>chaincodeID>name by the one returned on the previous
step
3. Interact more with your chaincode
1. Run INVOKE V0.6
31. Getting Started With Hyperledger Fabric (Blockchain)
Page 31 of 51
Do not forget to change the chaincodeID as step before, let the
default parameters pointing to Fairbanks and you should have a
response 200 OK.
For information, the data result>message on the response
corresponds to the transaction ID
Let’s call the query again to check the result
32. Getting Started With Hyperledger Fabric (Blockchain)
Page 32 of 51
You should have an amount with value 42 on the message returned.
This confirms that your farmer has been credited of 42$.
33. Getting Started With Hyperledger Fabric (Blockchain)
Page 33 of 51
Part 3 – Develop the client side application
a) Initialization
We will now use the Java SDK to interact with our blockchain instead of the HTTP
API. HTTP API will be deprecated on V1.0 of Hyperledger so we will need to use
GRPC channel to communicate with the network, it on what is based the SDK.
We want to use a real java client app to keep our wallet safe, so we choose to use a
simple spring boot project and build an API over it for testing (You could do it with
any other java application using JavaFx, Swing or whatever support the SDK which is
built on java 8)
1. Create a new maven Project in Eclipse named JavaCDDWeb
34. Getting Started With Hyperledger Fabric (Blockchain)
Page 34 of 51
Skip the archetype selection, use the default workspace location
35. Getting Started With Hyperledger Fabric (Blockchain)
Page 35 of 51
you can edit as above, but we will override it on the next step anyway
2. Edit pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ibm</groupId>
<artifactId>JavaCDDWeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>
<packaging>war</packaging>
<dependencies>
37. Getting Started With Hyperledger Fabric (Blockchain)
Page 37 of 51
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
This is the simplest configuration that we can have to have a REST API ready
You maybe have noticed that we have changed the SDK dependency. It is because,
we will need the last version of the Git branch 0.6 and it has not been released
officially yet on Maven Central.
3. Create a controller class named MyController on the package
com.ibm.controller
38. Getting Started With Hyperledger Fabric (Blockchain)
Page 38 of 51
Create new java package and a new class MyController
39. Getting Started With Hyperledger Fabric (Blockchain)
Page 39 of 51
4. Edit MyController.java
@RestController
@EnableAutoConfiguration
public class MyController {
private static Log logger =
40. Getting Started With Hyperledger Fabric (Blockchain)
Page 40 of 51
LogFactory.getLog(MyController.class);
private Member registrar;
private String chainCodeID;
private Chain chain;
public static void main(String[] args) throws Exception {
SpringApplication.run(MyController.class, args);
}
}
For the moment, you can run MyController as a Java Application but does nothing
more than starting a server and exposing the controller on http://localhost:8080
TIP: If you start Spring Boot application and you have the port 8080 already in use,
please kill the other process like this :
lsof -i tcp:8080
kill mypidijustfoundwiththepreviouscommand
TIP: If you have any problem with JRE, just check you are using JDK8 on your
project. Right click on your project, click on buildpath and see with JDK you are
using.
41. Getting Started With Hyperledger Fabric (Blockchain)
Page 41 of 51
It is not JDK 8, remove the library, then click on the right panel to add library
Then select JDK8 library and confirm
42. Getting Started With Hyperledger Fabric (Blockchain)
Page 42 of 51
Also sometimes Eclipse complains about JDK compliance, you can right click on
project, Prperties and filter “compliance”. You should have Java compiler compliance
>= 1.7
b) Deployment
1. Write the Constructor and deploy function
public MyController() throws Exception {
logger.info("In MyController constructor ...");
chain = new Chain("javacdd");
chain.setDeployWaitTime(60*5);
try {
chain.setMemberServicesUrl("grpc://localhost:7054",
null);
// create FileKeyValStore
Path path =
Paths.get(System.getProperty("user.home"),
"/test.properties");
if (Files.notExists(path))
Files.createFile(path);
43. Getting Started With Hyperledger Fabric (Blockchain)
Page 43 of 51
chain.setKeyValStore(new
FileKeyValStore(path.toString()));
chain.addPeer("grpc://localhost:7051", null);
registrar = chain.getMember("admin");
if (!registrar.isEnrolled()) {
registrar = chain.enroll("admin",
"Xurw3yU9zI0l");
}
logger.info("registrar is :" +
registrar.getName() + ",secret:" +
registrar.getEnrollmentSecret());
chain.setRegistrar(registrar);
chain.eventHubConnect("grpc://localhost:7053",
null);
chainCodeID = deploy();
} catch (CertificateException | IOException e) {
logger.error(e.getMessage(), e);
throw new Exception(e);
}
logger.info("Out MyController constructor.");
}
Chain object will represent the chaincode deployed.
We are configuring MemberServices url in order to register a user admin and get the
signing & encryption certificates that we will store in our local wallet saved under
test.properties file.
We are configuring the peer to whom we will discuss with
We are enrolling the user admin the first time to get the keys, but next time we will
retrieve it from the local wallet on the machine. Be careful in case you failed storing
the keys the first time because the CA will consider that the user has been enrolled
and we no more deliver the keys. You will need to clean all CA database so we
recommend to destroy the full network with docker-compose and redo a new one.
We are connecting to peer eventhub to catch all failures and success messages after
we call invocation methods. As the system is asynchronous, it is the only way to
know if the grpc call finally succeeded.
Finally, we are deploying our chaincode and get the chaincodeID back
44. Getting Started With Hyperledger Fabric (Blockchain)
Page 44 of 51
2. Write the deploy function now. Use your path setting from Part 2 for
the setChaincodePath (e.g. “workspace”,”JavaCDD”).
String deploy() throws ChainCodeException,
NoAvailableTCertException, CryptoException, IOException {
DeployRequest deployRequest = new DeployRequest();
ArrayList<String> args = new ArrayList<String>();
args.add("init");
args.add("farmer");
args.add("10");
args.add("42");
deployRequest.setArgs(args);
deployRequest.setChaincodePath(Paths.get(System.getProper
ty("user.home"), "git", "JavaCDD").toString());
deployRequest.setChaincodeLanguage(ChaincodeLanguage.JAVA
);
deployRequest.setChaincodeName(chain.getName());
ChainCodeResponse chainCodeResponse =
registrar.deploy(deployRequest);
return chainCodeResponse.getChainCodeID();
}
We are building a DeployRequest and the registrar is submitting it to the peer (the
SDK signing under the hood)
Finally we return the chaincodeID that needs to be used later
c) Queries
Let’s write our query to obtain the total redeemed amount of a client
@RequestMapping(method = RequestMethod.GET, path = "/query",
produces = { MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
String query(@RequestParam String clientName) throws
JsonProcessingException {
logger.info("Calling /query ...");
QueryRequest queryRequest = new QueryRequest();
ArrayList<String> args = new ArrayList<String>();
45. Getting Started With Hyperledger Fabric (Blockchain)
Page 45 of 51
args.add("query");
args.add(clientName);
queryRequest.setArgs(args);
queryRequest.setChaincodeLanguage(ChaincodeLanguage.JAVA)
;
queryRequest.setChaincodeID(chainCodeID);
try {
ChainCodeResponse chainCodeResponse =
registrar.query(queryRequest);
logger.info("End call /query.");
return new
ObjectMapper().writeValueAsString(chainCodeResponse);
} catch (ChainCodeException |
NoAvailableTCertException | CryptoException | IOException e) {
logger.error("Error", e);
return new
ObjectMapper().writeValueAsString(e);
}
}
We are exposing a GET API under /query and we need the client name on input. We
are building a QueryRequest object that will be submitted by the registrar, etc … the
response will be sent on the body of the message on JSON format
d) Invocations
Same as above but for the invocation function of the chaincode
@RequestMapping(method = RequestMethod.GET, path =
"/executeContract", produces = {
MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
String executeContract(@RequestParam String clientName,
@RequestParam String postalCode,
@RequestParam String countryCode) throws
JsonProcessingException {
logger.info("Calling /executeContract ...");
46. Getting Started With Hyperledger Fabric (Blockchain)
Page 46 of 51
InvokeRequest invokeRequest = new InvokeRequest();
ArrayList<String> args = new ArrayList<String>();
args.add("executeContract");
args.add(clientName);
args.add(postalCode);
args.add(countryCode);
invokeRequest.setArgs(args);
invokeRequest.setChaincodeLanguage(ChaincodeLanguage.JAVA
);
invokeRequest.setChaincodeID(chainCodeID);
invokeRequest.setChaincodeName(chain.getName());
try {
ChainCodeResponse chainCodeResponse =
registrar.invoke(invokeRequest);
logger.info("End call /executeContract.");
return new
ObjectMapper().writeValueAsString(chainCodeResponse);
} catch (ChainCodeException |
NoAvailableTCertException | CryptoException | IOException e) {
logger.error("Error", e);
return new
ObjectMapper().writeValueAsString(e);
}
}
We are exposing a GET API under /executeContract and we need the client name,
postal code and country code on input. We are building an InvokeRequest object
that will be submitted by the registrar, etc … the response will be sent on the body of
the message on JSON format
e) Testing it !
1. So you have now a client application that runs on a secured network.
Let’s do some modifications on the work done on Part1 to make it secure.
Remember the file /base/peer-unsecure-base.yaml, edit now this property:
- CORE_SECURITY_ENABLED=true
47. Getting Started With Hyperledger Fabric (Blockchain)
Page 47 of 51
Also, the peers will need to be authenticated on the network, not only the users, so for
each peer on the file four-peer-ca.yaml, add these new properties on the block
environment
For vp0:
- CORE_SECURITY_ENROLLID=test_vp0
- CORE_SECURITY_ENROLLSECRET=MwYpmSRjupbT
For vp1:
- CORE_SECURITY_ENROLLID=test_vp1
- CORE_SECURITY_ENROLLSECRET=5wgHK9qqYaPy
For vp2:
- CORE_SECURITY_ENROLLID=test_vp2
- CORE_SECURITY_ENROLLSECRET=vQelbRvja7cJ
For vp3:
- CORE_SECURITY_ENROLLID=test_vp3
- CORE_SECURITY_ENROLLSECRET=9LKqKH5peurL
2. Now that the network runs with security enabled, you will need to add
extra security jars to your JDK.
Download this zip, and extract it on the folder ${java.home}/jre/lib/security/
: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-
2133166.html
3. You will have to solve an issue due to official Hyperledger images. It
refers to a Docker javaenv image named hyperledger/fabric-
javaenv:latest .Sadly this image does not exist so here is the trick :
docker pull hyperledger/fabric-javaenv:x86_64-0.6.1-preview
docker tag hyperledger/fabric-javaenv:x86_64-0.6.1-preview
hyperledger/fabric-javaenv:latest
4. You will need to destroy your network and rebuild it with docker-
compose
docker-compose -f four-peer-ca.yaml down
docker-compose -f four-peer-ca.yaml up
5. Now you can start you Spring Boot Application
48. Getting Started With Hyperledger Fabric (Blockchain)
Page 48 of 51
6. Open again Postman and select QUERY CLIENT V0.6, click on SEND
You should have the API responding SUCCESS with message “0” if the client has
not been redeemed yet
49. Getting Started With Hyperledger Fabric (Blockchain)
Page 49 of 51
7. Now select INVOKE CLIENT V0.6, click on SEND
You should have the API responding SUCCESS
8. Try again QUERY CLIENT V0.6, click on SEND
You should have the API responding SUCCESS with message “42” because the
client has been redeemed
51. Getting Started With Hyperledger Fabric (Blockchain)
Page 51 of 51
CONGRATULATIONS !!!
You have successfully invoked your chaincode and
incremented the client account. You know can now:
• Change location parameters while invoking chaincode
• Change the code adding begin and end date validity
checks
• Plug another temperature feed from an external API
service or IoT device
• Make the code more deterministic !
Correction links here :
https://github.com/zamrokk/JavaCDDNetwork
https://github.com/zamrokk/JavaCDD
https://github.com/zamrokk/JavaCDDWeb