Vertx HttpClientRequest - Unable to catch timeout exception - java

I have been unable to catch time out exception that happens in my vertx HttpClientRequest. I have enclosed my connection and request creation code in try-catch block. Also I have added exceptionHandler and endHandler. But none of them gets fired when the time out happens. All I receive is the below error message which gets printed on the console. Please give me idea how to catch this exception, so that I can call the caller back with relevant info.
io.vertx.core.http.impl.HttpClientRequestImpl
SEVERE: io.netty.channel.ConnectTimeoutException: connection timed out:
The code below is what I use to make request to server. As you can see I have used try-catch and added exceptionHandler as well.
try{
HttpClient httpClient = Vert.x.createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true).setVerifyHost(false));
HttpClientRequest request = httpClient.get(port, host, uri.getRawPath(), event-> {
event.exceptionHandler(e -> {
log.error(" Error:: " + e);
});
event.handler(handler -> {
//code
});
});
request.putHeader(HttpHeaders.Names.AUTHORIZATION, "Basic "+authEnc);
request.end();
} catch(Exception e){
log.error(" Exception :: " + e);
}

Due to the async programing model you won't be able to use try-catch since your method has long been terminated before you get the timeout event. In order to catch it you need to setup an exception handler like:
request.exceptionHandler(t -> {
// where t is a throwable
// do something with it...
}
If you're interested in catching response exceptions same concept applies.

Related

ContextException: Unknown Ban can't be caught (Discord Java)

My unban command sometimes throws a ContextException, when you unban a person who wasn't banned.
I wanted to catch it with a try catch block to notify the user that the person they are trying to unban isn't banned. This is what I tried:
try {
event.getGuild().unban(event.getMessage().getContentRaw().substring(8)).queue();
} catch(ContextException e) {
event.getChannel().sendMessage("This user isn't banned!").queue();
return;
}
But the catch() line just says Exception 'net.dv8tion.jda.api.exceptions.ContextException' is never thrown in the corresponding try block.
Your exception, in this case isn't even a ContextException but an ErrorResponseException. Since queue(...) does asynchronous operations in a different thread, the exceptions cannot be thrown from here. Instead, you should use the failure callback as described by the documentation.
You can use ErrorHandler to handle specific ErrorResponses.
Example:
String userId = event.getMessage().getContentRaw().substring(8);
ErrorHandler handler = new ErrorHandler().handle(ErrorResponse.UNKNOWN_BAN, (error) -> {
event.getChannel().sendMessage("This user isn't banned!").queue();
});
event.getGuild()
.unban(userId)
.queue(null, handler);
The ContextException is only there to tell you where in your code the error originated from. Since the actual exception happens on other threads which give you no context to find the issue.
ContextException handles async exception. So your try block cannot catch the exception.
You can change your code like this.
event.getGuild().unban(event.getMessage().getContentRaw().substring(8)).queue(
null,
(error) -> {
if (error.getMessage().equals("10026: Unknown Ban")) {
event.getChannel().sendMessage("This user isn't banned!").queue();
}
}
);

Looking for ways to detect AWS Lambda timeouts(few seconds before timeout) in Java and to test the same

My current Lambda function is calling a 3rd party web service Synchronously.This function occasionally times out (current timeout set to 25s and cannot be increased further)
My code is something like:
handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
try{
response = calling 3rd party REST service
}catch(Exception e){
//handle exceptions
}
}
1)I want to custom handle the timeout (tracking the time and handling few milli seconds before actual timeout) within my Lambda function by sending a custom error message back to the client.
How can I effectively use the
context.getRemainingTimeInMillis()
method to track the time remaining while my synchronous call is running? Planning to call the context.getRemainingTimeInMillis() asynchronously.Is that the right approach?
2)What is a good way to test the timeout custom functionality ?
I solved my problem by increasing the Lambda timeout and invoking my process in a new thread and timing out the Thread after n seconds.
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = () ->{
try {
myFunction();
} catch (Exception e) {
e.printStackTrace();
}
};
f = service.submit(r);
f.get(n, TimeUnit.MILLISECONDS);// attempt the task for n milliseconds
}catch(TimeoutException toe){
//custom logic
}
Another option is to use the
readTimeOut
property of the RestClient(in my case Jersey) to set the timeout.But I see that this property is not working consistently within the Lambda code.Not sure if it's and issue with the Jersey client or the Lambda.
You can try with cancellation token to return custom exceptions with lambda before timeout.
try
{
var tokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1)); // set timeout value
var taskResult = ApiCall(); // call web service method
while (!taskResult.IsCompleted)
{
if (tokenSource.IsCancellationRequested)
{
throw new OperationCanceledException("time out for lambda"); // throw custom exceptions eg : OperationCanceledException
}
}
return taskResult.Result;
}
catch (OperationCanceledException ex)
{
// handle exception
}

