WEBINAR
HOME TO GRAILS & MICRONAUT
Micronaut Declarative HTTP Client
Presented By: Puneet Behl
© 2019, Object Computing, Inc. (OCI). All rights reserved. No part of these notes may be reproduced, stored in a retrieval system, or transmitted, in any objectcomputing.com
form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior, written permission of Object Computing, Inc. (OCI)
About Me
Software Engineer
Member of 2GM Team
@puneetbhl
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 2
Motivation
The motivation behind creating a new HTTP client for Micronaut centers
around providing a rich set of cloud native features that in total did not
exists in any solution at that time.
A non-blocking HTTP client based on Netty that has integration with
service-discovery, load-balancing and many more other features is the
result.
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 3
Dependency
To use the HTTP client, just add the following dependency:
build.gradle
implementation “io.micronaut:micronaut-http-client"
<dependency> pom.xml
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 4
Usage
To inject the client use @Client with @Inject annotation with a URL of the API
@Client("https://newsapi.org") @Inject RxHttpClient rxHttpClient;
rxHttpClient.retrieve(HttpRequest.GET("/v2/top-headlines?country=in")
.header("X-Api-Key", "API_KEY_VALUE"), Argument.of(Map.class));
@Singleton
public class NewsService { Create the Client via ApplicationContext
private final HttpClient httpClient;
public NewsService(ApplicationContext applicationContext) {
this.httpClient = applicationContext.createBean(HttpClient.class, "/news");
}
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 5
HttpRequest Factory
METHOD DESCRIPTION ALLOWS BODY
HttpRequest.GET(java.lang.String) Constructs an HTTP GET request FALSE
HttpRequest.OPTIONS(java.lang.String) Constructs an HTTP OPTIONS request FALSE
HttpRequest.HEAD(java.lang.String) Constructs an HTTP HEAD request FALSE
HttpRequest.POST(java.lang.String,T) Constructs an HTTP POST request TRUE
HttpRequest.PUT(java.lang.String,T) Constructs an HTTP PUT request TRUE
HttpRequest.PATCH(java.lang.String,T) Constructs an HTTP PATCH request TRUE
HttpRequest.DELETE(java.lang.String) Constructs an HTTP DELETE request TRUE
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 6
Errors
@Client("http://localhost:8080") RxHttpClient rxHttpClient;
String uri = UriBuilder.of("/pet/{name}")
.expand(Collections.singletonMap("name", "dodo"))
.toString();
Assertions.assertThrows(HttpClientResponseException.class, () -> {
rxHttpClient.toBlocking().retrieve(uri, Pet.class);
});
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 7
Debugging
<logger name="io.micronaut.http.client" level="TRACE" />
Client Specific
micronaut:
http: Logging
client: Configurations
logger-name: mylogger
services:
other-client:
logger-name: other.client
<logger name="mylogger" level="DEBUG"/>
<logger name="other.client" level="TRACE"/>
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 8
Demo
String uri = UriBuilder.of("/v2/top-headlines")
.queryParam("country", "in")
.queryParam("apiKey", NEWS_API_KEY) A Basic HTTP Client
.build() Request
.toString();
Assertions.assertEquals("/v2/top-headlines?
country=in&apiKey=837fe7ca80a34f48bdbdd2c64c9d91ad", uri);
Map newsApiResult = rxHttpClient.toBlocking().retrieve(uri, Map.class);
Assertions.assertEquals(
"ok",
newsApiResult.get("status")
);
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 9
Declarative Client
The declarative client can be created by annotating
any interface or abstract class with @Client annotation.
@Client(“https://newsapi.org") @QueryValue is Optional
public interface NewsClient {
@Get("/v2/top-headlines{?country}")
Map fetchHeadlines(@QueryValue String country);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 10
Client Configurations
1. Proxy 5. Logging
2. Thread Pool 6. SSL
3. Timeouts 7. Connection Pooling
4. Follow Redirects 8. More…
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 11
Validation
implementation "io.micronaut:micronaut-validation"
@Post
Single<Pet> save(@NotBlank String name, @Min(1L) int age);
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 12
JSON Streaming
@Client("/news")
public interface NewsSteamingClient {
@Get(value = "/headlines/{country}", processes = MediaType.APPLICATION_JSON_STREAM)
Flowable<NewsArticle> headlines(@PathVariable String country);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 13
Customizing Headers
@Client("https://newsapi.org")
@Header(name = "X-Api-Key", value = "${news.api.key}")
public interface NewsClient {
@Get(value = "/v2/top-headlines", processes = MediaType.APPLICATION_JSON)
@Override
Flowable<HttpResponse<NewsArticleResult>> fetchLiveTopAndBreakingNewsHeadlines();
Alternatively you can supply a
NEWS_API_KEY environment
news: variable and the value will be
api:
key: 837fe7ca80a34f48bdbdd2c64c9d91ad
populated
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 14
Client Filter
@Filter(“/v2/top-headlines/**")
public class NewsApiFilter implements HttpClientFilter {
private String apiKey;
public NewsApiFilter(@Value("${news.api.key}") String apiKey) {
this.apiKey = apiKey;
}
@Override
public Publisher<? extends HttpResponse<?>> doFilter(MutableHttpRequest<?>
request, ClientFilterChain chain) {
return chain.proceed(request.header("X-Api-Key", apiKey));
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 15
Multipart Upload
MultipartBody multipartBody = MultipartBody.builder()
.addPart("file", "dodo.jpg", new File("dodo.jpg"))
.build()
@Client("http://localhost:8080/pet")
public interface PetClient {
@Post(uri = "/image", produces = MediaType.MULTIPART_FORM_DATA)
Single<HttpResponse<String>> uploadImage(@Body MultipartBody body);
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 16
Demo
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 17
Retry
Enable retries with a simple annotation. If all attempts fail the original
exception is thrown.
@Retryable(delay = "2s", attempts = "3")
@Client("http://localhost:8080/pet")
public interface PetClient extends PetApi {
@Override
@Get("{name}")
Single<HttpResponse<Pet>> get(@PathVariable String name);
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 18
Circuit Breaker
Same thing as @Retry but with reset option
@CircuitBreaker(delay = "2s", attempts = "3")
@Client("http://localhost:8080/pet")
public interface PetClient extends PetApi {
@Override
@Get("{name}")
Single<HttpResponse<Pet>> get(@PathVariable String name);
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 19
Fallback
The @Client annotation is annotated with @Recoverable
When an exception is thrown, a fallback is searched for and executed
@Fallback
public class PetFallback implements PetApi {
private static final Logger LOG = LoggerFactory.getLogger(PetFallback.class);
public static final int FALLBACK_PET_AGE = 10;
@Override
public Single<HttpResponse<Pet>> get(String name) {
if (LOG.isDebugEnabled()) {
LOG.debug("Fallback called for PetApi get method call");
}
return Single.just(HttpResponse.ok(new Pet(name, FALLBACK_PET_AGE)));
}
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 20
Demo
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 21
Service Discovery
implementation ‘io.micronaut:micronaut-discovery-client'
@Client("pets-server")
public interface PetClient {
...
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 22
Load Balancing
Round robin by default
Static list or service discovery
Provide your own implementation through the LoadBalancer interface
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 23
Tracing
All tracing integrations automatically support the HTTP client; declarative and
imperative styles.
Zipkin, Jaeger
https://guides.micronaut.io/tags/distributed-tracing.html
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 24
Demo
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 25
Using Micronaut HTTP Client with Spring
@Client("http://localhost:8080")
public interface PetClient {
@GetMapping(“/pet/{name}")
public Pet get(@PathVariable String name)
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 26
Using Micronaut HTTP Client with Grails
Micronaut is the parent application context of Grails 4 so you can take advantage of
many Micronaut features including HTTP Client.
@Client("https://start.grails.org")
interface GrailsAppForgeClient {
@Get("/{version}/profiles")
List<Map> profiles(String version)
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 27
Questions?
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 28
Micronaut Resources
• gitter.im/micronautfw
• docs.micronaut.io
• guides.micronaut.io
• micronaut.io/faq.html
• github.com/micronaut-projects/micronaut-core
• github.com/micronaut-projects/micronaut-examples
• objectcomputing.com/products/micronaut
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 29
LEARN MORE ABOUT OCI EVENTS AND TRAINING
HOME TO GRAILS & MICRONAUT
Events:
● objectcomputing.com/events
Training:
● objectcomputing.com/training
● grailstraining.com
● micronauttraining.com
Or email info@ocitraining.com to schedule a private tech talk or custom workshop for your team.
We can deliver these events on site, online, or in our state-of-the-art, Midwest training lab.
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 30
CONNECT WITH US
1+ (314) 579-0066
@objectcomputing
objectcomputing.com
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 31