应用开发指南

应用开发步骤

主要开发步骤

使用web3sdk开发区块链java应用主要包括如下过程:
  1. 数据结构和接口设计,编写合约,并将合约代码转换成java代码
  2. 编写应用程序:调用合约接口完成合约部署和调用逻辑
  3. 配置java应用
  4. 运行并测试java应用

编写合约

合约功能设计:实现简单计数器

实现一个简单的计数器,主要功能包括:
  • 设置和读取计数器名字、增加计数、读取当前计数功能。
  • 通过receipt log的方式,把修改记录log到区块中,供客户端查询。

(注: receipt log用处很大,是区块链和业务端同步交易处理过程和结果信息的有效渠道)

智能合约代码Counter.sol

根据合约功能要求可实现智能合约 Counter.sol ,合约代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
pragma solidity ^0.4.2;
contract Counter{
    string name;
    uint256 counter;
    //event handle
    event counted(uint256 c,uint256 oldvalue,uint256 currvalue,string memo); 
    event changename(string oldname); 

    function Counter(){
       name="I'm counter";
       counter = 0;
    }

    function setname(string n){
    	name=n;
	    changename(n);
    }
	
    function getname()constant returns(string){
        return name;
    }

    function addcount(uint256 c,string memo)
    {
   	uint256 oldvalue = counter;
        counter = counter+c;
        counted(c,oldvalue,counter,memo); //event
    }
	
    function getcount()constant returns(uint256){
        return counter;
    }
}

将合约代码Counter.sol转换为java代码Counter.java

web3sdk提供了 counter_compile.sh 脚本将Counter.sol转换成Counter.java:
# 进入合约编译脚本所在目录 (设web3sdk位于~/mydata目录)
# Counter 合约所在目录为 ~/mydata/web3sdk/dist/contracts
$ cd ~/mydata/web3sdk/dist/bin
# 执行合约编译脚本
# (com是java代码所属的包,转换后可手动修改)
$ bash counter_compile.sh org.bcosliteclient
# 也可以使用如下命令编译所有合约
$ bash compile.sh org.bcosliteclient
查看生成的java代码
$ cd ~/mydata/web3sdk/dist/output
# ...此处省略若干输出...
├── Counter.abi  # Counter.sol编译生成的abi文件
├── Counter.bin  # Counter.sol编译生成的bin文件
└── org
   └── bcosliteclient
       ├── Counter.java # Counter.sol转换成的java代码
       ├── Evidence.java
       ├── EvidenceSignersData.java
       └── Ok.java

output目录生成了合约的.abi, .bin等文件,以及org/bcosliteclient/Counter.java文件。

这个java文件可以复制到客户端开发环境里,后续建立的java工程的对应的包路径下。

若转换成java代码时报错,请参考 faq【合约转换成java代码出错】 .

Counter.sol对应的Counter.java代码如下:

搭建并配置java应用

下载java应用bcosliteclient

编译bcosliteclient应用

# 解压应用程序(设下载的压缩包bcosliteclient.zip位于~/mydata目录下)
$ cd ~/mydata && unzip bcosliteclient.zip

# 编译bcosliteclient应用
$ cd bcosliteclient && gradle build
此时bcosliteclient应用目录如下:
$ tree -L 2
├── bcosliteclient # 编译生成目录
│   ├── bin        # 包含部署和调用Counter.sol合约的可执行脚本
│   ├── conf       # 配置文件,包含客户端配置文件applicationContext.xml,客户端证书
│   └── lib        # jar包目录
├── build          # 编译生成的临时目录
│   ├── ...省略若干行...
├── build.gradle   
├── lib
│   ├── fastjson-1.2.29.jar
│   └── web3sdk.jar    # 应用引用的web3sdk jar包
└── src
   ├── bin             # 包含可执行程序bcosclient
   ├── contract        
   |── org             # 源码目录
   └── resources       # 配置文件目录

配置java应用

参考 web3sdk配置 配置java应用,主要配置选项包括:

../../_images/javaconfig.png

部署和调用合约

部署Counter.sol合约

按照上节操作配置好java应用工程后,可调用相关接口部署和调用Counter.sol合约。
# 设bcosliteclient应用位于~/mydata目录
$ cd ~/mydata/bcosliteclient/bcosliteclient/bin
# 部署合约
$ chmod a+x bcosclient && ./bcosclient deploy
-----> start test !
init AOMP ChannelEthereumService
-->Got ethBlockNumber: 42
Deploy contract :null,address :0x8bc176465048ec377a824b7cf36f3cd7452cd093
<--start blockNumber = 42,finish blocknmber=43

由输出结果看出,合约部署成功,合约地址为 0x8bc176465048ec377a824b7cf36f3cd7452cd093 ,且部署成功后,区块链系统区块高度由42增加为43.

调用Counter.sol合约

