Skip to content

Commit 97ed71f

Browse files
committed
Java shim/chaincode project reorg, separate java docker env
Fixes the following issues #2146 #2139 1. Separate java docker image 2. Added java package info to proto files 3. Removed duplicate .proto files checked into java shim project, and copy it as part of build process 4. Modified java unit test to refer to new path 5. Updated JAVAChaincode documentation to reflect new changes and added instructions for developing new chaincode 6. Split java chaincode examples from java shim project Change-Id: I7cbe92449c30700f17949b03f8fc7c06e0c7efb6 Signed-off-by: Satheesh Kathamuthu <[email protected]>
1 parent 8ec1147 commit 97ed71f

File tree

31 files changed

+848
-412
lines changed

31 files changed

+848
-412
lines changed

Makefile

+20-4
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ SUBDIRS:=$(strip $(SUBDIRS))
5454
BASEIMAGE_RELEASE = $(shell cat ./images/base/release)
5555
BASEIMAGE_DEPS = $(shell git ls-files images/base scripts/provision)
5656

57+
JAVASHIM_DEPS = $(shell git ls-files core/chaincode/shim/java)
5758
PROJECT_FILES = $(shell git ls-files)
58-
IMAGES = base src ccenv peer membersrvc
59+
IMAGES = base src ccenv peer membersrvc javaenv
60+
5961

6062
all: peer membersrvc checks
6163

@@ -135,9 +137,9 @@ build/docker/bin/%: build/image/src/.dummy $(PROJECT_FILES)
135137
build/bin:
136138
mkdir -p $@
137139

138-
# Both peer and peer-image depend on ccenv-image
139-
build/bin/peer: build/image/ccenv/.dummy
140-
build/image/peer/.dummy: build/image/ccenv/.dummy
140+
# Both peer and peer-image depend on ccenv-image and javaenv-image (all docker env images it supports)
141+
build/bin/peer: build/image/ccenv/.dummy build/image/javaenv/.dummy
142+
build/image/peer/.dummy: build/image/ccenv/.dummy build/image/javaenv/.dummy
141143
build/image/peer/.dummy: build/docker/bin/examples/events/block-listener/
142144

143145
build/bin/%: build/image/base/.dummy $(PROJECT_FILES)
@@ -170,6 +172,20 @@ build/image/ccenv/.dummy: build/image/src/.dummy build/image/ccenv/bin/protoc-ge
170172
docker build -t $(PROJECT_NAME)-ccenv:latest $(@D)
171173
@touch $@
172174

175+
# Special override for java-image
176+
build/image/javaenv/.dummy: Makefile $(JAVASHIM_DEPS)
177+
@echo "Building docker javaenv-image"
178+
@mkdir -p $(@D)
179+
@cat images/javaenv/Dockerfile.in > $(@D)/Dockerfile
180+
# Following items are packed and sent to docker context while building image
181+
# 1. Java shim layer source code
182+
# 2. Proto files used to generate java classes
183+
# 3. Gradle settings file
184+
@git ls-files core/chaincode/shim/java | tar -jcT - > $(@D)/javashimsrc.tar.bz2
185+
@git ls-files protos settings.gradle | tar -jcT - > $(@D)/protos.tar.bz2
186+
docker build -t $(PROJECT_NAME)-javaenv:latest $(@D)
187+
@touch $@
188+
173189
# Default rule for image creation
174190
build/image/%/.dummy: build/image/src/.dummy build/docker/bin/%
175191
$(eval TARGET = ${patsubst build/image/%/.dummy,%,${@}})

bddtests/java_shim.feature

+77-7
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,32 @@
66
#
77
# @chaincodeImagesUpToDate use this if all scenarios chaincode images are up to date, and do NOT require building. BE SURE!!!
88

9+
#
10+
#Copyright DTCC 2016 All Rights Reserved.
11+
#
12+
#Licensed under the Apache License, Version 2.0 (the "License");
13+
#you may not use this file except in compliance with the License.
14+
#You may obtain a copy of the License at
15+
#
16+
# http://www.apache.org/licenses/LICENSE-2.0
17+
#
18+
#Unless required by applicable law or agreed to in writing, software
19+
#distributed under the License is distributed on an "AS IS" BASIS,
20+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21+
#See the License for the specific language governing permissions and
22+
#limitations under the License.
23+
#
24+
#
25+
26+
927
#@chaincodeImagesUpToDate
1028
Feature: SimpleSample Java example
1129

