reactivefeign.rx3.Rx3ReactiveFeign Maven / Gradle / Ivy
package reactivefeign.rx3;
import feign.Contract;
import feign.MethodMetadata;
import io.reactivex.rxjava3.core.*;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.reactive.function.client.WebClient;
import reactivefeign.ReactiveOptions;
import reactivefeign.client.ReactiveHttpClient;
import reactivefeign.client.ReactiveHttpClientFactory;
import reactivefeign.client.ReactiveHttpRequestInterceptor;
import reactivefeign.methodhandler.MethodHandlerFactory;
import reactivefeign.publisher.FluxPublisherHttpClient;
import reactivefeign.publisher.MonoPublisherHttpClient;
import reactivefeign.publisher.PublisherClientFactory;
import reactivefeign.publisher.PublisherHttpClient;
import reactivefeign.retry.ReactiveRetryPolicy;
import reactivefeign.rx3.client.statushandler.Rx3ReactiveStatusHandler;
import reactivefeign.rx3.client.statushandler.Rx3StatusHandler;
import reactivefeign.rx3.methodhandler.Rx3MethodHandlerFactory;
import reactivefeign.webclient.WebClientFeignCustomizer;
import reactivefeign.webclient.WebReactiveFeign;
import reactivefeign.webclient.client.WebReactiveHttpClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import static feign.Util.resolveLastTypeParameter;
import static java.util.Optional.ofNullable;
import static reactivefeign.utils.FeignUtils.getBodyActualType;
import static reactivefeign.utils.FeignUtils.returnPublisherType;
import static reactivefeign.webclient.client.WebReactiveHttpClient.webReactiveHttpResponse;
/**
* @author Sergii Karpenko
*/
public final class Rx3ReactiveFeign {
private Rx3ReactiveFeign(){}
public static Builder builder() {
return new Builder<>(WebClient.builder());
}
public static Builder builder(WebClient.Builder webClientBuilder) {
return new Builder<>(webClientBuilder);
}
public static Builder builder(WebClient.Builder webClientBuilder, WebClientFeignCustomizer webClientCustomizer) {
return new Builder<>(webClientBuilder, webClientCustomizer);
}
public static class Builder extends WebReactiveFeign.Builder {
private BackpressureStrategy backpressureStrategy;
protected Builder(WebClient.Builder webClientBuilder) {
super(webClientBuilder);
}
protected Builder(WebClient.Builder webClientBuilder, WebClientFeignCustomizer webClientCustomizer) {
super(webClientBuilder, webClientCustomizer);
}
/**
* Used to convert {@link Observable} into {@link Flux}
* @param backpressureStrategy
*/
public void setBackpressureStrategy(BackpressureStrategy backpressureStrategy) {
this.backpressureStrategy = backpressureStrategy;
}
@Override
public MethodHandlerFactory buildReactiveMethodHandlerFactory(PublisherClientFactory publisherClientFactory) {
return new Rx3MethodHandlerFactory(publisherClientFactory, backpressureStrategy);
}
@Override
public Builder contract(final Contract contract) {
this.contract = new Rx3Contract(contract);
return this;
}
@Override
public Builder addRequestInterceptor(ReactiveHttpRequestInterceptor requestInterceptor) {
super.addRequestInterceptor(requestInterceptor);
return this;
}
@Override
public Builder decode404() {
super.decode404();
return this;
}
public Builder statusHandler(Rx3StatusHandler statusHandler) {
super.statusHandler(new Rx3ReactiveStatusHandler(statusHandler));
return this;
}
@Override
public Builder retryWhen(ReactiveRetryPolicy retryPolicy){
super.retryWhen(retryPolicy);
return this;
}
@Override
public Builder options(final ReactiveOptions options) {
super.options(options);
return this;
}
protected PublisherHttpClient toPublisher(ReactiveHttpClient reactiveHttpClient, MethodMetadata methodMetadata){
Type returnType = returnPublisherType(methodMetadata);
if(returnType == Single.class || returnType == Maybe.class){
return new MonoPublisherHttpClient(reactiveHttpClient);
} else if(returnType == Flowable.class || returnType == Observable.class){
return new FluxPublisherHttpClient(reactiveHttpClient);
} else {
throw new IllegalArgumentException("Unknown returnType: " + returnType);
}
}
@Override
protected ReactiveHttpClientFactory clientFactory(){
this.webClientBuilder.clientConnector(clientConnector());
if(webClientCustomizer != null){
webClientCustomizer.accept(webClientBuilder);
}
return methodMetadata -> webClient(methodMetadata, webClientBuilder.build());
}
public WebReactiveHttpClient webClient(MethodMetadata methodMetadata, WebClient webClient) {
final Type returnType = methodMetadata.returnType();
Type returnPublisherType = ((ParameterizedType) returnType).getRawType();
ParameterizedTypeReference