com.gs.api.accelrx.web.client.reflect.AccelRxWebClientInvocationHandler Maven / Gradle / Ivy
package com.gs.api.accelrx.web.client.reflect;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.gs.api.accelrx.*;
import com.gs.api.accelrx.context.ServiceContext;
import com.gs.api.accelrx.context.ServiceContextProvider;
import com.gs.api.accelrx.context.SimplePerformanceLog;
import com.gs.api.accelrx.web.api.HttpException;
import com.gs.api.accelrx.web.api.WebClientBlockingResponse;
import com.gs.api.accelrx.web.api.WebClientObservableResponse;
import com.gs.api.accelrx.web.api.WebClientSingleResponse;
import com.gs.api.accelrx.web.client.AccelRxWebClientConfig;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.core.SingleTransformer;
import io.vertx.rxjava3.core.MultiMap;
import io.vertx.rxjava3.core.RxHelper;
import io.vertx.rxjava3.core.Vertx;
import org.slf4j.MDC;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public class AccelRxWebClientInvocationHandler implements InvocationHandler {
private final Vertx vertx;
private final AccelRxWebClient webClient;
private final APIContract apiContract;
private final AccelRxWebClientConfig config;
private final Supplier serviceContextSupplier;
private final Supplier perfLogSupplier;
private AccelRxWebClientInvocationHandler(Vertx vertx,
AccelRxWebClient webClient,
APIContract apiContract,
AccelRxWebClientConfig config,
Supplier serviceContextSupplier,
Supplier perfLogSupplier) {
this.vertx = vertx;
this.webClient = webClient;
this.apiContract = apiContract;
this.config = config;
this.serviceContextSupplier = serviceContextSupplier;
this.perfLogSupplier = perfLogSupplier;
}
public static AccelRxWebClientInvocationHandler create(Vertx vertx,
AccelRxWebClient webClient,
APIContract apiContract,
AccelRxWebClientConfig config,
ServiceContext serviceContext) {
return new AccelRxWebClientInvocationHandler(vertx, webClient, apiContract, config, () -> serviceContext, SimplePerformanceLog::new);
}
public static AccelRxWebClientInvocationHandler create(Vertx vertx,
AccelRxWebClient webClient,
APIContract apiContract,
AccelRxWebClientConfig config) {
return new AccelRxWebClientInvocationHandler(vertx, webClient, apiContract, config, ServiceContextProvider::getFromContext, SimplePerformanceLog::new);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
ServiceContext serviceContext = serviceContextSupplier.get();
PerformanceLog perfLog = perfLogSupplier.get();
AccelRxProxyMethod proxyMethod = AccelRxProxyMethod.create(apiContract, method);
if (proxyMethod.isResponseMethod()) {
return responseMethod(proxyMethod, args, serviceContext, perfLog);
} else {
return directBodyMethod(proxyMethod, args, serviceContext, perfLog);
}
}
private Object responseMethod(AccelRxProxyMethod proxyMethod, Object[] args, ServiceContext context, PerformanceLog perfLog) {
if (proxyMethod.apiOperation().isResponseStream()) {
return webClient.executeToStream(clientRequest(proxyMethod, args, context, perfLog))
.compose(toObservableResponseObject(proxyMethod))
.subscribeOn(RxHelper.scheduler(vertx));
} else {
Single responseSingle = webClient.execute(clientRequest(proxyMethod, args, context, perfLog))
.subscribeOn(RxHelper.scheduler(vertx));
if (proxyMethod.isBlockingMethod()) {
return responseSingle.compose(toBlockingResponseObject(proxyMethod))
.blockingGet();
} else {
return responseSingle.compose(toResponseObject(proxyMethod));
}
}
}
private Object directBodyMethod(AccelRxProxyMethod proxyMethod, Object[] args, ServiceContext context, PerformanceLog perfLog) {
if (proxyMethod.apiOperation().isResponseStream()) {
return webClient.executeToStream(clientRequest(proxyMethod, args, context, perfLog))
.compose(toResponseStreamOrError())
.flatMapObservable(body -> (Observable) body)
.subscribeOn(RxHelper.scheduler(vertx));
} else if (!proxyMethod.apiOperation().hasSuccessResponseBody()) {
Completable responseCompletable = webClient.execute(clientRequest(proxyMethod, args, context, perfLog))
.flatMapCompletable(response -> {
if (response.successful()) {
return Completable.complete();
} else {
return Completable.error(exceptionFrom(response));
}
})
.subscribeOn(RxHelper.scheduler(vertx));
if (proxyMethod.isBlockingMethod()) {
responseCompletable.blockingAwait(config.blockingTimeout(), TimeUnit.MILLISECONDS);
return null;
} else {
return responseCompletable;
}
} else {
Single> responseSingle = webClient.execute(clientRequest(proxyMethod, args, context, perfLog))
.compose(toResponseBodyOrError(proxyMethod))
.subscribeOn(RxHelper.scheduler(vertx));
if (proxyMethod.isBlockingMethod()) {
return responseSingle.blockingGet();
} else {
return responseSingle;
}
}
}
private AccelRxWebClientRequest clientRequest(AccelRxProxyMethod proxyMethod, Object[] args, ServiceContext context, PerformanceLog perfLog) {
return new ReflectionWebClientRequest(
proxyMethod.apiOperation(),
config,
proxyMethod.argsMap(args),
context,
perfLog);
}
private SingleTransformer toResponseObject(AccelRxProxyMethod proxyMethod) {
return upstream ->
upstream.flatMap(response ->
Single.just(((Class>) proxyMethod.responseType())
.getConstructor(WebClientSingleResponse.class)
.newInstance(response))
);
}
private SingleTransformer toBlockingResponseObject(AccelRxProxyMethod proxyMethod) {
return upstream ->
upstream.map(AccelRxWebClientBlockingResponse::from)
.flatMap(response ->
Single.just(((Class>) proxyMethod.responseType())
.getConstructor(WebClientBlockingResponse.class)
.newInstance(response))
);
}
private SingleTransformer toObservableResponseObject(AccelRxProxyMethod proxyMethod) {
return upstream ->
upstream.flatMap(response ->
Single.just(((Class>) proxyMethod.responseType())
.getConstructor(WebClientObservableResponse.class)
.newInstance(response))
);
}
private SingleTransformer toResponseBodyOrError(AccelRxProxyMethod proxyMethod) {
return upstream ->
upstream.flatMap(response -> {
if (response.successful()) {
return response.body(proxyMethod.responseType());
} else {
return Single.error(exceptionFrom(response));
}
});
}
private SingleTransformer toResponseStreamOrError() {
return upstream ->
upstream.flatMap(response -> {
if (response.successful()) {
return response.bodyStream();
} else {
return Single.error(exceptionFrom(response));
}
});
}
private HttpException exceptionFrom(AccelRxWebClientResponse response) {
return new HttpException(response.serviceName() + "." + response.operationId(),
response.statusCode(),
response.message(),
response.errorBody(),
toGoogleCollections(response.headers()));
}
private ListMultimap toGoogleCollections(MultiMap map) {
ListMultimap googleMap = ArrayListMultimap.create();
map.forEach(googleMap::put);
return googleMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy