繁体   English   中英

尝试将 hyperledger Fabric SDK 与 spring REST 控制器集成时出现以下错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM