I am working on an api to make batch requests through HTTP. Suggested by this (How to make batch http call in java), I decided to use Multithreading.
Here is the implementation:
public class GetItems {
//Control the number of connections made to the server.
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(120);
cm.setDefaultMaxPerRoute(30);
HttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
//Using concurrent map to store the result from different threads
private Map<String, ItemAttributesFromDatapath> itemDataMap = Maps.newConcurrentMap();
//requests' batch
private List<Request> requests;
public List<String> call() {
List<Thread> threads = Lists.newArrayList();
requests.forEach(request -> {
Thread thread = new Thread(new GetTask(client, request));
thread.start();
threads.add(thread);
});
threads.forEach(thread -> {
try {
thread.join();
} catch (Exception ex) {
LOGGER.error(ex);
}
});
}
//Inner class for multi-thread.
public class GetTask implements Runnable{
private CatalogHttpRequest request;
private CatalogHttpClient client;
private String asin;
public GetTask(HttpClient client, final HttpRequest request) {
this.request = request;
this.client = client;
}
@Override
public void run(){
try{
HttpResponse response = client.executeHttpRequest(request);
try {
if (response.isOK()) {
//some logic here
String item = handle(response)
itemDataMap.put(itemId, item);
} else {
String message = "Is Client Error";
LOGGER.error(message);
}
} catch (Exception ex){
LOGGER.error(ex.getMessage());
}
} catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
}
}
Then I tried to write unit-test,
@Test
public void testBatchRequest() throws Exception{
HttpClient = mockClient(...);
GetItems batch = new GetItems(...);
List<String> ret = batch.call();}
Inside mockClient method, I mock some class using Mockito:
private HttpClient mockSuccessfulClient(InputStream responseStream, int code) throws IOException{
HttpEntity entity = Mockito.mock(HttpEntity.class);
when(entity.getContent()).thenReturn(responseStream);
HttpResponse response = Mockito.mock(CloseableHttpResponse.class);
when(response.getEntity()).thenReturn(entity);
StatusLine statusLine = Mockito.mock(StatusLine.class);
when(statusLine.getStatusCode()).thenReturn(code);
when(response.getStatusLine()).thenReturn(statusLine);
//CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class);
//when(httpClient.execute(any())).thenReturn(response);
CatalogHttpClient client = Mockito.mock(HttpClient.class);
when(client.executeHttpRequest(any())).thenReturn(response);
return client;
}
For the unit-test right now, the return list is empty, which is incorrect.
I tried to debug the code by setting up breaking point and found the main code didn't execute run() method inside GetTask when thread starts.
Since I am not familiar with multi-thread stuff. This problem may seem dumb to you, but can you help me figure out what's wrong in my code and how to write the proper test for my case.
Also, I am not sure if the ConcurrentMap is a good practice to store the results across multiple threads?