I made a wrapper for an API that I am using, basically what I'm doing is sending in a list of Series
objects and for each item in the list, a thread ("worker"?) starts and fetches information for their respective series.
The API that I'm using doesn't support fetching several series using one request, which would simplify this by a large margin, therefore I run threads for each item in the list.
I'm mostly concerned about the thread part, but I'll provide all the other parts as well.
@RequestMapping(value = "/series", method = RequestMethod.POST)
public List<Response> fetchSeveralSeries(@RequestBody List<Series> list) throws InterruptedException, ExecutionException {
List<Callable<Response>> callableList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
callableList.add(new performRequest(list.get(i).getSeries()));
}
final ExecutorService service = Executors.newFixedThreadPool(list.size());
List<Future<Response>> futureObjects = service.invokeAll(callableList);
List<Response> series = new ArrayList<>();
for (Future<Response> obj : futureObjects) {
series.add(obj.get());
}
return series;
}
Callable class used. (temporarily in my Spring boot controller class, as my entire implementation is in the controller atm.)
private class performRequest implements Callable<Response> {
private int seriesId;
private performRequest(int seriesId) {
this.seriesId = seriesId;
}
@Override
public Response call() throws UnirestException {
return request.send(new Url(seriesId).toString());
}
}
About the request made by each thread, I have a Url
class which constructs the Url for the request and a Request
class which sends the request to the external API.
Request
class which sends the request to external API. The Response
object is a "GSON Object".
@Service
public class Request {
private static final Logger logger = LoggerFactory.getLogger(Request.class);
public Response send(String url) throws UnirestException {
logger.info("sending GET");
HttpResponse<JsonNode> json = Unirest.get(url).asJson();
String body = json.getBody().toString();
return new Gson().fromJson(body, Response.class);
}
}
Url
class which constructs the URL.
@Data
public class Url {
private static final String BASE_URL = "https://api.themoviedb.org/3";
private static final String API_KEY = System.getenv("API_KEY");
private Integer id;
private Integer season;
private Integer episode;
private String searchQuery; // should turn spaces into %20
public Url(String searchQuery) {
this.searchQuery = searchQuery;
}
public Url(Integer id) {
this.id = id;
}
public Url(Integer id, Integer season) {
this.id = id;
this.season = season;
}
public Url(Integer id, Integer season, Integer episode) {
this.id = id;
this.season = season;
this.episode = episode;
}
@Override
public String toString() {
return this.searchQuery != null ?
String.format("%s/search/tv?api_key=%s&language=en-US&query=%s", BASE_URL, API_KEY, this.searchQuery) : this.episode != null ?
String.format("%s/tv/%s/season/%s/episode/%s?api_key=%s&language=en-US", BASE_URL, this.id, this.season, this.episode, API_KEY) : this.season != null ?
String.format("%s/tv/%s/season/%s?api_key=%s&language=en-US", BASE_URL, this.id, this.season, API_KEY) :
String.format("%s/tv/%s?api_key=%s&language=en-US", BASE_URL, this.id, API_KEY);
}
}
An example POST
request body would be something like below:
[
{
"series": 37680
},
{
"series": 53123
},
{
"series": 12345
},
{
"series": 29182
}
]
Could my code be improved somehow? Would it be possible to decrease response time? Is it "thread-safe"?
Any feedback is welcome.