We live in a small, wonderful world where everybody is interconnected and impatient! We are interconnected through technology and applications, such as social networks, Internet banking, telephones, chats, and so on. Likewise, our applications are interconnected; often, an application housed in India may need to query an external service hosted in Philadelphia to get some significant information.
We are impatient as we expect everything to be done in seconds; we get frustrated when we make an HTTP call to a remote service, and this blocks the processing unless the remote response is back. We cannot finish everything in milliseconds or nanoseconds, but we can process long-running tasks asynchronously or in a separate thread, allowing the user to work on something else.
To handle RESTful web service calls asynchronously, Spring offers two useful classes: AsyncRestTemplate
and ListenableFuture
. We can make an async call using the template and get Future
back and then continue with other processing, and finally we can ask Future
to get the result.
This section builds an asynchronous RESTful client to query the RESTful web service we developed in the preceding section. The AsyncRestTemplate
class defines an array of overloaded methods to access RESTful web services asynchronously. We'll explore the exchange
and execute
methods.
The following are the steps to explore the template:
com.packt.rest.template
.AsyncRestTemplateTest
JUnit test.exchange()
test method and add the following lines:@Test public void exchange(){ AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(); String url ="http://localhost:8080/RESTfulWeb/hello/all/"; HttpMethod method = HttpMethod.GET; Class<String> responseType = String.class; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); HttpEntity<String> requestEntity = new HttpEntity<String>("params", headers); ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.exchange(url, method, requestEntity, responseType); try { //waits for the result ResponseEntity<String> entity = future.get(); //prints body of the given URL System.out.println(entity.getBody()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
The exchange()
method has six overloaded versions. We used the method that takes a URL, an HttpMethod
method such as GET
or POST
, an HttpEntity
method to set the header, and finally a response type class. We called the exchange
method, which in turn called the execute
method and returned ListenableFuture
. The ListenableFuture
is the handle to our output; we invoked the GET
method on ListenableFuture
to get the RESTful service call response. The ResponseEntity
has the getBody
, getClass
, getHeaders
, and getStatusCode
methods for extracting the web service call response.
We invoked the http://localhost:8080/RESTfulWeb/hello/all/
URL and got back the following response:
execute
test method and add the following lines:@Test public void execute(){ AsyncRestTemplate asyncTemp = new AsyncRestTemplate(); String url ="http://localhost:8080/RESTfulWeb/hello/reader"; HttpMethod method = HttpMethod.GET; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); AsyncRequestCallback requestCallback = new AsyncRequestCallback (){ @Override public void doWithRequest(AsyncClientHttpRequest request) throws IOException { System.out.println(request.getURI()); } }; ResponseExtractor<String> responseExtractor = new ResponseExtractor<String>(){ @Override public String extractData(ClientHttpResponse response) throws IOException { return response.getStatusText(); } }; Map<String,String> urlVariable = new HashMap<String, String>(); ListenableFuture<String> future = asyncTemp.execute(url, method, requestCallback, responseExtractor, urlVariable); try { //wait for the result String result = future.get(); System.out.println("Status =" +result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
The execute
method has several variants. We invoke the one that takes a URL, HttpMethod
such as GET
or POST
, an AsyncRequestCallback
method which is invoked from the execute
method just before executing the request asynchronously, a ResponseExtractor
to extract the response, such as a response body, status code or headers, and a URL variable such as a URL that takes parameters. We invoked the execute
method and received a future, as our ResponseExtractor
extracts the status code. So, when we ask the future to get the result, it returns the response status which is OK
or 200
. In the AsyncRequestCallback
method, we invoked the request URI; hence, the output first displays the request URI and then prints the response status.
The following is the output:
18.191.210.205