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

java全链路监控有哪些工具 java调用链路_智能合约


2、在idea的pom.xml中引入下面两个依赖

java全链路监控有哪些工具 java调用链路_智能合约_02


3、到 fabric-samples/test-network 目录里找到 organizations

java全链路监控有哪些工具 java调用链路_智能合约_03


4、将里面的两个文件复制到本地

java全链路监控有哪些工具 java调用链路_ide_04

5、放到idea的scr/main/resources/crypto-config 里

java全链路监控有哪些工具 java调用链路_ide_05


6、在resources文件下创建连接配置文件(采用json格式)

java全链路监控有哪些工具 java调用链路_区块链_06

{
  "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调用

java全链路监控有哪些工具 java调用链路_区块链_07


--------------------完成如果用postman传入参数显示:Content type ‘text/plain;charset=UTF-8’ not supported

那需要在postman传参数时,注意将格式改成json

java全链路监控有哪些工具 java调用链路_ide_08


如果在做传参数的操作时,后台报null(java.lang.NullPointerException),也许是postman这里的参数字符写错了,可以检查看看