How to catch/Capture "javax.net.ssl.SSLHandshakeException: Failed to create SSL connection" while sending message over java vert.x Eventbus - vert.x

I am trying to use SSL over eventbus. To test the failure case I tried sending message to the eventbus from another verticle in same cluster by passing some different keystore.
I am getting below exception on console but it is not failing the replyHandler hence my code is not able to detect the SSL exception.
my code:
eb.request("ping-address", "ping!", new DeliveryOptions(), reply -> {
try {
if (reply.succeeded()) {
System.out.println("Received reply " + reply.result().body());
} else {
System.out.println("An exception " + reply.cause().getMessage());
}
} catch (Exception e) {
System.out.println("An error occured" + e.getCause());
}
});
Exception on console:
**javax.net.ssl.SSLHandshakeException: Failed to create SSL connection**
at io.vertx.core.net.impl.ChannelProvider$1.userEventTriggered(ChannelProvider.java:109)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:341)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:327)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:319)
at io.netty.handler.ssl.SslHandler.handleUnwrapThrowable(SslHandler.java:1249)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1230)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1271)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:505)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:444)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:283)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:813)
Caused by: javax.net.ssl.SSLException: Received fatal alert: bad_certificate
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1647)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1615)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1781)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1070)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:896)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:766)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:282)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1329)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1224)
... 20 more
But handler is failing for timeout after 30 sec.
Timed out after waiting 30000(ms) for a reply. address: __vertx.reply.8419a431-d633-4ba8-a12e-c41fd5a4f37a, repliedAddress: ping-address
I want to capture the SSL exception immediately and handle it. Please guide me how can I Capture/catch this exception.
I tried with below code. Below one is able to handle the exception and I am not getting reply result from called event-bus. Reply result is always null. (value is always null)
MessageProducer<Object> ms = eb.sender("ping-address");
ms.write("ping!", reply -> {
if (reply.succeeded()) {
reply.map(value -> {
System.out.println("Received reply " + value);
return reply;
});
} else {
System.out.println("No reply");
System.out.println("An exception : " + reply.cause().getMessage());
}
});

You can't catch this exception because the Vert.x clustered EventBus implementation buffers messages when the nodes are not connected together. The message could be sent later if the problem is only temporary.
If you want to be notified earlier, you could set a lower timeout in DeliveryOptions.

Related

Flutter mqtt - Unicode(Korean) doesn't work

I am using mqtt_client: ^9.6.8 in my flutter project.
I want to subscribe to Korean topics, like topic: "test/안녕"
I want to get messages in Korean, like message: "안녕하세요"
currently if I try to subscribe to a korean topic, the client disconnects and the process just kills itself.
The log was a little bit different before, but this is the current log after I subscribe to a korean topic.
I/flutter (18972): 1-2022-08-09 15:38:40.135206 -- MqttConnectionBase::_onDone - calling disconnected callback
I/flutter (18972): 1-2022-08-09 15:38:40.135985 -- MqttConnectionKeepAlive::stop - stopping keep alive
I/flutter (18972): EXAMPLE::OnDisconnected client callback - Client disconnection
I/flutter (18972): EXAMPLE::OnDisconnected callback is unsolicited or none, this is incorrect - exiting
D/HostConnection(18972): createUnique: call
F/libc (18972): FORTIFY: pthread_mutex_lock called on a destroyed mutex (0xb400006dd36425a0)
D/HostConnection(18972): HostConnection::get() New Host Connection established 0xb400006de3607310, tid 19012
F/libc (18972): Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 19013 (1.raster), pid 18972
if I send a korean message, then it comes like HÅU± which is not what I want.
I tried to decode with utf8 but I can't seem to do it correctly.
Any helps on this? thanks for every suggestion!!
--edit--
this is the part where I print the received mqtt message
client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) {
final recMess = c![0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
context.read<SubTopic>().newTopic(c[0].topic);
context.read<SubMessage>().newMessage(pt);
print('Notification: topic is <${c[0].topic}>, payload is <$pt>');
});
this is where I subscribe to the topic
try {
await client.connect();
} on NoConnectionException catch (e) {
print('EXAMPLE::client exception - $e');
client.disconnect();
} on SocketException catch (e) {
print('EXAMPLE::socket exception - $e');
client.disconnect();
}
if (client.connectionStatus!.state == MqttConnectionState.connected) {
print('EXAMPLE::Mosquitto client connected');
for (String topic in _subTopicList) {
print(topic);
client.subscribe(topic, MqttQos.exactlyOnce);
}
} else {
print(
'EXAMPLE::ERROR Mosquitto client connection failed - disconnecting, status is ${client.connectionStatus}');
client.disconnect();
// exit(-1);
}

Can we recognise inaccessible url using apache CloseableHttpAsyncClient

