How to handle HTTP timeout? - java

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!

Related

WebSocket connection can't reconnect after some time

I wrote some logic which represent near 200 websocet connection with exchange at the same time.I use third party api and it based on org.eclipse.jetty.websocket.api. I have this method which i had to override.
try {
URI uri = new URI(websocketBaseUrl + url);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustAll(true);
WebSocketClient client = new WebSocketClient(sslContextFactory);
client.setMaxIdleTimeout(0);
client.start();
return client.connect(adapter, uri).get();
} catch (URISyntaxException e) {
throw new BinanceApiException("URL Syntax error: " + e.getMessage());
} catch (Throwable e) {
throw new BinanceApiException("Websocket error: " + e.getMessage());
}
I added setIdleTimeout to it so that the connection is not lost when i don't recieve information for a long time.
Exchange close connection one time a day but for 2,3 sometimes 4 days it have been reconnected.But finally i get this:
java.nio.channels.ClosedChannelException: null at
org.eclipse.jetty.io.WriteFlusher.onClose(WriteFlusher.java:507) at
org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onIncompleteFlush(SslConnection.java:527)
at
org.eclipse.jetty.io.AbstractEndPoint$2.onIncompleteFlush(AbstractEndPoint.java:54)
at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:331) at
org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:372)
at
org.eclipse.jetty.websocket.common.io.FrameFlusher$Flusher.flush(FrameFlusher.java:153)
at
org.eclipse.jetty.websocket.common.io.FrameFlusher$Flusher.process(FrameFlusher.java:217)
at
org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
at
org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
at
org.eclipse.jetty.websocket.common.io.FrameFlusher.enqueue(FrameFlusher.java:382)
at
org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.outgoingFrame(AbstractWebSocketConnection.java:614)
at
org.eclipse.jetty.websocket.client.io.WebSocketClientConnection.outgoingFrame(WebSocketClientConnection.java:72)
at
org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onConnectionStateChange(AbstractWebSocketConnection.java:473)
at
org.eclipse.jetty.websocket.common.io.IOState.notifyStateListeners(IOState.java:184)
at
org.eclipse.jetty.websocket.common.io.IOState.onReadFailure(IOState.java:498)
at
org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.readParse(AbstractWebSocketConnection.java:666)
at
org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:511)
at
org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104)
at
org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:289)
at
org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:149)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104)
at
org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
at
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
at
org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:243)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679)
at
org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:597)
at java.lang.Thread.run(Thread.java:748)
I find this question on stackoverflow but i can't see clear answer. Pls help.Thanks in advance.
If you want the connection to stay open if idle, you should configure your client this way:
client.setMaxIdleTimeout(Long.MAX_VALUE);
Setting maxIdleTimeout to 0 would have the opposite effect: Closing the connection as soon as it becomes idle.

Vertx HttpClientRequest - Unable to catch timeout exception

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.

Set timeout on an FTP Connect in Java

Im trying to set a timeout on an FTP Connect using com.enterprisedt.net.ftp.FTPClient but for some reason can't get it to work.
This is my code:
public boolean testFtpDetails(String path) {
boolean success = false;
try {
FTPClient ftp = new FTPClient();
ftp.setRemoteHost("210.160.1.100");
ftp.setTimeout(3000);
ftp.connect();
ftp.login("test", "test");
success = ftp.connected();
if (success && path != null) {
ftp.chdir(path);
}
ftp.quit();
} catch (UnknownHostException e) {
} catch (IOException e) {
} catch (FTPException e) {
}
So after 3 seconds of trying to execute ftp.connect() I would expect it to timeout. However this does not happen and it takes around 15 seconds to timeout. Is there a way to change this?
Thanks,
the setTimeout method is documented as:
Set the SO_TIMEOUT in milliseconds on the underlying socket.
In this way it only affects the low level socket operations. The questions would be - what kind of timeout are you expecting to happen?
On connect ? During transfer? On idle?
If you connect to e.g. an unknown host you will also have DNS lookup taking most of the time before the timeout is even considered.

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.

Registering with a URL for asynchronous notifications?

I am trying to understand more about async notifications. I have a URL in the form of:
http://www.sample.com/AsyncNotify?sessionId=xxxxxx
Now if I call this URL with the sessionId, it is equivalent to registering for Asynchronous notifications. I am using Apache HTTP Commons library to do Http Post and Get. If that's the case, then how can I receive events from the server side? Do I have to forget this approach and use sockets instead? Currently, this is my approach:
HttpClient httpClient = new HttpClient;
String url = "http://www.sample.com/AsyncNotify?sessionId=xxxxxx"
GetMethod get = new GetMethod(url);
try {
httpClient.executeMethod(get);
//read the response
} catch(Exception e) {
}
What I was thinking was to establish a socket level connection inside a while loop and call a handler whenever it receives some data, but is there a better way to achieve this?
EDIT:
I've used xSocket to get to the following stage but the connection closes after 30 seconds:
try {
String _GETRequest = "/sample/notify";
HttpClientConnection con = new HttpClientConnection("10.0.0.23", 5050);
con.setConnectionTimeoutMillis(100000);
GetRequest request = new GetRequest(_GETRequest);
request.setParameter("id", id);
IHttpResponseHandler responseHandler = new AsyncHandler();
con.send(request, responseHandler);
org.xlightweb.client.HttpClient httpClient = new org.xlightweb.client.HttpClient();
request.setParameter("id", id);
con.send(request, responseHandler);
// Don't let the program terminate. In other words,
// wait for a message from the server
while(con.isOpen()) {};
if(!con.isOpen()) {
}
} catch (ConnectException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Tomcat came out with a technology called Tomcat Comet ( http://tomcat.apache.org/tomcat-6.0-doc/aio.html ). It has also been used for the new Servlet 3.0 spec. This technology will allow you to do persistent HTTP connections through which you can push notifications to any clients.
There is also a technolgy called WebSockets that is part of HTML 5
( http://dev.w3.org/html5/websockets/ ) Of course it only works in a limied set of browsers for now. Probably should wait on this.
Of course the current way to do it to be technolgy backwards compatible (even if it sucks) is to poll the server periodically and get results that way.
Of course if everybody (clients and servers) are on a local network then probably something like RMI or even EJBs or JMS Pub/Sub would be best.
Here is a Comet tutorial http://www.ibm.com/developerworks/web/library/wa-cometjava/index.html and another one http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp-test.html

Categories