12-
#@doNotDecompose
13-
# @wip
1430
Scenario: java SimpleSample chaincode example single peer
1531
Given we compose "docker-compose-1.yml"
1632
When requesting "/chain" from "vp0"
1733
Then I should get a JSON response with "height" = "1"
18-
When I deploy lang chaincode "core/chaincode/shim/java" of "JAVA" with ctor "init" to "vp0"
34+
When I deploy lang chaincode "examples/chaincode/java/SimpleSample" of "JAVA" with ctor "init" to "vp0"
1935
| arg1 | arg2 | arg3 | arg4 |
2036
| a | 100 | b | 200 |
2137
Then I should have received a chaincode name
@@ -24,12 +40,12 @@ Feature: SimpleSample Java example
2440
When requesting "/chain" from "vp0"
2541
Then I should get a JSON response with "height" = "2"
2642

27-
When I query chaincode "example2" function name "query" on "vp0":
43+
When I query chaincode "SimpleSample" function name "query" on "vp0":
2844
|arg1|
2945
| a |
3046
Then I should get a JSON response with "result.message" = "{'Name':'a','Amount':'100'}"
3147

32-
When I invoke chaincode "example2" function name "transfer" on "vp0"
48+
When I invoke chaincode "SimpleSample" function name "transfer" on "vp0"
3349
|arg1|arg2|arg3|
3450
| a | b | 10 |
3551
Then I should have received a transactionID
@@ -38,12 +54,66 @@ Feature: SimpleSample Java example
3854
When requesting "/chain" from "vp0"
3955
Then I should get a JSON response with "height" = "3"
4056

41-
When I query chaincode "example2" function name "query" on "vp0":
57+
When I query chaincode "SimpleSample" function name "query" on "vp0":
4258
|arg1|
4359
| a |
4460
Then I should get a JSON response with "result.message" = "{'Name':'a','Amount':'90'}"
4561

46-
When I query chaincode "example2" function name "query" on "vp0":
62+
When I query chaincode "SimpleSample" function name "query" on "vp0":
4763
|arg1|
4864
| b |
4965
Then I should get a JSON response with "result.message" = "{'Name':'b','Amount':'210'}"
66+
67+
Scenario: java RangeExample chaincode single peer
68+
Given we compose "docker-compose-1.yml"
69+
When requesting "/chain" from "vp0"
70+
Then I should get a JSON response with "height" = "1"
71+
When I deploy lang chaincode "examples/chaincode/java/RangeExample" of "JAVA" with ctor "init" to "vp0"
72+
||
73+
||
74+
Then I should have received a chaincode name
75+
Then I wait up to "300" seconds for transaction to be committed to all peers
76+
77+
When requesting "/chain" from "vp0"
78+
Then I should get a JSON response with "height" = "2"
79+
80+
When I invoke chaincode "RangeExample" function name "put" on "vp0"
81+
|arg1|arg2|
82+
| a | alice |
83+
Then I should have received a transactionID
84+
Then I wait up to "25" seconds for transaction to be committed to all peers
85+
86+
When requesting "/chain" from "vp0"
87+
Then I should get a JSON response with "height" = "3"
88+
89+
When I invoke chaincode "RangeExample" function name "put" on "vp0"
90+
|arg1|arg2|
91+
| b | bob |
92+
Then I should have received a transactionID
93+
Then I wait up to "25" seconds for transaction to be committed to all peers
94+
95+
96+
When I query chaincode "RangeExample" function name "get" on "vp0":
97+
|arg1|
98+
| a |
99+
Then I should get a JSON response with "result.message" = "alice"
100+
101+
When I query chaincode "RangeExample" function name "get" on "vp0":
102+
|arg1|
103+
| b |
104+
Then I should get a JSON response with "result.message" = "bob"
105+
106+
107+
When I query chaincode "RangeExample" function name "keys" on "vp0":
108+
||
109+
||
110+
Then I should get a JSON response with "result.message" = "[a, b]"
111+
When I invoke chaincode "RangeExample" function name "del" on "vp0"
112+
|arg1|
113+
| b |
114+
Then I should have received a transactionID
115+
Then I wait up to "25" seconds for transaction to be committed to all peers
116+
When I query chaincode "RangeExample" function name "keys" on "vp0":
117+
||
118+
||
119+
Then I should get a JSON response with "result.message" = "[a]"