How do I catch an NPE and send custom error to Publisher in RxJava

I am doing an rxified version of what is shown here: (https://vertx.io/docs/vertx-amqp-client/java/#_creating_a_receiver).
Basically, the code below gets messages whenever they are received on a connection. Behind the scenes I am simulating a broken connection by stopping the message broker service. This results in the AMQP code throwing an NPE. I would like to catch the NPE and send a better error to the subscriber.
When the NPE occurs I can't seem to capture the error, so I'm unsure how to accomplish this.
public Publisher<Object> receiveAmqpMessages(AmqpConnection connection, String address) {
return connection
.rxCreateReceiver(address)
.flatMapPublisher(receiver ->
receiver.toObservable()
.doFinally(receiver::rxClose)
.onErrorReturn(e-> {
System.out.println("I never see this message");
return null;
}.toFlowable(BackpressureStrategy.BUFFER)
);
}
I tried wrapping it in a try/catch like so but it doesn't go into the catch block
public Publisher<Object> receiveAmqpMessages(AmqpConnection connection, String address) {
try {
// same code shown above
} catch (NullPointerException e) {
System.out.println("I never see this message either");
return Observable.error(new Exception("foo")).toFlowable(BackpressureStrategy.BUFFER);
}
}
FWIW the console looks like this (Note - The console never outputs anything that references my own class file):
SEVERE: Unhandled Exception
java.lang.NullPointerException
at io.vertx.ampq.impl.AmqpConnectionImpl.lambda$createReceiver$8(Line 251)
...
If you open their AmqpConnectionImpl and go to that line of code you see
ProtonReceiver receiver = connection.get().createReceiver(address,opts)
which causes the NPE since connection.get() is null

How to handle HTTP timeout?

In my application, I am downloading JSON data from a ReST web service. Most of the time, this works fine, however sometimes the connection will time out.
This is the code I use to set the timeout...
HttpConnectionParams.setConnectionTimeout( httpParameters, 20000 );
HttpConnectionParams.setSoTimeout( httpParameters, 42000 );
If the connection times out, the application crashes and closes, how do I handle a time out?
The HttpClient class throws a ConnectTimeoutException Exception, so you should listen for it:
try {
HttpResponse response = client.execute(post);
// do something with response
} catch (ConnectTimeoutException e) {
Log.e(TAG, "Timeout", e);
} catch (SocketTimeoutException e) {
Log.e(TAG, " Socket timeout", e);
}
Increase your time of waiting for response like :
HttpConnectionParams.setConnectionTimeout( httpParameters, 60000 ); //1 minute
HttpConnectionParams.setSoTimeout( httpParameters, 90000 ); // 1.5 minute
I have tried to catch a variety of exception types, I have found that catching an IOException worked as I wanted!

ActiveMQ register listener to StompConnection

I'm using a variation of the example at http://svn.apache.org/repos/asf/activemq/trunk/assembly/src/release/example/src/StompExample.java to receive message from a queue. What I'm trying to do is to keep listening to a queue and perform some action upon reception of a new message. The problem is that I couldn't find a way to register a listener to any of the related objects. I've tried something like:
public static void main(String args[]) throws Exception {
StompConnection connection = null;
try {
connection = new StompConnection();
connection.open("localhost", 61613);
connection.connect("admin", "activemq");
connection.subscribe("/queue/worker", Subscribe.AckModeValues.AUTO);
while (true) {
StompFrame message = connection.receive();
System.out.println(message.getBody());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
but this doesn't work as a time out occurs after a few seconds (java.net.SocketTimeoutException: Read timed out). Is there anything I can do to indefinitely listen to this queue?
ActiveMQ's StompConnection class is a relatively primitive STOMP client. Its not capable of async callbacks on Message or for indefinite waits. You can pass a timeout to receive but depending on whether you are using STOMP v1.1 it could still timeout early if a heart-beat isn't received in time. You can of course always catch the timeout exception and try again.
For STOMP via Java you're better off using StompJMS or the like which behaves like a real JMS client and allows for async Message receipt.
#Tim Bish: I tried StompJMS, but couldn't find any example that I could use (maybe you can provide a link). I 'fixed' the problem by setting the timeout to 0 which seems to be blocking.
even i was facing the same issue.. you can fix this by adding time out to your receive() method.
Declare a long type variable.
long waitTimeOut = 5000; //this is 5 seconds
now modify your receive function like below.
StompFrame message = connection.receive(waitTimeOut);
This will definitely work.

Categories