hyperleger java-SDK 调用部署在链码上的合约步骤和出现的报错
报错:
在调用过程里,如果有发生报错,可以先检查检查连接配置文件,通道id、文件路径、ip地址、端口等,这些地方比较容易错。比如报的错有(No peers provided、Unable to load channel configuration from connection profile:、)
出现gRPC failure=Status{code=UNAVAILABLE, description=io exception, cause=io.netty.channel.、No subject alternative DNS name matching org1.example.com found或者说是证书不能验证类的问题,可能是在第四步中身份文件不符合的原因(如果重新部署链码,都需要重新复制一遍新的到自己的idea里)
步骤:
前提:已经在fabric网络上部署好链码,并且测试正常,能够调用。
以下是在应用上实现对fabri网络中链码调用的大致步骤,如果在fabric网络的链码调用是根据 hyperleger fabric 2.2 文档里的步骤走的,可以直接用配置文件里的内容(除了ip地址那里需要改成直接的),否则需要自己注意修改一下通道名,节点数、端口号等问题,第10步也要注意修改成自己的通道id和链码包名。
1、先确保fabric网络是在运行着的:
输入:docker ps -a
2、在idea的pom.xml中引入下面两个依赖
3、到 fabric-samples/test-network 目录里找到 organizations
4、将里面的两个文件复制到本地
5、放到idea的scr/main/resources/crypto-config 里
6、在resources文件下创建连接配置文件(采用json格式)
{
"name": "test-network",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
},
"orderer": "300"
}
}
},
"channels": {
"mychannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
},
"peer0.org2.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca-org1"
],
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"
}
},
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com"
],
"certificateAuthorities": [
"ca-org2"
],
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem"
}
}
},
"orderers": {
"orderer.example.com": {
"url": "grpcs://自己的ip:7050",
"mspid": "OrdererMSP",
"grpcOptions": {
"ssl-target-name-override": "orderer.example.com",
"hostnameOverride": "orderer.example.com"
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
},
"adminPrivateKeyPEM": {
"path": "src/main/resources/crypto-config/ordererOrganizations.example.com/users.Admin@example.com/msp/keystore/priv_sk"
},
"signedCertPEM": {
"path": "src/main/resources/crypto-config/ordererOrganizations.example.com/users.Admin@example.com/msp/signcerts/Admin@example.com-cert.pem"
}
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://自己的ip:7051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"hostnameOverride": "peer0.org1.example.com",
"request-timeout": 120001
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
}
},
"peer0.org2.example.com": {
"url": "grpcs://自己的ip:9051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org2.example.com",
"hostnameOverride": "peer0.org2.example.com",
"request-timeout": 120001
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
}
}
},
"certificateAuthorities": {
"ca-org1": {
"url": "https://自己的ip:7054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
},
"ca-org2": {
"url": "https://自己的ip:8054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
}
}
}
7、创建一个实体类 HyperLedgerFabricProperties
@Configuration
@ConfigurationProperties(prefix = "fabric")
@Data
public class HyperLedgerFabricProperties {
String networkConnectionConfigPath;
String certificatePath;
String privateKeyPath;
}
8、在配置文件中(xxx.properties的文件,没有可以自己建)添加
fabric.networkConnectionConfigPath =src/main/resources/connectionConfiguration.json
fabric.certificatePath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem
fabric.privateKeyPath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk
logging.level.org.hyperledger =trace
9、创建一个配置连接类HyperLedgerFabricGatewayConfig
@Configuration
@AllArgsConstructor
@Slf4j
public class HyperLedgerFabricGatewayConfig {
final HyperLedgerFabricProperties hyperLedgerFabricProperties;
@Bean
public Gateway gateway() throws Exception {
BufferedReader certificateReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getCertificatePath()), StandardCharsets.UTF_8);
X509Certificate certificate = Identities.readX509Certificate(certificateReader);
BufferedReader privateKeyReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getPrivateKeyPath()), StandardCharsets.UTF_8);
PrivateKey privateKey = Identities.readPrivateKey(privateKeyReader);
Wallet wallet = Wallets.newInMemoryWallet();
wallet.put("user1",Identities.newX509Identity("Org1MSP",certificate,privateKey));
Gateway.Builder builder = Gateway.createBuilder()
.identity(wallet,"user1")
.networkConfig(Paths.get("src/main/resources/connectionConfiguration.json"));
Gateway gateway =builder.connect();
log.info("=========================================== connected fabric gateway {} ", gateway);
return gateway;
}
}
10、创建控制类和实体类进行调用
这里只写了初始化创建和查询全部信息,没有用到参数,我就没有写实体类对参数调用了,具体参考可以看视频
控制类:
@RestController
@RequestMapping("/Car")
@Slf4j
@AllArgsConstructor
public class ContractController {
final Gateway gateway;
@RequestMapping("/init")
public Map<String, Object> queryCatByKey(@PathVariable String key) throws GatewayException {
Map<String, Object> result = Maps.newConcurrentMap();
Contract contract =getContract();
byte[] cat = contract.evaluateTransaction("initLedger");
result.put("payload", StringUtils.newStringUtf8(cat));
result.put("status", "ok");
return result;
}
@RequestMapping("/query")
public Map<String, Object> queryCatByKey(@PathVariable String key) throws GatewayException {
Map<String, Object> result = Maps.newConcurrentMap();
Contract contract =getContract();
byte[] cat = contract.evaluateTransaction("queryAllCars");
result.put("payload", StringUtils.newStringUtf8(cat));
result.put("status", "ok");
return result;
}
private Network getNetwork(){
return gateway.getNetwork("mychannel");
}
private Contract getContract(){
return getNetwork().getContract("fabcar");
}
}
11、用postman调用
--------------------完成如果用postman传入参数显示:Content type ‘text/plain;charset=UTF-8’ not supported
那需要在postman传参数时,注意将格式改成json
如果在做传参数的操作时,后台报null(java.lang.NullPointerException),也许是postman这里的参数字符写错了,可以检查看看