I am using CloseableHttpAsyncClient for downloading image with socketreadtimemout of 10 sec , connect timeout 5sec and doing a retry if it fails with sockettimeout and Timeout exception.
Now when the url is not accessible(404) then instead of resource not found exception it is failing with socket timeout and doing a retry again.So in my case for this invalid url also we are trying again and it adds up to the latency(~10+10=20 sec).
Below is the code snippet
Future<HttpResponse> httpResponseFuture = asyncCloseableHttpClient.execute(httpUriRequest, null);
try {
return httpResponseFuture.get(10000, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
Throwable cause = e.getCause() != null ? e.getCause() : e;
if (cause instanceof ConnectException) {
throw new DownloadConnectionException("ConnectionException " + cause, DOWNLOAD_FAILED, cause);
}
if (cause instanceof SocketTimeoutException) {
throw new DownloadTimeoutException(DOWNLOAD_TIMEOUT_EXCEPTION);
}
if (cause instanceof ConnectionClosedException) {
throw new DownloadConnectionClosedException("ConnectionClosedException " + DOWNLOAD_FAILED, cause);
}
if(cause instanceof UnsupportedCharsetException) {
throw new BadRequestException("Image download failed with UnsupportedCharsetException " + cause,
INVALID_CONTENT_TYPE_EXCEPTION, cause);
}
} catch (TimeoutException e) {
throw new DownloadTimeoutException(DOWNLOAD_TIMEOUT_EXCEPTION);
}
This the config values for CloseableHttpAsyncClient
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(10000)
.setConnectTimeout(5000)
.setRedirectsEnabled(true)
.setMaxRedirects(3)
.setStaleConnectionCheckEnabled(false) // never set this to true, 30 ms extra per request
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
.build();
This is retry config
RetryConfig.custom().maxAttempts(downloadAttempts).retryOnException(e -> ( e instanceof DownloadTimeoutException) ) .waitDuration(Duration.ofMillis(30)).build();
To give more context why I am setting the socketreadtimemout of 10 sec because let's say for some bigger image download it may fail 1st time,so in that case retry is valid scenario but not in the resource not found case.
Can we do anything to make resource not found/invalid url fail fast so that it wont fail with sockettimeout exception.

ErrorDecoder not catching SocketTimeoutException

With feign builder I am making call to external URL. I have set readTimeout as 2seconds, I am getting the SocketTimeoutException but it's not going to ErrorDecoder.
Feign Builder Configuration:
Options options = new Options(10000, TimeUnit.MILLISECONDS, 2000,
TimeUnit.MILLISECONDS, false);
return Feign.builder()
.logLevel(level)
.client(client)
.retryer(Retryer.NEVER_RETRY)
.options(options)
.errorDecoder(feignErrorDecoder())
.exceptionPropagationPolicy(UNWRAP);
private ErrorDecoder feignErrorDecoder() {
return (methodKey, response) -> {
return new MyCustomException("ERROR_TIMEOUT",
"Timeout Occurred: " + response.status());
};
}
When I call service exception is not going to ErrorDecoder. java.lang.reflect.UndeclaredThrowableException coming.
ErrorDecoder is not called when an IOException (SocketTimeoutException) is thrown. See SynchronousMethodHandler#executeAndDecode(...). In general decoders are only called when a response is returend by the api-call. The ErrorCoder is only called when the http error code is not 2xx and 4xx.

KSQL Java Client app Received 404 response from server:

I have written KSQL Client Java app to fetch the topic message details from KSQL Tables. This is the code snippet to read the topic messages from KSQL table. But when i run this program getting below error. Please let me know how to resolve this issue.
KSQLClient Code:
ClientOptions options = ClientOptions.create()
.setHost(KSQLDB_SERVER_HOST)
.setPort(KSQLDB_SERVER_HOST_PORT);
Client client = Client.create(options);
System.out.println("Client object value ---->"+client);
// Send requests with the client by following the other examples
String query = "SELECT * FROM TESTKSQLTBLE EMIT CHANGES;";
Map<String, Object> properties = Collections.singletonMap("auto.offset.reset", "earliest");
client.streamQuery(query, properties)
.thenAccept(streamedQueryResult -> {
System.out.println("Result column names: " + streamedQueryResult.columnNames());
// RowSubscriber subscriber = new RowSubscriber();
//streamedQueryResult.subscribe(subscriber);
}).exceptionally(e -> {
System.out.println("Push query request failed: " + e);
return null;
});
Exception details:
Exception in thread "main" java.util.concurrent.ExecutionException: io.confluent.ksql.api.client.exception.KsqlClientException: Received 404 response from server: HTTP 404 Not Found. Error code: 40400
at java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
at java.util.concurrent.CompletableFuture.geta(Unknown Source)
at my.ksqldb.app.KSQLExampleApp.main(KSQLExampleApp.java:55)

How to handle UndeliverableException error thrown via blockingFirst() in Micronaut?

Below is a snippet from my micronaut web service:
try {
val result = hClient.exchange(GET<String>("$readEndpoint/$token")).blockingFirst()
logger.error("result")
} catch (e: Exception) {
logger.error(e.message)
}
hClient is a reactive http client injected as #Inject val hClient: RxHttpClient
The endpoint is throwing "Connection reset by peer" exception.
Issue I am facing
Even though I have wrapped code in try and catch, An exception io.reactivex.exceptions.UndeliverableException is thrown and not caught.
I basically get two exceptions thrown, one is caught by catch block with message Error occurred reading HTTP response: Connection reset by peer, another one is flowing up to service with message io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.nio.channels.ClosedChannelException
Reproducible via below code
Keep timeout too less to receive a timeout error.
micronaut:
http:
client:
read-timeout: 1s
#Controller("/")
class TokenController(
#Client("https://hello123456789.com/dummy") #Inject val hClient: RxHttpClient
) {
#Get("/test")
fun refresh(): String {
try {
val result = hClient.exchange(HttpRequest.GET<String>("/token/1234")).blockingFirst()
println("result")
} catch (e: Exception) {
println(e.message)
}
return ""
}
}
Googling told me that I need to add global onError to rxjava but couldn't find how to do that in Micronaut.
Any help is appreciated.