Java HTTP Client Request with defined timeout
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
...
// set the connection timeout value to 30 seconds (30000 milliseconds)
final HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
client = new DefaultHttpClient(httpParams);
Java HTTP Client request set timeout
Apache's HttpClient
has two separate timeouts: a timeout for how long to wait to establish a TCP connection, and a separate timeout for how long to wait for a subsequent byte of data.
HttpConnectionParams.setConnectionTimeout()
is used for establishing a TCP connection, whereas HttpConnectionParams.setSoTimeout()
is used while waiting for a subsequent byte of data.
// Creating default HttpClient
HttpClient httpClient = new DefaultHttpClient();
final HttpParams httpParams = httpClient.getParams();
// Setting timeouts
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 30000);
// Rest of your code
final HttpPost httppost = new HttpPost(address);
httppost.setHeader("Accept", "text/xml");
httppost.setHeader("Content-type", "application/xml; charset=UTF-8");
httppost.setEntity(new StringEntity(body));
final HttpResponse response = httpclient.execute(httppost);
final HttpEntity entity = response.getEntity();
How to set socket timeout in Java HTTP Client
You can specify it at the HttpRequest.Builder
level via the timeout method:
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("..."))
.timeout(Duration.ofSeconds(5)) //this
.build();
httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
If you've got connected successfully but not able to receive a response at the desired amount of time, java.net.http.HttpTimeoutException: request timed out
will be thrown (in contrast with java.net.http.HttpConnectTimeoutException: HTTP connect timed out
which will be thrown if you don't get a successful connection).
Using Apache HttpClient how to set the TIMEOUT on a request and response
The exceptions you'll see will be ConnectTimeoutException
and SocketTimeoutException
. The actual timeout values you use should be the maximum time your application is willing to wait. One important note about the read timeout is that it corresponds to the timeout on a socket read. So it's not the time allowed for the full response to arrive, but rather the time given to a single socket read. So if there are 4 socket reads, each taking 9 seconds, your total read time is 9 * 4 = 36 seconds.
If you want to specify a total time for the response to arrive (including connect and total read time), you can wrap the call in a thread and use a thread timeout for that. For example, I usually do something like this:
Future<T> future = null;
future = pool.submit(new Callable<T>() {
public T call() {
return executeImpl(url);
}
});
try {
return future.get(10, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.warn("task interrupted", name);
}
catch (ExecutionException e) {
log.error(name + " execution exception", e);
}
catch (TimeoutException e) {
log.debug("future timed out", name);
}
Some assumptions made in the code above are: 1) this is in a function with a url parameter, 2) it's in a class with a name variable, 3) log is a log4j instance, and 4) pool is a some thread pool executor. Note that even if you use a thread timeout, you should also specify a connect and socket timeout on the HttpClient, so that slow requests don't eat up the resources in the thread pool. Also note that I use a thread pool because typically I use this in a web service so the thread pool is shared across a bunch of tomcat threads. You're environment may be different, and you may prefer to simply spawn a new thread for each call.
Also, I've usually see the timeouts set via member functions of the params, like this:
params.setConnectionTimeout(10000);
params.setSoTimeout(10000);
But perhaps your syntax works as well (not sure).
Java net HttpClient: React to timeout in async call
Depending on what you are trying to do, there are at least three methods that you could use to take action when an exception occurs:
- CompletableFuture.exceptionally
- CompletableFuture.whenComplete
- CompletableFuture.handle
- 1 allows you to return a result of the same type when an exception occurs
- 2 allows you to trigger some action - and doesn't change the completion
result or exception. - 3 allows you to trigger some action, and change the type of the completion
result or exception
By far the easiest would be to use 2. Something like:
client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream())
.whenComplete((r,x) -> {
if (x instanceof HttpTimeoutException) {
// do something
}
});
HttpClient request succeeds with timeout defined, but hangs without
I found the answer! Turns out HttpClient only allows a certain number of connections at a time. According to my code, the default maximum connections is 2. I needed to close each connection after they were complete and the upload ran fine.
Fixed code adds request connection release.
private void uploadParts(String assetId) throws IOException {
//set up post request
HttpClient client = HttpClientBuilder.create().build();
String url = "";
//prepare video
File video = new File("files/video.mp4");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(video));
int partMaxSize = 1024 * 1024 * 5;
byte[] buffer = new byte[partMaxSize];
double fileSize = video.length();
System.out.println(fileSize);
System.out.println(fileSize / partMaxSize);
int parts = (int) Math.ceil(fileSize / partMaxSize);
System.out.println(parts);
for(int i = 1; i < parts+1; i++) {
String partNumber = i + "";
System.out.println("part: " + partNumber);
int partSize = (int) (i < parts ? partMaxSize : fileSize);
fileSize -= partSize;
int tmp = 0;
tmp = bis.read(buffer);
url = String.format("https://www.site.com/upload/multipart/%s/%s", assetId, partNumber);
final HttpPut request = new HttpPut(url);
request.addHeader("Authorization", "Bearer " + accessToken);
request.addHeader("Content-Type", "application/octet-stream");
request.setEntity(new ByteArrayEntity(buffer));
//Magical code start
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
if (request != null) {
request.abort();
}
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
//Magical code end
HttpResponse response = client.execute(request);
request.releaseConnection();
System.out.println(response.getStatusLine().getReasonPhrase());
}
bis.close();
}
The timer was working because it was closing my old connections after 10 seconds. Thank you for your input, guys.
Related Topics
What Is the Replacement for Javax.Activation Package in Java 9
Java/Convert Iso-8601 (2010-12-16T13:33:50.513852Z) to Date Object
Pageloadtimeout in Selenium Not Working
Get Declared Fields of Java.Lang.Reflect.Fields in Jdk12
How to Call a Method in Another Class of the Same Package
Javamail API to Imail -- Java.Net.Socketexception: Permission Denied: Connect
What Is Java Pojo Class, Java Bean, Normal Class
Access Restriction: Is Not Accessible Due to Restriction on Required Library ..\Jre\Lib\Rt.Jar
Rounding a Double to Turn It into an Int (Java)
Java.Util.Zip - Recreating Directory Structure
Composing Swing Components: How to Add the Ability to Add Actionlisteners
How to Configure Tomcat to Connect with MySQL
Arraylist's Custom Contains Method
Java.Lang.Stackoverflowerror While Using a Regex to Parse Big Strings
How to Define Multiple Jbutton Actions from a Different Class
Class Not Found with Ant, Ivy and Junit - Error in Build.Xml