core/chaincode/chaincode_support.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,13 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cID *pb.ChaincodeID, cLa
298298
case pb.ChaincodeSpec_JAVA:
299299
//TODO add security args
300300
args = strings.Split(
301-
fmt.Sprintf("/usr/bin/gradle run -p /root -PappArgs=[\"-a\",\"%s\",\"-i\",\"%s\"]"+
302-
" -x processResources -x classes", chaincodeSupport.peerAddress, cID.Name),
301+
fmt.Sprintf("/root/Chaincode/bin/runChaincode -a %s -i %s",
302+
chaincodeSupport.peerAddress, cID.Name),
303303
" ")
304-
chaincodeLogger.Debugf("Executable is gradle run on chaincode ID %s", cID.Name)
304+
if chaincodeSupport.peerTLS {
305+
args = append(args, " -s")
306+
}
307+
chaincodeLogger.Debugf("Executable is %s", args[0])
305308
default:
306309
return nil, nil, fmt.Errorf("Unknown chaincodeType: %s", cLang)
307310
}

core/chaincode/platforms/java/package.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
"strings"
77
"time"
88

9-
"github.com/spf13/viper"
10-
9+
cutil "github.com/hyperledger/fabric/core/container/util"
1110
pb "github.com/hyperledger/fabric/protos"
11+
"github.com/spf13/viper"
1212
)
1313

1414
//tw is expected to have the chaincode in it from GenerateHashcode.
@@ -38,20 +38,30 @@ func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error {
3838
}
3939
urlLocation = urlLocation[strings.LastIndex(urlLocation, "/")+1:]
4040

41-
var newRunLine string
41+
var dockerFileContents string
42+
var buf []string
43+
4244
if viper.GetBool("security.enabled") {
4345
//todo
4446
} else {
45-
newRunLine = fmt.Sprintf("COPY %s /root/\n"+
46-
"RUN cd /root/ && gradle build", urlLocation)
47+
buf = append(buf, viper.GetString("chaincode.java.Dockerfile"))
48+
buf = append(buf, "COPY src /root")
49+
buf = append(buf, "RUN gradle -b build.gradle build")
50+
buf = append(buf, "RUN unzip -od /root build/distributions/Chaincode.zip")
51+
4752
}
53+
dockerFileContents = strings.Join(buf, "\n")
4854

49-
dockerFileContents := fmt.Sprintf("%s\n%s", viper.GetString("chaincode.java.Dockerfile"), newRunLine)
5055
dockerFileSize := int64(len([]byte(dockerFileContents)))
5156

5257
//Make headers identical by using zero time
5358
var zeroTime time.Time
5459
tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime})
5560
tw.Write([]byte(dockerFileContents))
61+
err := cutil.WriteJavaProjectToPackage(tw, spec.ChaincodeID.Path)
62+
if err != nil {
63+
return fmt.Errorf("Error writing Chaincode package contents: %s", err)
64+
}
65+
5666
return nil
5767
}

core/chaincode/platforms/java/test/java_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestJava_BuildImage(t *testing.T) {
4040
return
4141
}
4242

43-
chaincodePath := "../../../shim/java"
43+
chaincodePath := "../../../../../examples/chaincode/java/SimpleSample"
4444
//TODO find a better way to launch example java chaincode
4545
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_JAVA, ChaincodeID: &pb.ChaincodeID{Path: chaincodePath}, CtorMsg: &pb.ChaincodeInput{Args: shim.ToChaincodeArgs("f")}}
4646
if _, err := vm.BuildChaincodeContainer(spec); err != nil {

core/chaincode/shim/java/build.gradle

+21-10
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,15 @@ buildscript {
2424
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.6'
2525
}
2626
}
27-
27+
2828
plugins {
2929
id "java"
3030
id "com.google.protobuf" version "0.7.6"
3131
id "eclipse"
32-
id "application"
3332
}
33+
archivesBaseName = 'chaincode'
34+
version = '1.0'
3435

35-
mainClassName = "example.SimpleSample"
36-
37-
run {
38-
if (project.hasProperty("appArgs")) {
39-
args = Eval.me(appArgs)
40-
}
41-
}
4236

