I have a Java application which uses Spring's RestTemplate API to write concise, readable consumers of JSON REST services:
In essence:
RestTemplate rest = new RestTemplate(clientHttpRequestFactory);
ResponseEntity<ItemList> response = rest.exchange(url,
HttpMethod.GET,
requestEntity,
ItemList.class);
for(Item item : response.getBody().getItems()) {
handler.onItem(item);
}
The JSON response contains a list of items, and as you can see, I have have an event-driven design in my own code to handle each item in turn. However, the entire list is in memory as part of response
, which RestTemplate.exchange()
produces.
I would like the application to be able to handle responses containing large numbers of items - say 50,000, and in this case there are two issues with the implementation as it stands:
- Not a single item is handled until the entire HTTP response has been transferred - adding unwanted latency.
- The huge response object sits in memory and can't be GC'd until the last item has been handled.
Is there a reasonably mature Java JSON/REST client API out there that consumes responses in an event-driven manner?
I imagine it would let you do something like:
RestStreamer rest = new RestStreamer(clientHttpRequestFactory);
// Tell the RestStreamer "when, while parsing a response, you encounter a JSON
// element matching JSONPath "$.items[*]" pass it to "handler" for processing.
rest.onJsonPath("$.items[*]").handle(handler);
// Tell the RestStreamer to make an HTTP request, parse it as a stream.
// We expect "handler" to get passed an object each time the parser encounters
// an item.
rest.execute(url, HttpMethod.GET, requestEntity);
I appreciate I could roll my own implementation of this behaviour with streaming JSON APIs from Jackson, GSON etc. -- but I'd love to be told there was something out there that does it reliably with a concise, expressive API, integrated with the HTTP aspect.