Skip to content

Commit

Permalink
Merge "Java shim/chaincode project reorg, separate java docker env"
Browse files Browse the repository at this point in the history
  • Loading branch information
ghaskins authored and Gerrit Code Review committed Aug 23, 2016
2 parents 061e064 + 97ed71f commit d4125d5
Show file tree
Hide file tree
Showing 31 changed files with 848 additions and 412 deletions.
24 changes: 20 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ SUBDIRS:=$(strip $(SUBDIRS))
BASEIMAGE_RELEASE = $(shell cat ./images/base/release)
BASEIMAGE_DEPS = $(shell git ls-files images/base scripts/provision)

JAVASHIM_DEPS = $(shell git ls-files core/chaincode/shim/java)
PROJECT_FILES = $(shell git ls-files)
IMAGES = base src ccenv peer membersrvc
IMAGES = base src ccenv peer membersrvc javaenv


all: peer membersrvc checks

Expand Down Expand Up @@ -135,9 +137,9 @@ build/docker/bin/%: build/image/src/.dummy $(PROJECT_FILES)
build/bin:
mkdir -p $@

# Both peer and peer-image depend on ccenv-image
build/bin/peer: build/image/ccenv/.dummy
build/image/peer/.dummy: build/image/ccenv/.dummy
# Both peer and peer-image depend on ccenv-image and javaenv-image (all docker env images it supports)
build/bin/peer: build/image/ccenv/.dummy build/image/javaenv/.dummy
build/image/peer/.dummy: build/image/ccenv/.dummy build/image/javaenv/.dummy
build/image/peer/.dummy: build/docker/bin/examples/events/block-listener/

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

# Special override for java-image
build/image/javaenv/.dummy: Makefile $(JAVASHIM_DEPS)
@echo "Building docker javaenv-image"
@mkdir -p $(@D)
@cat images/javaenv/Dockerfile.in > $(@D)/Dockerfile
# Following items are packed and sent to docker context while building image
# 1. Java shim layer source code
# 2. Proto files used to generate java classes
# 3. Gradle settings file
@git ls-files core/chaincode/shim/java | tar -jcT - > $(@D)/javashimsrc.tar.bz2
@git ls-files protos settings.gradle | tar -jcT - > $(@D)/protos.tar.bz2
docker build -t $(PROJECT_NAME)-javaenv:latest $(@D)
@touch $@

# Default rule for image creation
build/image/%/.dummy: build/image/src/.dummy build/docker/bin/%
$(eval TARGET = ${patsubst build/image/%/.dummy,%,${@}})
Expand Down
84 changes: 77 additions & 7 deletions bddtests/java_shim.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,32 @@
#
# @chaincodeImagesUpToDate use this if all scenarios chaincode images are up to date, and do NOT require building. BE SURE!!!

#
#Copyright DTCC 2016 All Rights Reserved.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
#


#@chaincodeImagesUpToDate
Feature: SimpleSample Java example

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

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

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

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

When I query chaincode "example2" function name "query" on "vp0":
When I query chaincode "SimpleSample" function name "query" on "vp0":
|arg1|
| b |
Then I should get a JSON response with "result.message" = "{'Name':'b','Amount':'210'}"

Scenario: java RangeExample chaincode single peer
Given we compose "docker-compose-1.yml"
When requesting "/chain" from "vp0"
Then I should get a JSON response with "height" = "1"
When I deploy lang chaincode "examples/chaincode/java/RangeExample" of "JAVA" with ctor "init" to "vp0"
||
||
Then I should have received a chaincode name
Then I wait up to "300" seconds for transaction to be committed to all peers

When requesting "/chain" from "vp0"
Then I should get a JSON response with "height" = "2"

When I invoke chaincode "RangeExample" function name "put" on "vp0"
|arg1|arg2|
| a | alice |
Then I should have received a transactionID
Then I wait up to "25" seconds for transaction to be committed to all peers

When requesting "/chain" from "vp0"
Then I should get a JSON response with "height" = "3"

When I invoke chaincode "RangeExample" function name "put" on "vp0"
|arg1|arg2|
| b | bob |
Then I should have received a transactionID
Then I wait up to "25" seconds for transaction to be committed to all peers


When I query chaincode "RangeExample" function name "get" on "vp0":
|arg1|
| a |
Then I should get a JSON response with "result.message" = "alice"

When I query chaincode "RangeExample" function name "get" on "vp0":
|arg1|
| b |
Then I should get a JSON response with "result.message" = "bob"


When I query chaincode "RangeExample" function name "keys" on "vp0":
||
||
Then I should get a JSON response with "result.message" = "[a, b]"
When I invoke chaincode "RangeExample" function name "del" on "vp0"
|arg1|
| b |
Then I should have received a transactionID
Then I wait up to "25" seconds for transaction to be committed to all peers
When I query chaincode "RangeExample" function name "keys" on "vp0":
||
||
Then I should get a JSON response with "result.message" = "[a]"
9 changes: 6 additions & 3 deletions core/chaincode/chaincode_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,13 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cID *pb.ChaincodeID, cLa
case pb.ChaincodeSpec_JAVA:
//TODO add security args
args = strings.Split(
fmt.Sprintf("/usr/bin/gradle run -p /root -PappArgs=[\"-a\",\"%s\",\"-i\",\"%s\"]"+
" -x processResources -x classes", chaincodeSupport.peerAddress, cID.Name),
fmt.Sprintf("/root/Chaincode/bin/runChaincode -a %s -i %s",
chaincodeSupport.peerAddress, cID.Name),
" ")
chaincodeLogger.Debugf("Executable is gradle run on chaincode ID %s", cID.Name)
if chaincodeSupport.peerTLS {
args = append(args, " -s")
}
chaincodeLogger.Debugf("Executable is %s", args[0])
default:
return nil, nil, fmt.Errorf("Unknown chaincodeType: %s", cLang)
}
Expand Down
22 changes: 16 additions & 6 deletions core/chaincode/platforms/java/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"strings"
"time"

