Skip to content

Commit

Permalink
[FAB-3066] sync java/go chaincode interface
Browse files Browse the repository at this point in the history
ChaincodeBase:
 - removed run() method
 - implemented new Chaincode interface
 - added init(stub) method
 - added invoke(stub) method

ChaincodeStub:
 - added chaincode args to stub (like golang version)

Handler:
 - ChaincodeStub initialized with args
 - invoke calls Chaincode.invoke()
 - initialize call Chaincode.init()

Other:
 - edited chaincode docs
 - fixed example Java chaincodes

Change-Id: I04906052317c382b78884c00a85b80a12ed1bd9d
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Apr 14, 2017
1 parent 8eb16dc commit 8026601
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 153 deletions.
3 changes: 3 additions & 0 deletions core/chaincode/shim/java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
protos
src/main/proto
.classpath
20 changes: 19 additions & 1 deletion core/chaincode/shim/java/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright DTCC 2016 All Rights Reserved.
Copyright DTCC, IBM 2016, 2017 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.
Expand Down Expand Up @@ -106,6 +106,24 @@ task copyProtos(type:Copy){
into "${projectDir}/src/main/proto"
}

task copyProtosFromDevEnv(type:Copy){
into "peer", {
from ("../../../../protos/peer"){
include 'chaincode_event.proto'
include 'chaincode.proto'
include 'chaincode_shim.proto'
include 'proposal.proto'
include 'proposal_response.proto'
}
}
into "common", {
from ("../../../../protos/common"){
include 'common.proto'
}
}
into "${projectDir}/protos"
}

tasks['build'].mustRunAfter tasks['copyProtos']
build.dependsOn(copyProtos)
build.finalizedBy(copyToLib)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright IBM 2017 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.
package org.hyperledger.java.shim;

import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;

