I have a SwingWorker
that gets a list of URLs (can be several hundred). In the doInBackground()
method it loops through these URLs, creates each time a CloseableHttpClient
, managed by a PoolingHttpClientConnectionManager
, and a HttpGet
.
The client
will then execute the httpGet
and write the content (image) to a file (if possible! Not all URLs are valid and some return a 404
).
This works for approximately 100 requests just until the maxTotal
(or the defaultMaxPerRoute
) of the connectionManager is reached. Then everything stops, the client's execution stops and no Exception gets thrown.
So I figured, I'd set the maxTotal
and the defaultMaxPerRoute
to 1000
and check it out. It works when I try downloading 1500 images, but it just feels so wrong! I want to reuse the clients instead of having 1000 of them in a pool.
Socket- or ConnectionTimeouts didn't work, Debugging does not tell me what is happening and creating new HttpClients
without the PoolingHttpClientConnectionManager
doesn't work either. Closing the clients and/or the results does not work either.
How should I manage the clients or setup the pool to make sure that my SwingWorker
could even download thousands of images?
I'll try to break down my SwingWorker
code to the important parts:
(Almost forgot, it's actually a list of objects that's looped and each object has 3 URLs)
// this is how I init the connectionManager (outside the swing worker)
this.connectionManager = new PoolingHttpClientConnectionManager();
this.connectionManager.setMaxTotal(100);
this.connectionManager.setDefaultMaxPerRoute(100);
// this is where the images are downloaded in the swing worker
@Override
protected Void doInBackground() throws Exception{
for(MyUrls myUrls : myUrlsList){
client = HttpClients.custom().setConnectionManager(connectionManager).build();
for(MyImage image : myUrls.getImageList()){
File outputFile = null;
HttpEntity entity = null;
switch(image.getImageSize()){
case 1:
HttpGet httpGet = new HttpGet(image.getUrl()));
httpGet.setConfig(RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1000).build()); // doesn't change anything
response = client.execute(httpGet);
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
entity = response.getEntity();
if(entity != null){
String contentType = entity.getContentType().getValue();
String extension = "." + (contentType.contains("/") ? contentType.substring(contentType.indexOf("/") + 1) : "jpg");
outputFile = new File(image.getName()+extension);
}
}else{
System.err.println("download of "+image.getName()+extension+" failed: " + response.getStatusLine().getStatusCode());
}
break;
case 2:
// the other cases are pretty much the same
}
if(entity != null && outputFile != null){
try(InputStream inputStream = entity.getContent(); FileOutputStream outputStream = new FileOutputStream(outputFile)){
byte[] buffer = new byte[1024];
int bytesRead;
while((bytesRead = inputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, bytesRead);
}
}
}
}
}
}