[英]While trying to integrate the Hyperledger fabric SDK with the Spring boot getting the following error
[英]Getting the following error when trying to integrate hyperledger fabric SDK with spring REST controller
我正在做的事情背后的想法是使用 Spring REST API 公开超级账本结构区块链。 当我构建我的代码(没有 REST)并使用 java 命令调用它时,它工作正常并从 Hyperledger 结构返回数据。 但是,当我尝试在 REST 控制器中实现它时,我发现自己被阻止了。
下面是我的 Rest Controller 代码:
@RestController
public class RestWebController {
private static final Logger log = Logger.getLogger(RestWebController.class);
@RequestMapping(value = "/getall", method = RequestMethod.GET)
public void getAll(){
try {
HFCAClient caClient = getHfCaClient("http://localhost:7054", null);
// enroll or load admin
AppUser admin = getAdmin(caClient);
log.info(admin);
// register and enroll new user
AppUser appUser = getUser(caClient, admin, "hfuser");
log.info(appUser);
// get HFC client instance
HFClient client = getHfClient();
// set user context
client.setUserContext(admin);
// get HFC channel using the client
Channel channel = getChannel(client);
log.info("Channel: " + channel.getName());
// call query blockchain example
queryBlockChain(client);
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Invoke blockchain query
*
* @param client The HF Client
* @throws ProposalException
* @throws InvalidArgumentException
*/
static void queryBlockChain(HFClient client) throws ProposalException, InvalidArgumentException {
// get channel instance from client
Channel channel = client.getChannel("mychannel");
// create chaincode request
QueryByChaincodeRequest qpr = client.newQueryProposalRequest();
// build cc id providing the chaincode name. Version is omitted here.
ChaincodeID fabcarCCId = ChaincodeID.newBuilder().setName("poc-app").build();
qpr.setChaincodeID(fabcarCCId);
// CC function to be called
qpr.setFcn("queryAllTransactions");
Collection<ProposalResponse> res = channel.queryByChaincode(qpr);
// display response
for (ProposalResponse pres : res) {
String stringResponse = new String(pres.getChaincodeActionResponsePayload());
log.info(stringResponse);
}
}
/**
* Initialize and get HF channel
*
* @param client The HFC client
* @return Initialized channel
* @throws InvalidArgumentException
* @throws TransactionException
*/
static Channel getChannel(HFClient client) throws InvalidArgumentException, TransactionException {
// initialize channel
// peer name and endpoint in fabcar network
Peer peer = client.newPeer("peer0.org1.example.com", "grpc://localhost:7051");
// eventhub name and endpoint in fabcar network
EventHub eventHub = client.newEventHub("eventhub01", "grpc://localhost:7053");
// orderer name and endpoint in fabcar network
Orderer orderer = client.newOrderer("orderer.example.com", "grpc://localhost:7050");
// channel name in fabcar network
Channel channel = client.newChannel("mychannel");
channel.addPeer(peer);
channel.addEventHub(eventHub);
channel.addOrderer(orderer);
channel.initialize();
return channel;
}
/**
* Create new HLF client
*
* @return new HLF client instance. Never null.
* @throws CryptoException
* @throws InvalidArgumentException
*/
static HFClient getHfClient() throws Exception {
// initialize default cryptosuite
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
// setup the client
HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(cryptoSuite);
return client;
}
/**
* Register and enroll user with userId.
* If AppUser object with the name already exist on fs it will be loaded and
* registration and enrollment will be skipped.
*
* @param caClient The fabric-ca client.
* @param registrar The registrar to be used.
* @param userId The user id.
* @return AppUser instance with userId, affiliation,mspId and enrollment set.
* @throws Exception
*/
static AppUser getUser(HFCAClient caClient, AppUser registrar, String userId) throws Exception {
AppUser appUser = tryDeserialize(userId);
if (appUser == null) {
RegistrationRequest rr = new RegistrationRequest(userId, "org1");
String enrollmentSecret = caClient.register(rr, registrar);
Enrollment enrollment = caClient.enroll(userId, enrollmentSecret);
appUser = new AppUser(userId, "org1", "Org1MSP", enrollment);
serialize(appUser);
}
return appUser;
}
/**
* Enroll admin into fabric-ca using {@code admin/adminpw} credentials.
* If AppUser object already exist serialized on fs it will be loaded and
* new enrollment will not be executed.
*
* @param caClient The fabric-ca client
* @return AppUser instance with userid, affiliation, mspId and enrollment set
* @throws Exception
*/
static AppUser getAdmin(HFCAClient caClient) throws Exception {
AppUser admin = tryDeserialize("admin");
if (admin == null) {
Enrollment adminEnrollment = caClient.enroll("admin", "adminpw");
admin = new AppUser("admin", "org1", "Org1MSP", adminEnrollment);
serialize(admin);
}
return admin;
}
/**
* Get new fabic-ca client
*
* @param caUrl The fabric-ca-server endpoint url
* @param caClientProperties The fabri-ca client properties. Can be null.
* @return new client instance. never null.
* @throws Exception
*/
static HFCAClient getHfCaClient(String caUrl, Properties caClientProperties) throws Exception {
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
HFCAClient caClient = HFCAClient.createNewInstance(caUrl, caClientProperties);
caClient.setCryptoSuite(cryptoSuite);
return caClient;
}
// user serialization and deserialization utility functions
// files are stored in the base directory
/**
* Serialize AppUser object to file
*
* @param appUser The object to be serialized
* @throws IOException
*/
static void serialize(AppUser appUser) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(
Paths.get(appUser.getName() + ".jso")))) {
oos.writeObject(appUser);
}
}
/**
* Deserialize AppUser object from file
*
* @param name The name of the user. Used to build file name ${name}.jso
* @return
* @throws Exception
*/
static AppUser tryDeserialize(String name) throws Exception {
if (Files.exists(Paths.get(name + ".jso"))) {
return deserialize(name);
}
return null;
}
static AppUser deserialize(String name) throws Exception {
try (ObjectInputStream decoder = new ObjectInputStream(
Files.newInputStream(Paths.get(name + ".jso")))) {
return (AppUser) decoder.readObject();
}
}
我使用 mvn spring-boot:run 运行 spring boot,服务器正常启动。 这是我的 pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hyperledger.fabric-sdk-java</groupId>
<artifactId>fabric-sdk-java</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在 localhost:8080/getall 上调用服务器后,我收到此错误:
2018-07-13 14:56:33.439 WARN 24669 --- [ault-executor-0] io.grpc.internal.ChannelExecutor : Runnable threw exception in ChannelExecutor
java.lang.NoClassDefFoundError: io/netty/handler/codec/http2/internal/hpack/Decoder
at io.grpc.netty.GrpcHttp2HeadersDecoder.<init>(GrpcHttp2HeadersDecoder.java:85) ~[grpc-netty-1.3.0.jar:1.3.0]
at io.grpc.netty.GrpcHttp2HeadersDecoder$GrpcHttp2ClientHeadersDecoder.<init>(GrpcHttp2HeadersDecoder.java:147) ~[grpc-netty-1.3.0.jar:1.3.0]
at io.grpc.netty.NettyClientHandler.newHandler(NettyClientHandler.java:119) ~[grpc-netty-1.3.0.jar:1.3.0]
at io.grpc.netty.NettyClientTransport.start(NettyClientTransport.java:190) ~[grpc-netty-1.3.0.jar:1.3.0]
at io.grpc.internal.ForwardingConnectionClientTransport.start(ForwardingConnectionClientTransport.java:44) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.InternalSubchannel.startNewTransport(InternalSubchannel.java:216) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.InternalSubchannel.obtainActiveTransport(InternalSubchannel.java:186) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.ManagedChannelImpl$SubchannelImplImpl.obtainActiveTransport(ManagedChannelImpl.java:812) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.GrpcUtil.getTransportFromPickResult(GrpcUtil.java:592) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.DelayedClientTransport.reprocess(DelayedClientTransport.java:295) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.ManagedChannelImpl$LbHelperImpl$5.run(ManagedChannelImpl.java:718) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.ChannelExecutor.drain(ChannelExecutor.java:87) ~[grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.ManagedChannelImpl$LbHelperImpl.runSerialized(ManagedChannelImpl.java:709) [grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.ManagedChannelImpl$NameResolverListenerImpl.onAddresses(ManagedChannelImpl.java:758) [grpc-core-1.3.0.jar:1.3.0]
at io.grpc.internal.DnsNameResolver$1.run(DnsNameResolver.java:175) [grpc-core-1.3.0.jar:1.3.0]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: java.lang.ClassNotFoundException: io.netty.handler.codec.http2.internal.hpack.Decoder
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_171]
... 18 common frames omitted
2018-07-13 14:56:35.321 ERROR 24669 --- [nio-8080-exec-2] o.hyperledger.fabric.sdk.OrdererClient : sendDeliver time exceeded for orderer
org.hyperledger.fabric.sdk.exception.TransactionException: sendDeliver time exceeded for orderer
at org.hyperledger.fabric.sdk.OrdererClient.sendDeliver(OrdererClient.java:274) ~[fabric-sdk-java-1.0.0.jar:na]
at org.hyperledger.fabric.sdk.Orderer.sendDeliver(Orderer.java:165) [fabric-sdk-java-1.0.0.jar:na]
at org.hyperledger.fabric.sdk.Channel.getLatestBlock(Channel.java:1074) [fabric-sdk-java-1.0.0.jar:na]
at org.hyperledger.fabric.sdk.Channel.getConfigurationBlock(Channel.java:898) [fabric-sdk-java-1.0.0.jar:na]
at org.hyperledger.fabric.sdk.Channel.parseConfigBlock(Channel.java:826) [fabric-sdk-java-1.0.0.jar:na]
at org.hyperledger.fabric.sdk.Channel.initialize(Channel.java:526) [fabric-sdk-java-1.0.0.jar:na]
at com.example.demo.controller.RestWebController.getChannel(RestWebController.java:144) [classes/:na]
at com.example.demo.controller.RestWebController.getAll(RestWebController.java:84) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) [spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) [spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.31.jar:8.5.31]
注意:网络运行良好,通过独立调用 .jar,甚至运行超级账本结构 nodeJS sdk。
NoClassDefFoundError
表示版本冲突。 gRPC 被编译为使用运行时不存在的方法。
使用mvn dependency:tree
我看到正在使用 Netty 版本 4.1.25.Final。 但是查看fabric-sdk-java 1.0.0 ,它使用的是 grpc-netty 1.3.0 和 Netty 4.1.8.Final。 spring-boot-starter-parent 正在引入选择 Netty 4.1.25.Final 的spring-boot-dependencies 。
我建议升级到使用 grpc-netty 1.11.0 和 Netty 4.1.23.Final 的 fabric-sdk-java 1.1.0。 然后通过设置 netty.version 属性覆盖 spring-boot-dependencies 以使用 Netty 4.1.23.Final:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<netty.version>4.1.23.Final</netty.version> <!-- add this line -->
</properties>
我也遇到了这个问题,感谢Eric Anderson的回答,我解决了这个问题。
NoClassDefFoundError
表示版本冲突是完全正确的。
我的版本:fabric-sdk-java 1.0.0 ,Spring Boot 2.2.6.RELEASE。
fabric-sdk-java 1.0.0的netty版本是4.1.8.Final,而Spring Boot 2.2.6.RELEASE parent的netty版本是4.1.48.Final,如果你什么都不做,fabric-sdk-java可以使用4.1.48.Final,所以会报错。
这是我的解决方案:
<properties>
<java.version>1.8</java.version>
<netty.version>4.1.8.Final</netty.version>
</properties>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.