4337
sourceSets {
4438
main {
@@ -82,8 +76,25 @@ protobuf {
8276
}
8377
}
8478

79+
task copyToLib(type: Copy) {
80+
into "$buildDir/libs"
81+
from configurations.runtime
82+
}
83+
84+
85+
task copyProtos(type:Copy){
86+
into "${projectDir}/src/main/proto"
87+
from "${rootDir}/protos"
88+
include '**/chaincodeevent.proto'
89+
include '**/chaincode.proto'
90+
}
91+
92+
tasks['build'].mustRunAfter tasks['copyProtos']
93+
build.dependsOn(copyProtos)
94+
build.finalizedBy(copyToLib)
95+
8596
dependencies {
86-
compile 'com.google.protobuf:protobuf-java:3.0.0-beta-2'
97+
compile 'com.google.protobuf:protobuf-java:3.0.0-beta-2'
8798
compile 'io.grpc:grpc-all:0.13.2'
8899
compile 'commons-cli:commons-cli:1.3.1'
89100
}

core/chaincode/shim/java/javabuild.sh

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
#
4+
#Copyright DTCC 2016 All Rights Reserved.
5+
#
6+
#Licensed under the Apache License, Version 2.0 (the "License");
7+
#you may not use this file except in compliance with the License.
8+
#You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
#Unless required by applicable law or agreed to in writing, software
13+
#distributed under the License is distributed on an "AS IS" BASIS,
14+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
#See the License for the specific language governing permissions and
16+
#limitations under the License.
17+
#
18+
#
19+
set -e
20+
PARENTDIR=$(pwd)
21+
22+
23+
gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle clean
24+
gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle build

core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeBase.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@
3535
import io.grpc.netty.NettyChannelBuilder;
3636
import io.grpc.stub.StreamObserver;
3737
import io.netty.handler.ssl.SslContext;
38-
import protos.Chaincode.ChaincodeID;
39-
import protos.Chaincode.ChaincodeMessage;
40-
import protos.Chaincode.ChaincodeMessage.Type;
41-
import protos.ChaincodeSupportGrpc;
42-
import protos.ChaincodeSupportGrpc.ChaincodeSupportStub;
38+
import org.hyperledger.protos.Chaincode.ChaincodeID;
39+
import org.hyperledger.protos.Chaincode.ChaincodeMessage;
40+
import org.hyperledger.protos.Chaincode.ChaincodeMessage.Type;
41+
import org.hyperledger.protos.ChaincodeSupportGrpc;
42+
import org.hyperledger.protos.ChaincodeSupportGrpc.ChaincodeSupportStub;
4343

4444
public abstract class ChaincodeBase {
4545

core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeStub.java

+28-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
package org.hyperledger.java.shim;
1818

1919
import com.google.protobuf.ByteString;
20+
import org.hyperledger.protos.Chaincode;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
2024

2125
import java.util.List;
2226

@@ -65,20 +69,34 @@ public void delState(String key) {
6569
}
6670

6771
/**
68-
*
72+
* Given a start key and end key, this method returns a map of items with value converted to UTF-8 string.
6973
* @param startKey
7074
* @param endKey
71-
* @param limit
7275
* @return
7376
*/
74-
// public HashMap<String, String> rangeQueryState(String startKey, String endKey, int limit) {
75-
// HashMap<String, String> map = new HashMap<>();
76-
// for (RangeQueryStateKeyValue mapping : handler.handleRangeQueryState(
77-
// startKey, endKey, limit, uuid).getKeysAndValuesList()) {
78-
// map.put(mapping.getKey(), mapping.getValue().toStringUtf8());
79-
// }
80-
// return map;
81-
// }
77+
public Map<String, String> rangeQueryState(String startKey, String endKey) {
78+
Map<String, String> retMap = new HashMap<>();
79+
for (Map.Entry<String, ByteString> item: rangeQueryRawState(startKey, endKey).entrySet()) {
80+
retMap.put(item.getKey(), item.getValue().toStringUtf8());
81+
}
82+
return retMap;
83+
}
84+
85+
/**
86+
* This method is same as rangeQueryState, except it returns value in ByteString, useful in cases where
87+
* serialized object can be retrieved.
88+
* @param startKey
89+
* @param endKey
90+
* @return
91+
*/
92+
public Map<String, ByteString> rangeQueryRawState(String startKey, String endKey) {
93+
Map<String, ByteString> map = new HashMap<>();
94+
for (Chaincode.RangeQueryStateKeyValue mapping : handler.handleRangeQueryState(
95+
startKey, endKey, uuid).getKeysAndValuesList()) {
96+
map.put(mapping.getKey(), mapping.getValue());
97+
}
98+
return map;
99+
}
82100

83101
/**
84102
*

0 commit comments

Comments
 (0)