如何解决错误:如何在超级账本链码中编写 getHistoryForKey() 方法以获取密钥的历史记录Java 语言
我已将以下方法写入我的超级账本链码(智能合约)以根据密钥获取历史记录(所有交易数据),
@Transaction(intent = Transaction.TYPE.EVALUATE)
public ArrayList<String> queryProductHistory(final Context ctx,final String productNumber) {
if (productNumber == null) {
throw new RuntimeException("No ID given");
}
ChaincodeStub stub = ctx.getStub();
ArrayList<String> results = new ArrayList<>();
try {
QueryResultsIterator<KeyModification> history = stub.getHistoryForKey(productNumber);
if (history == null) {
String errorMessage = String.format("Product %s does not exist",productNumber);
System.out.println(errorMessage);
throw new ChaincodeException(errorMessage,MySmartContractErrors.PRODUCT_NOT_FOUND.toString());
}
Iterator<KeyModification> iter = history.iterator();
while (iter.hasNext()) {
results.add(iter.next().getStringValue());
}
} catch (Exception e) {
results.add(e.getMessage());
results.add(e.getCause().getMessage());
results.add(e.getStackTrace().toString());
}
return results;
}
我还为上述方法编写了一个 API,
@RequestMapping(value = "find-product-history",method = RequestMethod.GET)
public String queryProductHistory(@RequestParam(value="channelName") String channelName,@RequestParam(value="productNumber") String productNumber) throws Exception {
// Load a file system based wallet for managing identities.
Path walletPath = Paths.get("wallet");
Wallet wallet = Wallets.newFileSystemWallet(walletPath);
// load a CCP
Path networkConfigPath = Paths.get("/home","ubuntu","fabric-samples","test-network","organizations","peerOrganizations","org1.example.com","connection-org1.yaml");
Gateway.Builder builder = Gateway.createBuilder();
builder.identity(wallet,"appUser").networkConfig(networkConfigPath).discovery(true);
// create a gateway connection
try (Gateway gateway = builder.connect()) {
// get the network and contract
Network network = gateway.getNetwork(channelName);
Contract contract = network.getContract("my-blockchain-smart-contract");
byte[] result;
result = contract.evaluateTransaction("queryProductHistory",productNumber);
System.out.println(new String(result));
return result.toString();
}
}
我收到以下错误。这里可能有什么问题?
org.hyperledger.fabric.gateway.ContractException: error in simulation: transaction returned with failure: Unexpected error
at org.hyperledger.fabric.gateway.impl.query.SingleQueryHandler.evaluate(SingleQueryHandler.java:50) ~[fabric-gateway-java-2.1.1.jar:na]
at org.hyperledger.fabric.gateway.impl.TransactionImpl.evaluate(TransactionImpl.java:207) ~[fabric-gateway-java-2.1.1.jar:na]
at org.hyperledger.fabric.gateway.impl.ContractImpl.evaluateTransaction(ContractImpl.java:55) ~[fabric-gateway-java-2.1.1.jar:na]
at com.my.blockchain.api.controller.BlockchainAPIController.queryProductHistory(BlockchainAPIController.java:137) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_275]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_275]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_275]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_275]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.2.jar:5.3.2]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.2.jar:5.3.2]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.41.jar:9.0.41]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_275]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_275]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.41.jar:9.0.41]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_275]
注意:我也在 core.xml 中做了 enableHistoryDatabase: true
解决方法
现在一切正常。
这是链码 queryProductHistory()
方法
@Transaction
public String queryProductHistory(final Context ctx,final String productNumber) {
if (productNumber == null) {
throw new RuntimeException("No ID given");
}
ChaincodeStub stub = ctx.getStub();
ArrayList<String> results = new ArrayList<>();
try {
QueryResultsIterator<KeyModification> history = stub.getHistoryForKey(productNumber);
if (history == null) {
String errorMessage = String.format("Product %s does not exist",productNumber);
System.out.println(errorMessage);
throw new ChaincodeException(errorMessage,MySmartContractErrors.PRODUCT_NOT_FOUND.toString());
}
Iterator<KeyModification> iterator = history.iterator();
while (iterator.hasNext()) {
String iteratorValue = iterator.next().getStringValue();
//String iteratorValue = "TIMESTAMP = " + iterator.next().getTimestamp() + "Tx ID = " + iterator.next().getTxId() + " VALUE = " + iterator.next().getStringValue();
results.add(iteratorValue);
System.out.println(iteratorValue);
}
history.close();
} catch (Exception e) {
results.add(e.getMessage());
results.add(e.getCause().getMessage());
results.add(e.getStackTrace().toString());
}
return results.toString();
}
这里是 API 服务 queryProductHistory()
方法
@RequestMapping(value = "find-product-history",method = RequestMethod.GET) public String queryProductHistory(@RequestParam(value="channelName") String channelName,@RequestParam(value="productNumber") String productNumber) throws Exception {
// Load a file system based wallet for managing identities.
Path walletPath = Paths.get("wallet");
Wallet wallet = Wallets.newFileSystemWallet(walletPath);
// load a CCP
Path networkConfigPath = Paths.get("/home","ubuntu","fabric-samples","test-network","organizations","peerOrganizations","org1.example.com","connection-org1.yaml");
Gateway.Builder builder = Gateway.createBuilder();
builder.identity(wallet,"appUser").networkConfig(networkConfigPath).discovery(true);
// create a gateway connection
try (Gateway gateway = builder.connect()) {
// get the network and contract
Network network = gateway.getNetwork(channelName);
Contract contract = network.getContract("my-blockchain-smart-contract");
byte[] result;
result = contract.evaluateTransaction("queryProductHistory",productNumber);
//result = contract.submitTransaction("queryProductHistory",productNumber);
System.out.println(new String(result));
return new String(result);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。