使用 bcosliteclient/bcosliteclient/bin 目录下的 bcosclient 脚本调用Counter.sol合约:
# 设bcosliteclient应用位于~/mydata目录
$ cd ~/mydata/bcosliteclient/bcosliteclient/bin
# 调用合约(合约地址是0x8bc176465048ec377a824b7cf36f3cd7452cd093)
$ chmod a+x bcosclient && ./bcosclient call_contract 0x8bc176465048ec377a824b7cf36f3cd7452cd093
-----> start test !
init AOMP ChannelEthereumService
-->Got ethBlockNumber: 43
counter value before transaction:0
setname-->oldname:[MyCounter from:0,inc:100],newname=[MyCounter from:0,inc:100]
Current Counter:100
addcount-->inc:100,before:0,after:100,memo=when tx done,counter inc 100
<--start blockNumber = 43,finish blocknmber=44

由输出结果可看出,计数器合约Counter.sol调用成功后,计数器值增加100,区块链系统块高由43增加为44.

gradle文件配置说明

gradle配置文件说明

应用SDK的【build.gradle】要通过【dependencies】添加web3sdk.jar依赖和应用外部依赖库:
../../_images/build-gradle.png

一个完整的build.gradle示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
apply plugin: 'maven'
apply plugin: 'java'
apply plugin: 'eclipse'

//指定JDK版本,改成系统中版本
sourceCompatibility = 1.8
targetCompatibility = 1.8

[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'

// In this section you declare where to find the dependencies of your project
repositories {
	maven {
		url "http://maven.aliyun.com/nexus/content/groups/public/"
	}

	mavenLocal()
	mavenCentral()
}


List logger = [
		'org.slf4j:slf4j-log4j12:1.7.25'
]

def spring_version="4.3.18.RELEASE"
List spring =[
		"org.springframework:spring-core:$spring_version",
		"org.springframework:spring-beans:$spring_version",
		"org.springframework:spring-context:$spring_version",
		"org.springframework:spring-tx:$spring_version",
		"org.springframework:spring-jdbc:$spring_version",
		"org.springframework:spring-test:$spring_version"
]

List alibaba = [
		'com.alibaba:druid:1.0.29',
		'com.alibaba:fastjson:1.2.29'
]

// In this section you declare the dependencies for your production and test code
dependencies {
	compile logger,spring,alibaba
	compile 'org.apache.commons:commons-lang3:3.1'
	compile "com.fasterxml.jackson.core:jackson-databind:2.9.6"
	compile 'io.netty:netty-all:4.1.15.Final'
	compile 'io.netty:netty-tcnative:2.0.18.Final'
	compile 'com.google.guava:guava:19.0'

	// web3j依赖
	compile 'org.apache.httpcomponents:httpclient:4.5.5',
			'org.bouncycastle:bcprov-jdk15on:1.54',
			'com.lambdaworks:scrypt:1.4.0',
			'com.squareup:javapoet:1.7.0',
			'io.reactivex:rxjava:1.2.4',
			'com.github.jnr:jnr-unixsocket:0.15'

}

sourceSets {
	main {
		java {
			srcDir 'src/main/java'
			srcDir 'src/test/java'
		}
		resources  {
			srcDir 'src/main/resources'
		}
	}
}

jar {
	destinationDir file('dist/apps')
	archiveName project.name + '.jar'
	exclude '**/*.xml'
	exclude '**/*.properties'

	doLast {
		copy {
			from file('tools/')
			into 'dist/'
		}
		copy {
			from configurations.runtime
			into 'dist/lib'
		}
		copy {
			from file('src/test/resources/')
			into 'dist/conf'
		}
	}
}

总结

SDK应用开发步骤总结

根据以上描述,使用web3sdk开发区块链应用主要包括如下过程:
  1. 根据应用功能设计合约数据结构和接口;
  2. 编写智能合约,可先用Nodejs简单验证合约代码逻辑是否正确,验证通过后,将合约代码转换成java代码
  3. 编写java应用,调用合约java接口完成合约部署和调用功能
  4. 配置并编译java应用
  5. 应用功能测试

SDK应用部署/调用合约主要流程

参考 CounterClient.java
  1. 初始化AMOP的ChannelEthereumService
  2. 使用AMOP初始化Web3j
  3. 初始化交易签名密钥对
  4. 初始化交易参数
  5. 调用合约接口部署或调用合约

其他说明

  • 从零开发SDK应用时,可使用eclipse新建java工程,编译配置文件build.gradle可参考bcosliteclient.zip中的编译配置;
  • java应用根目录的lib目录下要存放FISCO BCOS的web3sdk.jar,web3sdk升级时,首先请从github下载最新[web3sdk.jar](https://github.com/FISCO-BCOS/web3sdk/releases)替换java应用的原lib文件夹下的web3sdk.jar,然后参考官方项目的build.gradle文件拷贝相应依赖。

参考资料