Request send() hangs if response can not be parsed when using WebSocketService
Closed this issue · 0 comments
no result from send()
I'm trying to load blocks in batch from infura.io and sometimes due to some issue in infura I'm getting incorrect result. Instead of block object it could be just string, or id could be some uuid instead of long. If this situation occurs exception is logged in console and application just stops because send() method never exits.
As I see it, WebSocketService.processBatchRequestReply receives response, removes it from map, so timeout never happens, parsing throws one of Jackson exceptions and WebSocketService doesn't catch it. It is logged in WebSocketClient.onMessage(), but request never gets any response.
ERROR [org.web3j.protocol.websocket.WebSocketClient] (WebSocketConnectReadThread-186) Failed to process message '...' from server wss://holesky.infura.io/ws/v3/<mykey>: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.web3j.protocol.core.methods.response.EthBlock$Block` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('0x0000000000000000000000000000000000000000000000000000000000002460') at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: org.web3j.protocol.core.methods.response.EthBlock["result"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1754)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1379)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:311)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1592)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:197)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:2099)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1249)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1267)
at org.web3j.protocol.core.methods.response.EthBlock$ResponseDeserialiser.deserialize(EthBlock.java:1001)
at org.web3j.protocol.core.methods.response.EthBlock$ResponseDeserialiser.deserialize(EthBlock.java:992)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4893)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3036)
at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:3500)
at org.web3j.protocol.websocket.WebSocketService.processBatchRequestReply(WebSocketService.java:319)
at org.web3j.protocol.websocket.WebSocketService.onWebSocketMessage(WebSocketService.java:281)
at org.web3j.protocol.websocket.WebSocketService$1.onMessage(WebSocketService.java:155)
at org.web3j.protocol.websocket.WebSocketClient.lambda$onMessage$0(WebSocketClient.java:52)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at org.web3j.protocol.websocket.WebSocketClient.onMessage(WebSocketClient.java:49)
at org.java_websocket.client.WebSocketClient.onWebsocketMessage(WebSocketClient.java:644)
at org.java_websocket.drafts.Draft_6455.processFrameText(Draft_6455.java:986)
at org.java_websocket.drafts.Draft_6455.processFrame(Draft_6455.java:910)
at org.java_websocket.WebSocketImpl.decodeFrames(WebSocketImpl.java:402)
at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:234)
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:527)
at java.base/java.lang.Thread.run(Thread.java:1583)
Exception can be different depending on what faulty response I get
Steps To Reproduce
web3jService = new WebSocketService(network.getRpcUrl(), false);
web3jService.connect();
web3j = Web3j.build(web3jService);
BatchRequest batchRequest = web3j.newBatch();
for (long i = startBlockNum; i < endBlockNum; i++) {
batchRequest.add(web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(i)), true));
}
//this call never exists if response is incorrect
BatchResponse batchResponse = batchRequest.send();
Expected behavior
IOException or RuntimeException should be thrown or in case of sendAsync future should complete exceptionally.
Actual behavior
send method never exits
Environment
- Web3j version - 4.12.2
- Jackson databind - 2.18.1, but I think could be any
Additional context
I think problem and its possible solution is clear, but ask me if anything more information is needed