Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rest proxy remove block from Schedulers #5376

Merged
merged 9 commits into from
Sep 16, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import com.azure.core.implementation.util.TypeUtil;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand Down Expand Up @@ -459,13 +461,13 @@ private Mono<?> handleRestResponseReturnType(HttpDecodedResponse response, Swagg

if (TypeUtil.isTypeOrSubTypeOf(bodyType, Void.class)) {
asyncResult = response.getSourceResponse().getBody().ignoreElements()
.then(Mono.just(createResponse(response, entityType, null)));
.then(createResponse(response, entityType, null));
} else {
asyncResult = handleBodyReturnType(response, methodParser, bodyType)
.map((Function<Object, Response<?>>) bodyAsObject -> createResponse(response, entityType,
.flatMap((Function<Object, Mono<Response<?>>>) bodyAsObject -> createResponse(response, entityType,
bodyAsObject))
.switchIfEmpty(Mono.defer((Supplier<Mono<Response<?>>>) () -> Mono.just(createResponse(response,
entityType, null))));
.switchIfEmpty(Mono.defer((Supplier<Mono<Response<?>>>) () -> createResponse(response,
entityType, null)));
}
} else {
// For now we're just throwing if the Maybe didn't emit a value.
Expand All @@ -476,7 +478,7 @@ private Mono<?> handleRestResponseReturnType(HttpDecodedResponse response, Swagg
}

@SuppressWarnings("unchecked")
private Response<?> createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) {
private Mono<Response<?>> createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) {
final HttpResponse httpResponse = response.getSourceResponse();
final HttpRequest httpRequest = httpResponse.getRequest();
final int responseStatusCode = httpResponse.getStatusCode();
Expand Down Expand Up @@ -515,30 +517,42 @@ private Response<?> createResponse(HttpDecodedResponse response, Type entityType
// try to create an instance using our list of potential candidates
for (Constructor<?> constructor : constructors) {
final Constructor<? extends Response<?>> ctor = (Constructor<? extends Response<?>>) constructor;

try {
final int paramCount = constructor.getParameterCount();

switch (paramCount) {
case 3:
return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders);
case 4:
return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject);
case 5:
return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject,
response.getDecodedHeaders().block());
default:
throw logger.logExceptionAsError(new IllegalStateException(
"Response constructor with expected parameters not found."));
}
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
throw logger.logExceptionAsError(reactor.core.Exceptions.propagate(e));
final int paramCount = constructor.getParameterCount();

switch (paramCount) {
case 3:
return Mono.just(newInstanceHelper.apply(ctor,
new Object[] {httpRequest, responseStatusCode, responseHeaders}));
case 4:
return Mono.just(newInstanceHelper.apply(ctor, new Object[] {httpRequest, responseStatusCode,
responseHeaders, bodyAsObject}));
case 5:
return response.getDecodedHeaders()
.map((Function<Object, Response<?>>) headers -> {
return newInstanceHelper.apply(ctor, new Object[] {httpRequest, responseStatusCode,
responseHeaders, bodyAsObject, headers});
}).switchIfEmpty(Mono.defer((Supplier<Mono<Response<?>>>) () -> {
return Mono.just(newInstanceHelper.apply(ctor,
new Object[] {httpRequest, responseStatusCode,
responseHeaders, bodyAsObject, null}));
}));
default:
throw logger.logExceptionAsError(new IllegalStateException(
"Response constructor with expected parameters not found."));
}
}
// error
throw logger.logExceptionAsError(new RuntimeException("Cannot find suitable constructor for class " + cls));
}

private BiFunction<Constructor<? extends Response<?>>,Object[], Response<?>> newInstanceHelper = (ctor, args) -> {
try {
return ctor.newInstance(args);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
throw logger.logExceptionAsError(Exceptions.propagate(e));
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work @sima-zhu :). I learned something today.

Just one question - Do we need an implementation of BiFunction to achieve this? or just a method is sufficient?, something like:

private static Response<?> createResponse(Constructor<? extends Response<?>> ctr, Object[] args) {
    try {
	    return ctor.newInstance(args);
	} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
	    throw logger.logExceptionAsError(Exceptions.propagate(e));
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it should be enough. Making functional as it would easy for any lambda function. Since it does not take function as parameter, I agree to convert it to method.


protected final Mono<?> handleBodyReturnType(final HttpDecodedResponse response,
final SwaggerMethodParser methodParser, final Type entityType) {
final int responseStatusCode = response.getSourceResponse().getStatusCode();
Expand Down