10.6 Calling REST Services with HttpClient

Calling Grails REST services - as well as third-party services - is very straightforward using the Micronaut HTTP Client. This HTTP client has both a low-level API and a higher level AOP-driven API, making it useful for both simple requests as well as building declarative, type-safe API layers.

To use the Micronaut HTTP client you must have the micronaut-http-client dependency on your classpath. Add the following dependency to your build.gradle file.

build.gradle

  1. compile 'io.micronaut:micronaut-http-client'

Low-level API

The HttpClient interface forms the basis for the low-level API. This interfaces declares methods to help ease executing HTTP requests and receive responses.

The majority of the methods in the HttpClient interface returns Reactive Streams Publisher instances, and a sub-interface called RxHttpClient is included that provides a variation of the HttpClient interface that returns RxJava Flowable types. When using HttpClient in a blocking flow, you may wish to call toBlocking() to return an instance of BlockingHttpClient.

There are a few ways by which you can obtain a reference to a HttpClient. The most simple way is using the create method

Creating an HTTP client

  1. List<Album> searchWithApi(String searchTerm) {
  2. String baseUrl = "https://itunes.apple.com/"
  3. HttpClient client = HttpClient.create(baseUrl.toURL()).toBlocking() (1)
  4. HttpRequest request = HttpRequest.GET("/search?limit=25&media=music&entity=album&term=${searchTerm}")
  5. HttpResponse<String> resp = client.exchange(request, String)
  6. client.close() (2)
  7. String json = resp.body()
  8. ObjectMapper objectMapper = new ObjectMapper() (3)
  9. objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  10. SearchResult searchResult = objectMapper.readValue(json, SearchResult)
  11. searchResult.results
  12. }
1Create a new instance of HttpClient with the create method, and convert to an instance of BlockingHttpClient with toBlocking(),
2The client should be closed using the close method to prevent thread leaking.
3Jackson’s ObjectMapper API can be used to map the raw JSON to POGOs, in this case SearchResult

Consult the Http Client section of the Micronaut user guide for more information on using the HttpClient low-level API.

Declarative API

A declarative HTTP client can be written by adding the @Client annotation to any interface or abstract class. Using Micronaut’s AOP support (see the Micronaut user guide section on Introduction Advice), the abstract or interface methods will be implemented for you at compilation time as HTTP calls. Declarative clients can return data-bound POGOs (or POJOs) without requiring special handling from the calling code.

  1. package example.grails
  2. import io.micronaut.http.annotation.Get
  3. import io.micronaut.http.client.annotation.Client
  4. @Client("https://itunes.apple.com/")
  5. interface ItunesClient {
  6. @Get("/search?limit=25&media=music&entity=album&term={term}")
  7. SearchResult search(String term)
  8. }

Note that HTTP client methods are annotated with the appropriate HTTP method, such as @Get or @Post.

To use a client like the one in the above example, simply inject an instance of the client into any bean using the @Autowired annotation.

  1. @Autowired
  2. ItunesClient itunesClient
  3. List<Album> searchAlbums(String searchTerm) {
  4. SearchResult searchResult = itunesClient.search(searchTerm)
  5. searchResult.results
  6. }

For more details on writing and using declarative clients, consult the Http Client section of the Micronaut user guide.