"github.com/spf13/viper"

cutil "github.com/hyperledger/fabric/core/container/util"
pb "github.com/hyperledger/fabric/protos"
"github.com/spf13/viper"
)

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

var newRunLine string
var dockerFileContents string
var buf []string

if viper.GetBool("security.enabled") {
//todo
} else {
newRunLine = fmt.Sprintf("COPY %s /root/\n"+
"RUN cd /root/ && gradle build", urlLocation)
buf = append(buf, viper.GetString("chaincode.java.Dockerfile"))
buf = append(buf, "COPY src /root")
buf = append(buf, "RUN gradle -b build.gradle build")
buf = append(buf, "RUN unzip -od /root build/distributions/Chaincode.zip")

}
dockerFileContents = strings.Join(buf, "\n")

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

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

return nil
}
2 changes: 1 addition & 1 deletion core/chaincode/platforms/java/test/java_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestJava_BuildImage(t *testing.T) {
return
}

chaincodePath := "../../../shim/java"
chaincodePath := "../../../../../examples/chaincode/java/SimpleSample"
//TODO find a better way to launch example java chaincode
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_JAVA, ChaincodeID: &pb.ChaincodeID{Path: chaincodePath}, CtorMsg: &pb.ChaincodeInput{Args: shim.ToChaincodeArgs("f")}}
if _, err := vm.BuildChaincodeContainer(spec); err != nil {
Expand Down
31 changes: 21 additions & 10 deletions core/chaincode/shim/java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,15 @@ buildscript {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.6'
}
}

plugins {
id "java"
id "com.google.protobuf" version "0.7.6"
id "eclipse"
id "application"
}
archivesBaseName = 'chaincode'
version = '1.0'

mainClassName = "example.SimpleSample"

run {
if (project.hasProperty("appArgs")) {
args = Eval.me(appArgs)
}
}

sourceSets {
main {
Expand Down Expand Up @@ -82,8 +76,25 @@ protobuf {
}
}

task copyToLib(type: Copy) {
into "$buildDir/libs"
from configurations.runtime
}


task copyProtos(type:Copy){
into "${projectDir}/src/main/proto"
from "${rootDir}/protos"
include '**/chaincodeevent.proto'
include '**/chaincode.proto'
}

tasks['build'].mustRunAfter tasks['copyProtos']
build.dependsOn(copyProtos)
build.finalizedBy(copyToLib)

dependencies {
compile 'com.google.protobuf:protobuf-java:3.0.0-beta-2'
compile 'com.google.protobuf:protobuf-java:3.0.0-beta-2'
compile 'io.grpc:grpc-all:0.13.2'
compile 'commons-cli:commons-cli:1.3.1'
}
24 changes: 24 additions & 0 deletions core/chaincode/shim/java/javabuild.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

#
#Copyright DTCC 2016 All Rights Reserved.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
#
set -e
PARENTDIR=$(pwd)


gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle clean
gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle build
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.SslContext;
import protos.Chaincode.ChaincodeID;
import protos.Chaincode.ChaincodeMessage;
import protos.Chaincode.ChaincodeMessage.Type;
import protos.ChaincodeSupportGrpc;
import protos.ChaincodeSupportGrpc.ChaincodeSupportStub;
import org.hyperledger.protos.Chaincode.ChaincodeID;
import org.hyperledger.protos.Chaincode.ChaincodeMessage;
import org.hyperledger.protos.Chaincode.ChaincodeMessage.Type;
import org.hyperledger.protos.ChaincodeSupportGrpc;
import org.hyperledger.protos.ChaincodeSupportGrpc.ChaincodeSupportStub;

public abstract class ChaincodeBase {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
package org.hyperledger.java.shim;

import com.google.protobuf.ByteString;
import org.hyperledger.protos.Chaincode;
import java.util.HashMap;
import java.util.Map;


import java.util.List;

Expand Down Expand Up @@ -65,20 +69,34 @@ public void delState(String key) {
}

/**
*
* Given a start key and end key, this method returns a map of items with value converted to UTF-8 string.
* @param startKey
* @param endKey
* @param limit
* @return
*/
// public HashMap<String, String> rangeQueryState(String startKey, String endKey, int limit) {
// HashMap<String, String> map = new HashMap<>();
// for (RangeQueryStateKeyValue mapping : handler.handleRangeQueryState(
// startKey, endKey, limit, uuid).getKeysAndValuesList()) {
// map.put(mapping.getKey(), mapping.getValue().toStringUtf8());
// }
// return map;
// }
public Map<String, String> rangeQueryState(String startKey, String endKey) {
Map<String, String> retMap = new HashMap<>();
for (Map.Entry<String, ByteString> item: rangeQueryRawState(startKey, endKey).entrySet()) {
retMap.put(item.getKey(), item.getValue().toStringUtf8());
}
return retMap;
}

/**
* This method is same as rangeQueryState, except it returns value in ByteString, useful in cases where
* serialized object can be retrieved.
* @param startKey
* @param endKey
* @return
*/
public Map<String, ByteString> rangeQueryRawState(String startKey, String endKey) {
Map<String, ByteString> map = new HashMap<>();
for (Chaincode.RangeQueryStateKeyValue mapping : handler.handleRangeQueryState(
startKey, endKey, uuid).getKeysAndValuesList()) {
map.put(mapping.getKey(), mapping.getValue());
}
return map;
}

/**
*
Expand Down
Loading

0 comments on commit d4125d5

Please sign in to comment.