/**
* Defines methods that all chaincodes must implement.
*/
public interface Chaincode {
/**
* Called during an instantiate transaction after the container
* has been established, allowing the chaincode to initialize
* its internal data.
*/
public Response init(ChaincodeStub stub);
/**
* Called for every Invoke transaction. The chaincode may change
* its state variables.
*/
public Response invoke(ChaincodeStub stub);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,23 @@
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.SslContext;

public abstract class ChaincodeBase {

public abstract class ChaincodeBase implements Chaincode {

/* (non-Javadoc)
* @see org.hyperledger.java.shim.Chaincode#init(org.hyperledger.java.shim.ChaincodeStub)
*/
@Override
public abstract Response init(ChaincodeStub stub);

/* (non-Javadoc)
* @see org.hyperledger.java.shim.Chaincode#invoke(org.hyperledger.java.shim.ChaincodeStub)
*/
@Override
public abstract Response invoke(ChaincodeStub stub);

private static Log logger = LogFactory.getLog(ChaincodeBase.class);

public abstract Response run(ChaincodeStub stub, String function, String[] args);


public abstract String getChaincodeID();

public static final String DEFAULT_HOST = "127.0.0.1";
public static final int DEFAULT_PORT = 7051;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,43 @@

package org.hyperledger.java.shim;

import java.util.HashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperledger.fabric.protos.peer.ChaincodeShim;

import com.google.protobuf.ByteString;

//import static org.hyperledger.protos.TableProto.ColumnDefinition.Type.STRING;

public class ChaincodeStub {

private static Log logger = LogFactory.getLog(ChaincodeStub.class);

private final String uuid;
private final Handler handler;
private final List<ByteString> args;

public ChaincodeStub(String uuid, Handler handler) {
public ChaincodeStub(String uuid, Handler handler, List<ByteString> args) {
this.uuid = uuid;
this.handler = handler;
this.args = Collections.unmodifiableList(args);
}

public List<byte[]> getArgs() {
return args
.stream()
.map(x -> x.toByteArray())
.collect(Collectors.toList());
}

public List<String> getArgsAsStrings() {
return args
.stream()
.map(x -> x.toStringUtf8())
.collect(Collectors.toList());
}

/**
* Gets the UUID of this stub
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import static org.hyperledger.java.shim.HandlerHelper.newCompletedEventMessage;
import static org.hyperledger.java.shim.HandlerHelper.newErrorEventMessage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -208,15 +207,15 @@ public void handleInit(ChaincodeMessage message) {

// Get the function and args from Payload
final ChaincodeInput input = ChaincodeInput.parseFrom(message.getPayload());

// Mark as a transaction (allow put/del state)
markIsTransaction(message.getTxid(), true);

// Create the ChaincodeStub which the chaincode can use to callback
final ChaincodeStub stub = new ChaincodeStub(message.getTxid(), this);
final ChaincodeStub stub = new ChaincodeStub(message.getTxid(), this, input.getArgsList());

// Call chaincode's Run
final Response result = chaincode.run(stub, getFunction(input.getArgsList()), getParameters(input.getArgsList()));
final Response result = chaincode.init(stub);
logger.debug(String.format(String.format("[%s]Init succeeded. Sending %s", shortID(message), COMPLETED)));

if(result.getStatus() == Status.SUCCESS_VALUE) {
Expand Down Expand Up @@ -252,19 +251,6 @@ public void handleInit(ChaincodeMessage message) {
}).start();
}

private String getFunction(List<ByteString> args) {
return (args.size() > 0) ? args.get(0).toStringUtf8() : "";
}

private String[] getParameters(List<ByteString> args) {
final ArrayList<String> results = new ArrayList<>();
// skip arg[0], that is the function name
for(int i = 1; i < args.size(); i++) {
results.add(args.get(i).toStringUtf8());
}
return results.toArray(new String[results.size()]);
}

// enterInitState will initialize the chaincode if entering init from established.
public void beforeInit(Event event) {
logger.debug(String.format("Before %s event.", event.name));
Expand Down Expand Up @@ -305,12 +291,12 @@ public void handleTransaction(ChaincodeMessage message) {
markIsTransaction(message.getTxid(), true);

// Create the ChaincodeStub which the chaincode can use to callback
final ChaincodeStub stub = new ChaincodeStub(message.getTxid(), this);
final ChaincodeStub stub = new ChaincodeStub(message.getTxid(), this, input.getArgsList());

// Call chaincode's Run
Response response;
try {
response = chaincode.run(stub, getFunction(input.getArgsList()), getParameters(input.getArgsList()));
response = chaincode.invoke(stub);
} catch (Throwable throwable) {
// Send ERROR message to chaincode support and change state
logger.error(String.format("[%s]Error running chaincode. Transaction execution failed. Sending %s", shortID(message), ERROR));
Expand Down
24 changes: 14 additions & 10 deletions docs/source/Setup/JAVAChaincode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ To get started developing Java chaincode
2. Ensure you have the Java 1.8 **JDK** installed. Also ensure Java's
directory is on your path with ``java -version``

- Additionally, you will need to have the
```JAVA HOME`` <https://docs.oracle.com/cd/E19182-01/821-0917/6nluh6gq9/index.html>`__
variable set to your **JDK** installation in your system path
- Additionally, you will need to have the |JAVA_HOME|_ variable set to your
**JDK** installation in your system path

3. From your command line terminal, move to the ``devenv`` subdirectory
of your workspace environment. Log into a Vagrant terminal by
executing the following command:

.. |JAVA_HOME| replace:: ``JAVA_HOME``
.. _JAVA_HOME: https://docs.oracle.com/cd/E19182-01/821-0917/6nluh6gq9/index.html

::

vagrant ssh
Expand Down Expand Up @@ -163,13 +165,15 @@ Developing new JAVA chaincode
1. Create a new Java project structure.
2. Use existing ``build.grade`` from any example JAVA Chaincode project
like ``examples/chaincode/java/SimpleSample``.
3. Make your main class extend ChaincodeBase class and implement the
3. Make your main class extend ``ChaincodeBase`` class and implement the
following methods from base class.
4. ``public String run(ChaincodeStub stub, String function, String[] args)``
5. ``public String query(ChaincodeStub stub, String function, String[] args)``
6. ``public String getChaincodeID()``
7. Modify the ``mainClassName`` in ``build.gradle`` to point to your new

- ``public Response init(ChaincodeStub stub)``
- ``public Response invoke(ChaincodeStub stub);``
- ``public String getChaincodeID()``

4. Modify the ``mainClassName`` in ``build.gradle`` to point to your new
class.
8. Build this project using ``gradle -b build.gradle build``
9. Run this chaincode after starting a peer in dev-mode as above using
5. Build this project using ``gradle -b build.gradle build``
6. Run this chaincode after starting a peer in dev-mode as above using
``gradle -b build.gradle run``
Loading

0 comments on commit 8026601

Please sign in to comment.