Skip to content

PlaytikaOSS/feign-reactive

develop
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code
This branch is 480 commits ahead of kptfh:develop.

Latest commit

Bumps [brave-tests](https://github.com/openzipkin/brave) from 5.15.1 to 5.16.0.
- [Release notes](https://github.com/openzipkin/brave/releases)
- [Changelog](https://github.com/openzipkin/brave/blob/master/RELEASE.md)
- [Commits](openzipkin/brave@5.15.1...5.16.0)

---
updated-dependencies:
- dependency-name: io.zipkin.brave:brave-tests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
baba570

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
April 12, 2023 11:55
April 25, 2023 15:51
April 25, 2023 15:51
April 25, 2023 15:51
April 25, 2023 15:51
April 25, 2023 15:51
April 25, 2023 15:51
April 25, 2023 15:51
March 30, 2018 20:06
September 4, 2020 18:03
December 14, 2018 15:41
April 12, 2023 11:55
April 12, 2023 11:55
June 9, 2023 12:44

CircleCI codecov Codacy Badge Maven Central

feign-reactive

Use Feign with Spring WebFlux

Overview

Implementation of Feign on Spring WebClient. Brings you the best of two worlds together : concise syntax of Feign to write client side API on fast, asynchronous and non-blocking HTTP client of Spring WebClient.

Modules

feign-reactor-core : base classes and interfaces that should allow to implement alternative reactor Feign

feign-reactor-webclient : Spring WebClient based implementation of reactor Feign

feign-reactor-cloud : Spring Cloud implementation of reactor Feign (Ribbon/Hystrix)

feign-reactor-java11 : Java 11 HttpClient based implementation of reactor Feign (!! Winner of benchmarks !!)

feign-reactor-rx2 : Rx2 compatible implementation of reactor Feign (depends on feign-reactor-webclient)

feign-reactor-jetty : experimental Reactive Jetty client based implementation of reactor Feign (doesn't depend on feign-reactor-webclient). In future will allow to write pure Rx2 version.

  • have greater reactivity level then Spring WebClient. By default don't collect body to list instead starts sending request body as stream.
  • starts receiving reactive response before all reactive request body has been sent
  • process Flux<String> correctly in request and response body

feign-reactor-spring-cloud-starter : Single dependency to have reactive feign client operabable in your spring cloud application. Uses webclient as default client implementation.

feign-reactor-bom : Maven BOM module which simplifies dependency management for all reactive feign client modules.

Usage

Write Feign API as usual, but every method of interface

  • may accept org.reactivestreams.Publisher as body
  • must return reactor.core.publisher.Mono or reactor.core.publisher.Flux.
@Headers({ "Accept: application/json" })
public interface IcecreamServiceApi {

  @RequestLine("GET /icecream/flavors")
  Flux<Flavor> getAvailableFlavors();

  @RequestLine("GET /icecream/mixins")
  Flux<Mixin> getAvailableMixins();

  @RequestLine("POST /icecream/orders")
  @Headers("Content-Type: application/json")
  Mono<Bill> makeOrder(IceCreamOrder order);

  @RequestLine("GET /icecream/orders/{orderId}")
  Mono<IceCreamOrder> findOrder(@Param("orderId") int orderId);

  @RequestLine("POST /icecream/bills/pay")
  @Headers("Content-Type: application/json")
  Mono<Void> payBill(Publisher<Bill> bill);
}

Build the client :

/* Create instance of your API */
IcecreamServiceApi client = 
             WebReactiveFeign  //WebClient based reactive feign  
             //JettyReactiveFeign //Jetty http client based
             //Java11ReactiveFeign //Java 11 http client based
            .<IcecreamServiceApi>builder()
            .target(IcecreamServiceApi.class, "http://www.icecreame.com")

/* Execute nonblocking requests */
Flux<Flavor> flavors = icecreamApi.getAvailableFlavors();
Flux<Mixin> mixins = icecreamApi.getAvailableMixins();

or cloud aware client :

 IcecreamServiceApi client = CloudReactiveFeign.<IcecreamServiceApi>builder(WebReactiveFeign.builder())
            .setLoadBalancerCommandFactory(s -> LoadBalancerCommand.builder()
                    .withLoadBalancer(AbstractLoadBalancer.class.cast(getNamedLoadBalancer(serviceName)))
                    .withRetryHandler(new DefaultLoadBalancerRetryHandler(1, 1, true))
                    .build())
            .fallback(() -> Mono.just(new IcecreamServiceApi() {
                @Override
                public Mono<String> get() {
                    return Mono.just("fallback");
                }
            }))
            .target(IcecreamServiceApi.class,  "http://" + serviceName);

/* Execute nonblocking requests */
Flux<Flavor> flavors = icecreamApi.getAvailableFlavors();
Flux<Mixin> mixins = icecreamApi.getAvailableMixins();

Rx2 Usage

Write Feign API as usual, but every method of interface

  • may accept Flowable, Observable, Single or Maybe as body
  • must return Flowable, Observable, Single or Maybe.
@Headers({"Accept: application/json"})
public interface IcecreamServiceApi {

  @RequestLine("GET /icecream/flavors")
  Flowable<Flavor> getAvailableFlavors();

  @RequestLine("GET /icecream/mixins")
  Observable<Mixin> getAvailableMixins();

  @RequestLine("POST /icecream/orders")
  @Headers("Content-Type: application/json")
  Single<Bill> makeOrder(IceCreamOrder order);

  @RequestLine("GET /icecream/orders/{orderId}")
  Maybe<IceCreamOrder> findOrder(@Param("orderId") int orderId);

  @RequestLine("POST /icecream/bills/pay")
  @Headers("Content-Type: application/json")
  Single<Long> payBill(Bill bill);

Build the client :

/* Create instance of your API */
IcecreamServiceApi client = Rx2ReactiveFeign
    .builder()
    .target(IcecreamServiceApi.class, "http://www.icecreame.com")

/* Execute nonblocking requests */
Flowable<Flavor> flavors = icecreamApi.getAvailableFlavors();
Observable<Mixin> mixins = icecreamApi.getAvailableMixins();

Header to request

There are 2 options:

ReactiveHttpRequestInterceptor

ReactiveFeignBuilder
    .addRequestInterceptor(ReactiveHttpRequestInterceptors.addHeader("Cache-Control", "no-cache"))
    .addRequestInterceptor(request -> Mono
            .subscriberContext()
            .map(ctx -> ctx
                    .<String>getOrEmpty("authToken")
                    .map(authToken -> {
                      MultiValueMapUtils.addOrdered(request.headers(), "Authorization", authToken);
                      return request;
                    })
                    .orElse(request)));

@RequestHeader parameter

You can use @RequestHeader annotation for specific parameter to pass one header or map of headers @RequestHeader example

Spring Auto-Configuration

You can enable auto-configuration of reactive Feign clients as Spring beans just by adding feign-reactor-spring-configuration module to classpath. Spring Auto-Configuration module Sample cloud auto-configuration project with Eureka/WebFlux/ReaciveFeign

License

Library distributed under Apache License Version 2.0.