链码的开发不部分参考官网demo即可。

本文不会详细介绍开发过程

笔者启动的是一个gradle工程,也就是jar包管理使用的是gradle。

chaincode 源码:

/*
Copyright IBM Corp., DTCC All Rights Reserved. SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.example; import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import io.netty.handler.ssl.OpenSsl;
import io.netty.util.internal.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperledger.fabric.example.bean.Factor;
import org.hyperledger.fabric.shim.ChaincodeBase;
import org.hyperledger.fabric.shim.ChaincodeStub; import java.util.List; public class FactoringChaincode extends ChaincodeBase { private static Log _logger = LogFactory.getLog(FactoringChaincode.class); @Override
public Response init(ChaincodeStub stub) {
try {
_logger.info("Init java factoring chaincode");
String func = stub.getFunction();
if (!func.equals("init")) {
return newErrorResponse("function other than init is not supported");
}
_logger.info("begin test keepAlive");
stub.putStringState("keepAliveTest","keepAliveTestValue");
_logger.info("end test keepAlive");
return newSuccessResponse();
} catch (Throwable e) {
return newErrorResponse(e);
}
} @Override
public Response invoke(ChaincodeStub stub) {
try {
_logger.info("Invoke java factoring chaincode");
String func = stub.getFunction();
List<String> params = stub.getParameters();
_logger.debug("Invoke function is "+stub.getFunction()+"Parameter is "+params.toString());
if(params.isEmpty() || params.size()< || params.get().length()==){
return newErrorResponse("the invoke args not exist or arg[0] is emptyt");
}
if (func.equals("SaveData")) {
return saveData(stub, params);
}
if (func.equals("KeepaliveQuery")) {
return keepaliveQuery(stub, params);
}
if (func.equals("QueryDataByFabricTxId")) {
return queryDataByFabricTxId(stub, params);
}
if (func.equals("QueryDataByBusinessNo")) {
return queryDataByBusinessNo(stub, params);
}
return newErrorResponse("Invalid invoke function name. ");
} catch (Throwable e) {
return newErrorResponse(e);
}
} private Response keepaliveQuery(ChaincodeStub stub, List<String> params) {
String tarValue = stub.getStringState("keepAliveTest");
if(!"keepAliveTestValue".equals(tarValue)){
return newErrorResponse("ERROR! KeepaliveQuery get result is "+tarValue);
}
return newSuccessResponse("Reached".getBytes());
} private Response queryDataByBusinessNo(ChaincodeStub stub, List<String> params) {
String txId =new String(stub.getState(params.get()));
_logger.info("query data by businessNo:"+params.get()+",txId is"+txId);
return this.queryDataByFabricTxId(stub, Lists.newArrayList(txId));
} private Response queryDataByFabricTxId(ChaincodeStub stub, List<String> params) {
_logger.info("queryData by txId:"+params.get());
byte[] res = stub.getState(params.get());
return newSuccessResponse(new String(res),res);
} private Response saveData(ChaincodeStub stub, List<String> args) {
if(args.isEmpty() || args.size()<){
return newSuccessResponse("saveData wrong args");
}try{
Factor f = JSONArray.toJavaObject(JSONArray.parseObject(args.get()),Factor.class);
String businessNo = f.getBusinessNo();
if(StringUtil.isNullOrEmpty(businessNo)){
return newErrorResponse("businessNo must exist");
}
String txId = stub.getTxId();
stub.putState(txId,args.get().getBytes());
stub.putState(businessNo,txId.getBytes());
_logger.info("save data successfully with txid "+txId+",and businessNo"+businessNo);
}catch (Exception e){
return newErrorResponse(e.getMessage());
}
return newSuccessResponse();
} public static void main(String[] args) {
System.out.println("OpenSSL avaliable: " + OpenSsl.isAvailable());
new FactoringChaincode().start(args);
} }
keepaliveQuery方法是为了探活。因为如果某个节点上没有启动链码容器会对交易的速度结果有影响,所以采用这种方式,每个节点都需要调用一次该方法在开始正常业务的调用。

链码的逻辑很简单,需要注意的是,gradle工程的配置文件中,需要制定baseName是 chaincode。因为在节点实例化链码的时候会默认找名称为chaincode的jar包。

shadowJar {
baseName = 'chaincode'
version = null
classifier = null manifest {
attributes 'Main-Class': 'org.hyperledger.fabric.example.FactoringChaincode'
}
}

mainfest中需要特别指定main方法的java 文件。否则在实例化的时候会报错。

需要注意的是,目前fabric应用的大部分地方场景中的部署环境是没有外网的。如银行,政府企业的环境。这个时候gradle就需要支持离线打包。

在build.gradle的配置文件中添加

dependencies { compile fileTree(dir: 'libs', includes: ['*.jar'])}    项目的根目录,跟Src同级建立一个libs文件夹,把需要的jar包放进去即可。

开发完成以后把编写的项目放到服务器上打包:

./peer chaincode package -n factor -l java -p /usr/local/workspace/java_chaincode/ -v 1.0 -s -S -i "AND ('Org1MSP.peer')" factor.out

-i "AND ('Org1MSP.peer')"表示该链码只能被Org1的peer节点实例化,其他节点实例化的话会报错。如果不指定这个参数,默认的限制是每个组织的admin可以实例化该链码。

打包的文件经过安装实例化就可以正常调用了。

附git地址 https://github.com/figo050518/fabric_java_chaincode

fabric java chaincode 开发的更多相关文章

  1. Hyperledger Fabric java chaincode 中文乱码问题

    开发java chaincode过程中遇到一个中文乱码的问题.都是官方的demo,请求的sdk是用java写的,部署的chaincode有两种选择(不考虑node),一种go语言写的chaincode ...

  2. Hyperledger Fabric java chaincode 编译部署(1.4V)

    前提条件: 构建好了一个拥有四个peer 一个Order 的1.4版本的Fabric网络. 证书通过Cryptogen生成,没有使用CA服务. 开启TLS. 网络中的peer都加入了一个 名为mych ...

  3. Hyperledger Fabric ChainCode开发

    预览 Hyperledger Fabric的chaincode开发目前支持Go.Java.Node.js语言,下面以Go语言作为例子,我们先看下面的一个官方提供chaincode模板 ··· pack ...

  4. 用Hyperledger Fabric(超级账本)来构建Java语言开发区块链的环境

    面向 Java 开发人员的链代码简介 您或许听说过区块链,但可能不确定它对 Java™ 开发人员有何用.本教程将帮助大家解惑.我将分步展示如何使用 Hyperledger Fabric v0.6 来构 ...

  5. HyperLedger Fabric ChainCode开发——shim.ChaincodeStubInterface用法

    深蓝前几篇博客讲了Fabric的环境搭建,在环境搭建好后,我们就可以进行Fabric的开发工作了.Fabric的开发主要分成2部分,ChainCode链上代码开发和基于SDK的Application开 ...

  6. 搭建基于hyperledger fabric的联盟社区(四) --chaincode开发

    前几章已经分别把三台虚拟机环境和配置文件准备好了,在启动fabric网络之前我们要准备好写好的chaincode.chaincode的开发一般是使用GO或者JAVA,而我选择的是GO语言.先分析一下官 ...

  7. 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码

    部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...

  8. Hyperledger Fabric chaincode 开发(疑难解答)

    Q&A Q1: 使用fabric release 1.2 进行golang chaincode开发时报错: ..\..\hyperledger\fabric\vendor\github.com ...

  9. hyperledger fabric 中java chaincode 支持离线打包

    联盟链由于其本身的特性,目前应用在一些大型国有企业银行比较多.出于安全考虑,这些企业一般会隔离外网环境.所以在实际生产需求中可能存在需要在一个离线的环境中打包安装chaincode的情况. 本文基于这 ...

随机推荐

  1. 获取wifi热点

    https://stackoverflow.com/questions/31555640/how-to-get-wifi-ssid-in-ios9-after-captivenetwork-is-de ...

  2. java代码,用continue写出偶数

    总结:不满足条件时,输出当前==== package com.b; import java.util.Scanner; //用continue写出偶数的代码是: public class twe { ...

  3. 在U盘分区安装Kali并引导live CD 教程以及常见的注意事项

    Kali Linux作为强大的全能渗透系统,把它制成Live CD基本算是必备技能了,但是官方提供的文档虽然简单,但是整个U盘都会被占用,确实是有点可惜,结合网上提供的一些思路加上自己的经验,向大家讲 ...

  4. 12-21C#电脑蓝屏效果(可以恶搞整人哦)、输入输出流(StreamReader/streamWriter)

    一.winform电脑蓝屏效果 第一种方法:基本操作: 第一步:创建一个新的C#窗体“Form1”: 第二步:在设计窗口中,更改其属性: 1)text属性:将form1的text属性中的文字取消掉,然 ...

  5. 11-23网页基础--JavaScript基础知识

    第一课 JavaScript简介 一.定义:JavaScript是脚本语言,需要宿主文件,它的宿主文件是html文件. JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 ...

  6. oracle 在xml中批量插入,批量修改及多组条件查询

    最近公司用ibatis开发项目,本来可以用存储过程处理批量插入,批量修改及多组条件查询:但由于使用模块相对较小,暂时就在xml中配置,以前没有在xml做过类似处理,有必要记录一下:好了,代码如下: & ...

  7. android viewpage解决嵌套

    子viewpage 自定义 写法一: public class ChildViewPager extends ViewPager{ /** 触摸时按下的点 **/ PointF downP = new ...

  8. Android中的文件读写总结

    在Android中,文件主要分为两大类,内部存储和外部存储 内部存储的文件是程序私有的,分为普通文件和Cache文件 外部文件也可以是私有的,也可以是共有的,这要根据文件的目录位置来决定 共有文件可以 ...

  9. 1-1+zookeeper简介

     zookeeper是中间件,可以为分布式系统提供协调服务.如果没有分布式系统,zookeeper也发挥不了它的优势.

  10. URL操作

    ThinkPHP 的 URL 操作.主要涉及到 URL 路径大小写.伪静态.生成以及模版中的 U()方法. 一.URL大小写 系统默认的规范是根据 URL 里面的模块名.控制器名来定位到具体的控制器类 ...