© 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
form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior, written permission of Object Computing, Inc. (OCI)
objectcomputing.com
Micronaut HTTP Client
James Kleeh
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
1. Principal Software Engineer at OCI
2. Grails Engineering Team since 2015
3. Original Micronaut Engineer
4. @Schlogen
2
About Me
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
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
exist in any solution at the time.
A non blocking HTTP client based on Netty that has integration with
service discovery, load balancing, and many other features is the result.
3
Motivation
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
1. Basic Usage
2. Reactive
3. Recovery
4. Service Discovery / Load Balancing
5. Much More …
4
Agenda
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 5
Basic Usage
@Singleton
class MyService {
@Inject @Client('/hello')
HttpClient client
@Singleton
class MyService {
HttpClient client
MyService(ApplicationContext context) {
client = context.createBean(HttpClient, '/hello')
}
@Client('/hello')
interface MyService {
}
HttpClient.create(
new URL(“http://localhost/hello")
)
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 6
Usable Anywhere
compile “io.micronaut:micronaut-http-client"
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 7
Basic Usage - Imperative
There are 2 basic methods the API provides
Exchange: Returns a response object
Retrieve: Returns only the body
Reactive by default
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 8
Basic Usage - Exchange
Publisher<HttpResponse<Book>> bookPublisher = client.exchange(
HttpRequest.GET(“/book/1"), Book.class)
)
The publisher will behave like an RxJava Single
HttpRequest.METHOD provides a rich builder style API for constructing a
request with headers, cookies, attributes, etc
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 9
Basic Usage - Exchange
Publisher<HttpResponse<List>> books = client.exchange(
HttpRequest.GET(“/books”), Argument.of(List.class, Book.class)
)
The Argument type allows for generics of collections to be passed to the
client
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 10
Basic Usage - Retrieve
Publisher<Book> book = client.retrieve(
HttpRequest.GET(“/books/1"), Book.class
)
Book book = client.toBlocking().retrieve(…)
Body only response
Book is the body type
JSON serialization by default, extensible to support other options
Blocking variations available
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 11
Basic Usage - Errors
An HttpClientResponseException will be emitted or thrown in the case of
any error status code. The error response body is HATEOAS by default.
Publisher<HttpResponse<List>> books = client.exchange(
HttpRequest.GET("/books"),
Argument.of(List.class, Book.class),
Argument.of(String.class),
)
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 12
Basic Usage - Declarative
An interface can be used to declare a client. A bean implementing the
interface will be generated at compile time.
@Client("/books")
public interface BookClient {
@Get("/{id}")
Book get(Long id);
@Get("/")
List<Book> list();
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 13
Basic Usage - Declarative
Arguments are validated at compile time with micronaut-validation
@Client("/books")
public interface BookClient {
@Get("/{id}")
Book get1(Long idx); //fails to compile
@Get("{/id}")
Book get2(Long id); //fails to compile
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 14
Basic Usage - Declarative
Headers can be set statically or dynamically
@Client("/books")
@Header(name = "X-My-Header", value = "my-value")
public interface BookClient {
@Get("/{id}")
Book get(Long id);
@Get("/")
List<Book> list(@Header("X-My-Header") String myHeader)
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 15
Basic Usage - Declarative
@Client("/books")
public interface BookClient {
@Get(uri = "/{id}")
@Consumes("application/json")
Book get(Long id);
@Post(uri = "/", processes = “application/json“)
Book save(@Body Book book)
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 16
Basic Usage - Declarative
Just like in the imperative style, an HttpResponse or Publisher can be
returned.
@Client("/books")
public interface BookClient {
@Get("/{id}")
Publisher<Book> get(Long id);
@Get("/")
HttpResponse<List<Book>> list()
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 17
Reactive
Support for RxJava2 and Project Reactor.
@Client("/books")
public interface BookClient {
@Get("/{id}")
Single<Book> get(Long id);
// or Mono, Maybe
@Get("/")
Flowable<Book> list()
// or Flux, Publisher
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 18
Multipart Uploads
MultipartBody requestBody = MultipartBody.builder()
.addPart("pages", file)
.addPart("title", "Walking The Himalayas")
.build()
@Client("/books")
public interface BookClient {
@Post(uri = "/", produces = MediaType.MULTIPART_FORM_DATA)
Book save(@Body MultipartBody body);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 19
Retry Support
Enable retries with a simple annotation. If all attempts fail the original
exception is thrown.
@Client(“bookService")
@Retryable(attempts = '5', delay = '5ms')
public interface BookClient {
@Get(“/{id}")
Book get(Long id);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 20
Circuit Breaker
@CircuitBreaker same thing as @Retry with reset option
@Client(“bookService")
@CircuitBreaker(attempts = “5”, delay = “5ms”, reset = “2s")
public interface BookClient {
@Get(“/{id}")
Book get(Long id);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 21
Fallback
The @Client annotation is annotated with @Recoverable
When an exception is thrown, a fallback is searched for and executed
@Fallback
public class BookFallback implements BookApi {
@Override
Book get(Long id) {
return …
}
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 22
Resiliency Demo
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 23
Service Discovery
Micronaut’s HTTP client works seamlessly with service discovery solutions.
A common DiscoveryClient API abstracts the implementation.
@Client(“book-service")
public interface BookClient {
}
@Client(id = “book-service", path = "/books")
public interface BookClient {
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 24
Load Balancing
Round robin by default. Static list or service discovery. Provide your own
implementation through the LoadBalancer interface.
@Client("bookService")
public interface BookClient {
@Get(“/{id}")
Book get(Long id);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 25
Service Discovery Demo
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
1. Rich Configuration
2. Filters
3. JSON Streams
4. Jackson Features
5. Tracing
6. WebSockets
7. More …
26
Other Features
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 27
Rich Configuration
1. Proxy
2. Thread Pool
3. Timeouts
4. Follow Redirects
5. Logging
6. SSL
7. Connection Pooling
8. More…
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 28
Client Filters
@Filter("authors")
public class AuthorClientFilter implements HttpClientFilter {
@Override
public Publisher<? extends HttpResponse<?>> doFilter(
MutableHttpRequest<?> request,
ClientFilterChain chain) {
//mutate the request here
return Flowable.fromPublisher(chain.proceed(request))
.doOnNext(response -> {
//mutate the response here
});
}
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 29
JSON Streams
@Client("bookService")
public interface StreamingBookClient {
@Get(consumes = MediaType.APPLICATION_JSON_STREAM)
Flowable<Book> getBooks();
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 30
Jackson Features
@Client(“bookService")
@JacksonFeatures(
enabledSerializationFeatures = WRAP_ROOT_VALUE,
disabledSerializationFeatures = WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,
enabledDeserializationFeatures = {
UNWRAP_ROOT_VALUE, ACCEPT_SINGLE_VALUE_AS_ARRAY}
)
public interface BookClient {
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com 31
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 32
WebSockets
@ClientWebSocket("/chat/{topic}/{username}")
public abstract class WebSocketClient implements AutoCloseable {
@OnOpen
public void onOpen(String topic,
String username,
WebSocketSession session) { }
@OnMessage
public void onMessage(String message) { }
public abstract void send(String message);
}
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Questions?
33
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
❖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
34
Micronaut Resources
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Thank You
35

Micronaut Http Client

  • 1.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. No part of these notes may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior, written permission of Object Computing, Inc. (OCI) objectcomputing.com Micronaut HTTP Client James Kleeh
  • 2.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 1. Principal Software Engineer at OCI 2. Grails Engineering Team since 2015 3. Original Micronaut Engineer 4. @Schlogen 2 About Me
  • 3.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 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 exist in any solution at the time. A non blocking HTTP client based on Netty that has integration with service discovery, load balancing, and many other features is the result. 3 Motivation
  • 4.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 1. Basic Usage 2. Reactive 3. Recovery 4. Service Discovery / Load Balancing 5. Much More … 4 Agenda
  • 5.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 5 Basic Usage @Singleton class MyService { @Inject @Client('/hello') HttpClient client @Singleton class MyService { HttpClient client MyService(ApplicationContext context) { client = context.createBean(HttpClient, '/hello') } @Client('/hello') interface MyService { } HttpClient.create( new URL(“http://localhost/hello") )
  • 6.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 6 Usable Anywhere compile “io.micronaut:micronaut-http-client" <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-http-client</artifactId> <scope>compile</scope> </dependency>
  • 7.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 7 Basic Usage - Imperative There are 2 basic methods the API provides Exchange: Returns a response object Retrieve: Returns only the body Reactive by default
  • 8.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 8 Basic Usage - Exchange Publisher<HttpResponse<Book>> bookPublisher = client.exchange( HttpRequest.GET(“/book/1"), Book.class) ) The publisher will behave like an RxJava Single HttpRequest.METHOD provides a rich builder style API for constructing a request with headers, cookies, attributes, etc
  • 9.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 9 Basic Usage - Exchange Publisher<HttpResponse<List>> books = client.exchange( HttpRequest.GET(“/books”), Argument.of(List.class, Book.class) ) The Argument type allows for generics of collections to be passed to the client
  • 10.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 10 Basic Usage - Retrieve Publisher<Book> book = client.retrieve( HttpRequest.GET(“/books/1"), Book.class ) Book book = client.toBlocking().retrieve(…) Body only response Book is the body type JSON serialization by default, extensible to support other options Blocking variations available
  • 11.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 11 Basic Usage - Errors An HttpClientResponseException will be emitted or thrown in the case of any error status code. The error response body is HATEOAS by default. Publisher<HttpResponse<List>> books = client.exchange( HttpRequest.GET("/books"), Argument.of(List.class, Book.class), Argument.of(String.class), )
  • 12.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 12 Basic Usage - Declarative An interface can be used to declare a client. A bean implementing the interface will be generated at compile time. @Client("/books") public interface BookClient { @Get("/{id}") Book get(Long id); @Get("/") List<Book> list(); }
  • 13.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 13 Basic Usage - Declarative Arguments are validated at compile time with micronaut-validation @Client("/books") public interface BookClient { @Get("/{id}") Book get1(Long idx); //fails to compile @Get("{/id}") Book get2(Long id); //fails to compile }
  • 14.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 14 Basic Usage - Declarative Headers can be set statically or dynamically @Client("/books") @Header(name = "X-My-Header", value = "my-value") public interface BookClient { @Get("/{id}") Book get(Long id); @Get("/") List<Book> list(@Header("X-My-Header") String myHeader) }
  • 15.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 15 Basic Usage - Declarative @Client("/books") public interface BookClient { @Get(uri = "/{id}") @Consumes("application/json") Book get(Long id); @Post(uri = "/", processes = “application/json“) Book save(@Body Book book) }
  • 16.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 16 Basic Usage - Declarative Just like in the imperative style, an HttpResponse or Publisher can be returned. @Client("/books") public interface BookClient { @Get("/{id}") Publisher<Book> get(Long id); @Get("/") HttpResponse<List<Book>> list() }
  • 17.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 17 Reactive Support for RxJava2 and Project Reactor. @Client("/books") public interface BookClient { @Get("/{id}") Single<Book> get(Long id); // or Mono, Maybe @Get("/") Flowable<Book> list() // or Flux, Publisher }
  • 18.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 18 Multipart Uploads MultipartBody requestBody = MultipartBody.builder() .addPart("pages", file) .addPart("title", "Walking The Himalayas") .build() @Client("/books") public interface BookClient { @Post(uri = "/", produces = MediaType.MULTIPART_FORM_DATA) Book save(@Body MultipartBody body); }
  • 19.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 19 Retry Support Enable retries with a simple annotation. If all attempts fail the original exception is thrown. @Client(“bookService") @Retryable(attempts = '5', delay = '5ms') public interface BookClient { @Get(“/{id}") Book get(Long id); }
  • 20.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 20 Circuit Breaker @CircuitBreaker same thing as @Retry with reset option @Client(“bookService") @CircuitBreaker(attempts = “5”, delay = “5ms”, reset = “2s") public interface BookClient { @Get(“/{id}") Book get(Long id); }
  • 21.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 21 Fallback The @Client annotation is annotated with @Recoverable When an exception is thrown, a fallback is searched for and executed @Fallback public class BookFallback implements BookApi { @Override Book get(Long id) { return … } }
  • 22.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 22 Resiliency Demo
  • 23.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 23 Service Discovery Micronaut’s HTTP client works seamlessly with service discovery solutions. A common DiscoveryClient API abstracts the implementation. @Client(“book-service") public interface BookClient { } @Client(id = “book-service", path = "/books") public interface BookClient { }
  • 24.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 24 Load Balancing Round robin by default. Static list or service discovery. Provide your own implementation through the LoadBalancer interface. @Client("bookService") public interface BookClient { @Get(“/{id}") Book get(Long id); }
  • 25.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 25 Service Discovery Demo
  • 26.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 1. Rich Configuration 2. Filters 3. JSON Streams 4. Jackson Features 5. Tracing 6. WebSockets 7. More … 26 Other Features
  • 27.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 27 Rich Configuration 1. Proxy 2. Thread Pool 3. Timeouts 4. Follow Redirects 5. Logging 6. SSL 7. Connection Pooling 8. More…
  • 28.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 28 Client Filters @Filter("authors") public class AuthorClientFilter implements HttpClientFilter { @Override public Publisher<? extends HttpResponse<?>> doFilter( MutableHttpRequest<?> request, ClientFilterChain chain) { //mutate the request here return Flowable.fromPublisher(chain.proceed(request)) .doOnNext(response -> { //mutate the response here }); } }
  • 29.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 29 JSON Streams @Client("bookService") public interface StreamingBookClient { @Get(consumes = MediaType.APPLICATION_JSON_STREAM) Flowable<Book> getBooks(); }
  • 30.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 30 Jackson Features @Client(“bookService") @JacksonFeatures( enabledSerializationFeatures = WRAP_ROOT_VALUE, disabledSerializationFeatures = WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, enabledDeserializationFeatures = { UNWRAP_ROOT_VALUE, ACCEPT_SINGLE_VALUE_AS_ARRAY} ) public interface BookClient { }
  • 31.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 31 Tracing All tracing integrations automatically support the HTTP client; declarative and imperative styles. Zipkin, Jaeger https://guides.micronaut.io/tags/distributed-tracing.html
  • 32.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 32 WebSockets @ClientWebSocket("/chat/{topic}/{username}") public abstract class WebSocketClient implements AutoCloseable { @OnOpen public void onOpen(String topic, String username, WebSocketSession session) { } @OnMessage public void onMessage(String message) { } public abstract void send(String message); }
  • 33.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com Questions? 33
  • 34.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com ❖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 34 Micronaut Resources
  • 35.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com Thank You 35