Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 8796095

Browse files
committed
FABN-887 NodeSDK - deploy Java chaincode
Allow for the install and instantiation of Java chaincode. Change-Id: I25082c6f4a6241dc5b1eb8e5980eaea2fbc1735f Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
1 parent f013164 commit 8796095

File tree

19 files changed

+776
-18
lines changed

19 files changed

+776
-18
lines changed

build/tasks/test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ gulp.task('run-full', ['clean-up', 'lint', 'pre-test', 'compile', 'docker-ready'
203203
'test/integration/invoke.js',
204204
'test/integration/network-config.js',
205205
'test/integration/only-admin.js',
206+
'test/integration/javachaincode/e2e.js',
206207
'test/integration/discovery.js',
207208
'test/integration/grpc.js',
208209
// channel: mychannelts chaincode: examplets:v1
@@ -249,6 +250,7 @@ function shouldRunPKCS11Tests(tests) {
249250
if (os.arch().match(/(x64|x86)/) === null ||
250251
!(typeof process.env.PKCS11_TESTS === 'string' && process.env.PKCS11_TESTS.toLowerCase() == 'true')) {
251252
tests.push('!test/unit/pkcs11.js');
253+
tests.push('!test/integration/javachaincode/e2e.js');
252254
}
253255

254256
return tests;

fabric-client/lib/Client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ const Client = class extends BaseClient {
917917
* where the chaincode source code resides.
918918
* @property {string} chaincodeType - Optional. Type of chaincode. One of
919919
* 'golang', 'car', 'node' or 'java'.
920-
* Default is 'golang'. Note that 'java' is not yet supported.
920+
* Default is 'golang'.
921921
* @property {string[] | string} channelNames - Optional. When no targets are
922922
* provided. The loaded network configuration will be searched for
923923
* suitable target peers. Peers that are defined in the channels named

fabric-client/lib/Packager.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
const Golang = require('./packager/Golang.js');
1818
const Car = require('./packager/Car.js');
1919
const Node = require('./packager/Node.js');
20+
const Java = require('./packager/Java.js');
2021
const utils = require('./utils.js');
2122

2223
const logger = utils.getLogger('packager');
@@ -59,6 +60,9 @@ module.exports.package = function(chaincodePath, chaincodeType, devmode, metadat
5960
case 'node':
6061
handler = new Node();
6162
break;
63+
case 'java':
64+
handler = new Java();
65+
break;
6266
default:
6367
handler = new Golang(['.go','.c','.h','.s']);
6468
}

fabric-client/lib/packager/Java.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
Copyright 2017, 2018 IBM All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
*/
7+
8+
'use strict';
9+
10+
const path = require('path');
11+
const sbuf = require('stream-buffers');
12+
const utils = require('../utils.js');
13+
const walk = require('ignore-walk');
14+
15+
const logger = utils.getLogger('JavaPackager.js');
16+
17+
const BasePackager = require('./BasePackager');
18+
19+
class JavaPackager extends BasePackager {
20+
21+
/**
22+
* Package chaincode source and metadata files for deployment.
23+
* @param {string} chaincodePath The path to the top-level directory containing the source code.
24+
* @param {string} [metadataPath] The path to the top-level directory containing metadata descriptors
25+
* @returns {Promise.<byte[]>}
26+
*/
27+
async package (chaincodePath, metadataPath) {
28+
logger.debug('packaging Java source from %s', chaincodePath);
29+
30+
const buffer = new sbuf.WritableStreamBuffer();
31+
let descriptors = await this.findSource(chaincodePath);
32+
if (metadataPath){
33+
logger.debug('packaging metadata files from %s', metadataPath);
34+
35+
const metaDescriptors = await super.findMetadataDescriptors(metadataPath);
36+
descriptors = descriptors.concat(metaDescriptors);
37+
}
38+
await super.generateTarGz(descriptors, buffer);
39+
40+
return buffer.getContents();
41+
}
42+
43+
/**
44+
* Given an input 'filePath', recursively parse the filesystem for any files
45+
* that fit the criteria for being valid java chaincode source
46+
* note: currently all files found in the source path are included
47+
*
48+
* @param filePath
49+
* @returns {Promise}
50+
*/
51+
async findSource (filePath) {
52+
const descriptors = [];
53+
54+
const files = await walk({path: filePath, follow: true});
55+
if (files) {
56+
files.forEach((entry) => {
57+
const desc = {
58+
name: path.join('src', entry).split('\\').join('/'), // for windows style paths
59+
fqp: path.join(filePath, entry)
60+
};
61+
62+
logger.debug('adding descriptor entry', desc);
63+
descriptors.push(desc);
64+
});
65+
} else {
66+
logger.debug(' No files found at this path %s', filePath);
67+
}
68+
69+
return descriptors;
70+
}
71+
}
72+
73+
module.exports = JavaPackager;

scripts/check_license.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function filterExcludedFiles {
2626
| grep -v "\.pb\.go$" \
2727
| grep -v "\.yaml$" \
2828
| grep -v "\.json$" \
29+
| grep -v "\.gradle$" \
2930
| sort -u`
3031
}
3132

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
id 'com.github.johnrengelman.shadow' version '2.0.3'
3+
id 'java'
4+
}
5+
6+
group 'org.hyperledger.fabric'
7+
version '1.0-SNAPSHOT'
8+
9+
sourceCompatibility = 1.8
10+
11+
repositories {
12+
mavenLocal()
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
compile group: 'org.hyperledger.fabric', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT'
18+
testCompile group: 'junit', name: 'junit', version: '4.12'
19+
}
20+
21+
shadowJar {
22+
baseName = 'chaincode'
23+
version = null
24+
classifier = null
25+
26+
manifest {
27+
attributes 'Main-Class': 'org.hyperledger.fabric.example.SimpleChaincode'
28+
}
29+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'fabric-chaincode-example-gradle'
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
# Copyright IBM Corp. All Rights Reserved.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
8+
package org.hyperledger.fabric.example;
9+
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
import com.google.protobuf.ByteString;
14+
import io.netty.handler.ssl.OpenSsl;
15+
import org.apache.commons.logging.Log;
16+
import org.apache.commons.logging.LogFactory;
17+
import org.hyperledger.fabric.shim.ChaincodeBase;
18+
import org.hyperledger.fabric.shim.ChaincodeStub;
19+
20+
import static java.nio.charset.StandardCharsets.UTF_8;
21+
22+
public class SimpleChaincode extends ChaincodeBase {
23+
24+
private static Log _logger = LogFactory.getLog(SimpleChaincode.class);
25+
26+
@Override
27+
public Response init(ChaincodeStub stub) {
28+
try {
29+
_logger.info("Init java simple chaincode");
30+
String func = stub.getFunction();
31+
32+
if (!func.equals("init")) {
33+
return newErrorResponse("function other than init is not supported");
34+
}
35+
List<String> args = stub.getParameters();
36+
if (args.size() != 4) {
37+
newErrorResponse("Incorrect number of arguments. Expecting 4");
38+
}
39+
// Initialize the chaincode
40+
String account1Key = args.get(0);
41+
int account1Value = Integer.parseInt(args.get(1));
42+
String account2Key = args.get(2);
43+
int account2Value = Integer.parseInt(args.get(3));
44+
45+
_logger.info(String.format("account %s, value = %s; account %s, value %s", account1Key, account1Value, account2Key, account2Value));
46+
stub.putStringState(account1Key, args.get(1));
47+
stub.putStringState(account2Key, args.get(3));
48+
49+
return newSuccessResponse();
50+
} catch (Throwable e) {
51+
return newErrorResponse(e);
52+
}
53+
}
54+
55+
@Override
56+
public Response invoke(ChaincodeStub stub) {
57+
try {
58+
_logger.info("Invoke java simple chaincode");
59+
String func = stub.getFunction();
60+
List<String> params = stub.getParameters();
61+
if (func.equals("move")) {
62+
return move(stub, params);
63+
}
64+
if (func.equals("delete")) {
65+
return delete(stub, params);
66+
}
67+
if (func.equals("query")) {
68+
return query(stub, params);
69+
}
70+
if (func.equals("throwError")) {
71+
return newErrorResponse("throwError: an error occurred");
72+
}
73+
return newErrorResponse("Invalid invoke function name. Expecting one of: [\"move\", \"delete\", \"query\"] but found::" + func);
74+
} catch (Throwable e) {
75+
return newErrorResponse(e);
76+
}
77+
}
78+
79+
private Response move(ChaincodeStub stub, List<String> args) {
80+
if (args.size() != 3) {
81+
return newErrorResponse("Incorrect number of arguments. Expecting 3");
82+
}
83+
String accountFromKey = args.get(0);
84+
String accountToKey = args.get(1);
85+
86+
String accountFromValueStr = stub.getStringState(accountFromKey);
87+
if (accountFromValueStr == null) {
88+
return newErrorResponse(String.format("Entity %s not found", accountFromKey));
89+
}
90+
int accountFromValue = Integer.parseInt(accountFromValueStr);
91+
92+
String accountToValueStr = stub.getStringState(accountToKey);
93+
if (accountToValueStr == null) {
94+
return newErrorResponse(String.format("Entity %s not found", accountToKey));
95+
}
96+
int accountToValue = Integer.parseInt(accountToValueStr);
97+
98+
int amount = Integer.parseInt(args.get(2));
99+
100+
if (amount > accountFromValue) {
101+
return newErrorResponse(String.format("not enough money in account %s", accountFromKey));
102+
}
103+
104+
accountFromValue -= amount;
105+
accountToValue += amount;
106+
107+
_logger.info(String.format("new value of A: %s", accountFromValue));
108+
_logger.info(String.format("new value of B: %s", accountToValue));
109+
110+
stub.putStringState(accountFromKey, Integer.toString(accountFromValue));
111+
stub.putStringState(accountToKey, Integer.toString(accountToValue));
112+
113+
_logger.info("Transfer complete");
114+
115+
Map<String, byte[]> transientMap = stub.getTransient();
116+
if (null != transientMap) {
117+
if (transientMap.containsKey("event") && transientMap.get("event") != null) {
118+
stub.setEvent("event", transientMap.get("event"));
119+
}
120+
if (transientMap.containsKey("result") && transientMap.get("result") != null) {
121+
return newSuccessResponse(transientMap.get("result"));
122+
}
123+
}
124+
return newSuccessResponse("move succeed",ByteString.copyFrom("move succeed", UTF_8).toByteArray());
125+
}
126+
127+
// Deletes an entity from state
128+
private Response delete(ChaincodeStub stub, List<String> args) {
129+
if (args.size() != 1) {
130+
return newErrorResponse("Incorrect number of arguments. Expecting 1");
131+
}
132+
String key = args.get(0);
133+
// Delete the key from the state in ledger
134+
stub.delState(key);
135+
return newSuccessResponse();
136+
}
137+
138+
// query callback representing the query of a chaincode
139+
private Response query(ChaincodeStub stub, List<String> args) {
140+
if (args.size() != 1) {
141+
return newErrorResponse("Incorrect number of arguments. Expecting name of the person to query");
142+
}
143+
String key = args.get(0);
144+
//byte[] stateBytes
145+
String val = stub.getStringState(key);
146+
if (val == null) {
147+
return newErrorResponse(String.format("Error: state for %s is null", key));
148+
}
149+
_logger.info(String.format("Query Response:\nName: %s, Amount: %s\n", key, val));
150+
return newSuccessResponse(val, ByteString.copyFrom(val, UTF_8).toByteArray());
151+
}
152+
153+
public static void main(String[] args) {
154+
System.out.println("OpenSSL avaliable: " + OpenSsl.isAvailable());
155+
new SimpleChaincode().start(args);
156+
}
157+
158+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
id 'com.github.johnrengelman.shadow' version '2.0.3'
3+
id 'java'
4+
}
5+
6+
group 'org.hyperledger.fabric'
7+
version '1.0-SNAPSHOT'
8+
9+
sourceCompatibility = 1.8
10+
11+
repositories {
12+
mavenLocal()
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
compile group: 'org.hyperledger.fabric', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT'
18+
testCompile group: 'junit', name: 'junit', version: '4.12'
19+
}
20+
21+
shadowJar {
22+
baseName = 'chaincode'
23+
version = null
24+
classifier = null
25+
26+
manifest {
27+
attributes 'Main-Class': 'org.hyperledger.fabric.example.SimpleChaincode'
28+
}
29+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'fabric-chaincode-example-gradle'

0 commit comments

Comments
 (0)