"Timeout while fetching" URLFetch GAE/J - java

I'm using the XMLReader to simply read a feed like below.
URLConnection urlConnection = url.openConnection();
XmlReader reader = new XmlReader(urlConnection);
When this is called I receive within 5 seconds an IOException "Timeout
while fetching". So I tried to set the timeouts to the max. (10 sec) but still no luck and still an IOExeption in 5 sec.
urlConnection.setConnectTimeout(10000);
(the max is stated in documentation: http://code.google.com/intl/nl-NL/appengine/docs/java/urlfetch/overview.html)
Seems that the size of the feed is too large. When I call a smaller feed
it works properly. Is there any workaround or solution for this? I need to be able to call larger feeds.

You should use setReadTimeout method that sets the read deadline:
urlConnection.setReadTimeout(10000); //10 Sec
You should be able to download larger feeds in 10 seconds.
If you still have problem, try to fiddle with this different approach.

The reason is:
If no data is available for the read timeout period, exception can be thrown. From the doc of Oracle
A SocketTimeoutException can be thrown when reading from the returned input stream if the read timeout expires before data is available for read.
By the way, ReadTimeout is different with ConnectTimeout, the read timeout is the timeout to get data from the host, see different connection timeout and read timeout
So as #systempuntoout answer, need to set read timeout.

Related

JavaMail connection timeout is not working as per properties

Javax mail version used 1.6.2
manually setting JavaMailSender
Timeout thing I tried with mail.smtp.timeout & mail.smtps.timeout.
And, I tried with both String & Integer value 3000.
String timeOut = "3000";
Properties pros = new Properties();
pros.put("mail.smtp.timeout", timeOut);
pros.put("mail.smtp.connectiontimeout", timeOut);
pros.put("mail.smtp.writetimeout", timeOut);
pros.put("mail.smtp.auth", "true");
pros.put("mail.smtp.starttls.enable", "true");
jmailSender.setJavaMailProperties(pros);
return jmailSender;
It's taking around 7 seconds without any fail.
Since by default is infinite, so most probably it is not setting somehow
Are any properties missing or something else?
The properties mail.smtp.connectiontimeout and `mail.smtps.connectiontimeout only apply while establishing the connection. It is not related to any timeouts during transport.
The properties mail.smtp.timeout and mail.smtps.timeout are related to the time blocked waiting for a read. This is related to reading SMTP response codes.
The properties mail.smtp.writetimeout and mail.smtps.writetimeout are related to writing chunks of data which can vary in size.
None of these timeouts represent a deadline for a single transaction of sending a mime message. What is happening is that there is no single action (connect, read, write) that is exceeding the 3000ms.
For example, connect could take 1000ms, followed by say 30 requests (write) and response parsing (reads) that take 100ms, and set of say 3 writes to send the message that take 1000ms each due to the speed of the network and size of the message. That is 1000 + (30 * 100) + (3 * 1000) = 7000ms total time but no single action exceeded the timeouts.
In a test environment
Set all timeouts to 3000.
Set connectimeout to 1 and test. You should see the connection fail.
Restart the test by setting it back to 3000 and set timeout to 1. You should see the reads fail.
Restart the test by setting it back to 3000 and set writetimeout to 1. You should see the transport fail.
If the test doesn't act this way you either haven't set the properties correctly (typo or smtp vs. smtps). Or you are really lucky to have such low latency.

How do I make a Java function that retries a URL connection every half second if the connection takes too long?

So I have a problem with a Java program I have. The program's basic functionality includes basically connecting to a web API for data. The function that does that is something like this:
public static Object getData(String sURL) throws IOException {
URL url = new URL(sURL);
URLConnection request = url.openConnection();
request.connect();
return request.getContent();
}
The code works fine as it is, but recently, after my house changed ISPs, I have found that sometimes the connections take an unreasonably long amount of time, something like 10 seconds or more in about 10% of attempts, while the other 90% takes only around 200ms. I have found it to be faster to ask my program to call the function again in a different thread than to wait for some of these connections to finally connect.
Therefore, I want to change the function so that if after 500ms, the connection did not establish, it would disconnect and a new connection would be attempted. How could I do this?
Somewhere online I read that HttpURLConnection might help, but I am not sure how.
URLConnection allows you to specify the connect and read timeout prior to calling connect():
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html#setConnectTimeout(int)
Sets a specified timeout value, in milliseconds, to be used when
opening a communications link to the resource referenced by this
URLConnection. If the timeout expires before the connection can be
established, a java.net.SocketTimeoutException is raised. A timeout of
zero is interpreted as an infinite timeout.
With 500ms timeout:
try {
URLConnection request = url.openConnection();
request.setConnectTimeout(500); // 500 ms
request.connect();
// on successful connection
} catch (SocketTimeoutException ex) {
// on request timeout
}
This you can pack into a loop, but I recommend limiting the number of attempts made.
Java's URLConnection doesn't have retry capabilities in Java 8 therefore the best way here to achieve this - use an appropriate standalone 3-party library such as Apache HttpClient.
This is by far the best standalone 3-party HTTP client with advanced capabilities as of 2020 and it's still maintained.
By default as of version 5.2.x Apache Http Client, Apache Http Client uses the default implementation of org.apache.http.client.HttpRequestRetryHandler, which retries 3 times, but you can use a custom implementation instead.
The configuration might look like this(full imports are for example's sake):
org.apache.http.client.HttpClient httpClient = org.apache.http.impl.client.HttpClients.custom()
.setRetryHandler(YourCustomImplOfTheRetryHandlerClass)
//other config
.build();
There is no way I can reproduce that problem using my ISP.
I suggest you dig deeper into the problem and find a better solution. Sending another request just doesn't seem good enough to me. Maybe try a different way to get the data and see if that works for you. Can't say for sure as I can't reproduce the problem.

How the URLConnection.connectionTimeout is handled?

Given the code:
HttpURLConnection huc = (HttpURLConnection) new URL( url ).openConnection();
huc.setConnectTimeout( 10000 );
huc.connect();
how exactly the connection timeout is processed? Some HTTP header gets set or what? Or the connection status is being checked in a loop for connectionTimeout time?
I tried to find it in the source code, but there is only the long connectionTimout field...
Think of it as:
Inside connect first a parallel timer is run for the the connection timeout.
If the timer ends before the actual connection is established (response received), then fail.
In reality on most platforms the operating system can be parametrised with a timeout and will handle it oneself - in the same manner.
Not having seen the java native code, but there are POSIX methods like setsocketopt with which to set timeouts. POSIX connect will give a timeout.
In java the timeout was a later much desired addition to utilize these available timeouts.

SocketTimeoutException when ConnectTimeout and ReadTimeout is infinite? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Receiving request timeout even though connect timeout and read timeout is set to default (infinite)?
I tried to connect to a web service and received a SocketTimeoutException after approximately 20 seconds. The Tomcat server hosting the web service is down so the Exception is expected. However, I did not set the value of my ConnectTimeout and ReadTimeout. According to the documentation, the default values of these two are infinite.
One possibility for this is that the server I tried connecting to has its own timeout. But when my friend tried to connect to it using iOS, his connection timed out after approximately 1 minute and 15 seconds. If the server is the one issuing the timeout, our connection should have timed out at almost the same time. Please note that he is also using the default time out of iOS.
Why did my socket timed out so early when my connect and read timeout are set to infinite?
Is socket timeout different to connect and read timeout? If so, how is it different?
How can I know the value of my socket timeout? I am using HttpURLConnection.
Is there a way to set the socket timeout? How?
Below is a snippet of my code:
httpURLConnection = (HttpURLConnection) ((new URL("http://www.website.com/webservice")).openConnection());
httpURLConnection.setDoInput(isDoInput);
httpURLConnection.setDoOutput(isDoOutput);
httpURLConnection.setRequestMethod(method);
try
{
OutputStreamWriter writer = new OutputStreamWriter(httpURLConnection.getOutputStream());
writer.write("param1=value1");
writer.flush;
}catch(Exception e)
{
}
Why did my socket timed out so early when my connect and read timeout are set to infinite?
Code please.
Is socket timeout different to connect and read timeout? If so, how is it different?
SocketTimeoutException is a read timeout.
How can I know the value of my socket timeout? I am using HttpURLConnection.
HttpURLConnection.getReadTimeout(); also HttpURLConnection.getConnectTimeout().
Is there a way to set the socket timeout? How?
HttpURLConnection.setReadTimeout().
You have already cited all these methods in your original post. Why are you asking about them here?
Finally, I found what causing my timeout! It turns out that it is indeed the server who is causing my timeout. I doubt on this one at first because I am receiving a different timeout when using iOS which is more than 1 minute.
So here it is:
The operating system holding my Tomcat server is Windows. Windows' default number of retries for unanswered connection is 2. So when your first attempt to connect fails, you still have 2 retries left. The retries are all done internally. I'm not sure how the time for each retry is calculated but basically it's 3 + 6 + 12 = 21 seconds.
1st retry = 3 seconds
2nd retry = 6 seconds
3rd retry = 12 seconds
After the 3rd retry, your connection will be cut-off. Also, by that time, you already waited for 21 seconds.

Safe use of HttpURLConnection

When using HttpURLConnection does the InputStream need to be closed if we do not 'get' and use it?
i.e. is this safe?
HttpURLConnection conn = (HttpURLConnection) uri.getURI().toURL().openConnection();
conn.connect();
// check for content type I don't care about
if (conn.getContentType.equals("image/gif") return;
// get stream and read from it
InputStream is = conn.getInputStream();
try {
// read from is
} finally {
is.close();
}
Secondly, is it safe to close an InputStream before all of it's content has been fully read?
Is there a risk of leaving the underlying socket in ESTABLISHED or even CLOSE_WAIT state?
According to http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html
and OpenJDK source code.
(When keepAlive == true)
If client called HttpURLConnection.getInputSteam().close(), the later call to HttpURLConnection.disconnect() will NOT close the Socket. i.e. The Socket is reused (cached)
If client does not call close(), call disconnect() will close the InputStream and close the Socket.
So in order to reuse the Socket, just call InputStream.close(). Do not call HttpURLConnection.disconnect().
is it safe to close an InputStream
before all of it's content has been
read
You need to read all of the data in the input stream before you close it so that the underlying TCP connection gets cached. I have read that it should not be required in latest Java, but it was always mandated to read the whole response for connection re-use.
Check this post: keep-alive in java6
Here is some information regarding the keep-alive cache. All of this information pertains Java 6, but is probably also accurate for many prior and later versions.
From what I can tell, the code boils down to:
If the remote server sends a "Keep-Alive" header with a "timeout" value that can be parsed as a positive integer, that number of seconds is used for the timeout.
If the remote server sends a "Keep-Alive" header but it doesn't have a "timeout" value that can be parsed as a positive integer and "usingProxy" is true, then the timeout is 60 seconds.
In all other cases, the timeout is 5 seconds.
This logic is split between two places: around line 725 of sun.net.www.http.HttpClient (in the "parseHTTPHeader" method), and around line 120 of sun.net.www.http.KeepAliveCache (in the "put" method).
So, there are two ways to control the timeout period:
Control the remote server and configure it to send a Keep-Alive header with the proper timeout field
Modify the JDK source code and build your own.
One would think that it would be possible to change the apparently arbitrary five-second default without recompiling internal JDK classes, but it isn't. A bug was filed in 2005 requesting this ability, but Sun refused to provide it.
If you really want to make sure that the connection is close you should call conn.disconnect().
The open connections you observed are because of the HTTP 1.1 connection keep alive feature (also known as HTTP Persistent Connections).
If the server supports HTTP 1.1 and does not send a Connection: close in the response header Java does not immediately close the underlaying TCP connection when you close the input stream. Instead it keeps it open and tries to reuse it for the next HTTP request to the same server.
If you don't want this behaviour at all you can set the system property http.keepAlive to false:
System.setProperty("http.keepAlive","false");
When using HttpURLConnection does the InputStream need to be closed if we do not 'get' and use it?
Yes, it always needs to be closed.
i.e. is this safe?
Not 100%, you run the risk of getting a NPE. Safer is:
InputStream is = null;
try {
is = conn.getInputStream()
// read from is
} finally {
if (is != null) {
is.close();
}
}
You also have to close error stream if the HTTP request fails (anything but 200):
try {
...
}
catch (IOException e) {
connection.getErrorStream().close();
}
If you don't do it, all requests that don't return 200 (e.g. timeout) will leak one socket.
Since Java 7 the recommended way is
try (InputStream is = conn.getInputStream()) {
// read from is
// ...
}
as for all other classes implementing Closable. close() is called at the end of the try {...} block.
Closing the input stream also means you are done with reading. Otherwise the connection hangs around until the finalizer closes the stream.
Same applies to the output stream, if you are sending data.
There is no need to get an close the ErrorStream. Even if it implements the InputStream interface: It's using the InputStream in combination with a buffer. Closing the InputStream is sufficient.

Categories