From a0e7584b48a68ad6bdbfe80e1ca605d6563a67e9 Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Sun, 15 Sep 2019 14:29:43 -0700 Subject: [PATCH 1/9] Rest proxy remove block from Schedulers --- .../azure/core/implementation/RestProxy.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index a7d7a059ab103..b3199e1f8ac83 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -462,10 +462,10 @@ private Mono handleRestResponseReturnType(HttpDecodedResponse response, Swagg .then(Mono.just(createResponse(response, entityType, null))); } else { asyncResult = handleBodyReturnType(response, methodParser, bodyType) - .map((Function>) bodyAsObject -> createResponse(response, entityType, + .flatMap((Function>>) bodyAsObject -> createResponse(response, entityType, bodyAsObject)) - .switchIfEmpty(Mono.defer((Supplier>>) () -> Mono.just(createResponse(response, - entityType, null)))); + .switchIfEmpty(Mono.defer((Supplier>>) () -> createResponse(response, + entityType, null))); } } else { // For now we're just throwing if the Maybe didn't emit a value. @@ -476,7 +476,7 @@ private Mono handleRestResponseReturnType(HttpDecodedResponse response, Swagg } @SuppressWarnings("unchecked") - private Response createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) { + private Mono> createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) { final HttpResponse httpResponse = response.getSourceResponse(); final HttpRequest httpRequest = httpResponse.getRequest(); final int responseStatusCode = httpResponse.getStatusCode(); @@ -521,12 +521,19 @@ private Response createResponse(HttpDecodedResponse response, Type entityType switch (paramCount) { case 3: - return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders); + return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders)); case 4: - return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject); + return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject)); case 5: - return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject, - response.getDecodedHeaders().block()); + return response.getDecodedHeaders().flatMap( + headers -> { + try { + return Mono.justOrEmpty(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject, + headers)); + } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { + throw new RuntimeException("a"); + } + }); default: throw logger.logExceptionAsError(new IllegalStateException( "Response constructor with expected parameters not found.")); From 911a83df24766687e779c25c87bb53e5f4232e5d Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Sun, 15 Sep 2019 15:10:58 -0700 Subject: [PATCH 2/9] Checkstyle fix --- .../java/com/azure/core/implementation/RestProxy.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index b3199e1f8ac83..3ba2493395f80 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -523,15 +523,18 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti case 3: return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders)); case 4: - return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject)); + return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, + bodyAsObject)); case 5: return response.getDecodedHeaders().flatMap( headers -> { try { - return Mono.justOrEmpty(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject, + return Mono.justOrEmpty(ctor.newInstance(httpRequest, responseStatusCode, + responseHeaders, bodyAsObject, headers)); - } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { - throw new RuntimeException("a"); + } catch (IllegalAccessException | InvocationTargetException + | InstantiationException e) { + throw logger.logExceptionAsError(reactor.core.Exceptions.propagate(e)); } }); default: From 41df2f3a015d039ad65ce2ef0eebc72ba32f6c59 Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 09:26:54 -0700 Subject: [PATCH 3/9] Fixed the case when deserialized header is null --- .../azure/core/implementation/RestProxy.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index 3ba2493395f80..a75f73f4ccd43 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -459,13 +459,12 @@ 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) - .flatMap((Function>>) bodyAsObject -> createResponse(response, entityType, + .flatMap((Function>) bodyAsObject -> createResponse(response, entityType, bodyAsObject)) - .switchIfEmpty(Mono.defer((Supplier>>) () -> createResponse(response, - entityType, null))); + .switchIfEmpty(createResponse(response, entityType, null)); } } else { // For now we're just throwing if the Maybe didn't emit a value. @@ -475,6 +474,12 @@ private Mono handleRestResponseReturnType(HttpDecodedResponse response, Swagg return asyncResult; } + private static final class NullObject { + private NullObject() { + } + public static final NullObject INSTANCE = new NullObject(); + } + @SuppressWarnings("unchecked") private Mono> createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) { final HttpResponse httpResponse = response.getSourceResponse(); @@ -511,7 +516,6 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti if (constructors.isEmpty()) { throw logger.logExceptionAsError(new RuntimeException("Cannot find suitable constructor for class " + cls)); } - // try to create an instance using our list of potential candidates for (Constructor constructor : constructors) { final Constructor> ctor = (Constructor>) constructor; @@ -526,17 +530,32 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject)); case 5: - return response.getDecodedHeaders().flatMap( - headers -> { + return response.getDecodedHeaders() + .defaultIfEmpty(NullObject.INSTANCE) + .map(headers -> { try { - return Mono.justOrEmpty(ctor.newInstance(httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, - headers)); + if (headers instanceof NullObject) { + return ctor.newInstance(httpRequest, responseStatusCode, + responseHeaders, bodyAsObject, null); + } + return ctor.newInstance(httpRequest, responseStatusCode, + responseHeaders, bodyAsObject, headers); } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { - throw logger.logExceptionAsError(reactor.core.Exceptions.propagate(e)); + throw logger.logExceptionAsError(Exceptions.propagate(e)); } }); +// Function> headersToResponse = (deserializedHeaders) -> { +// try { +// return ctor.newInstance(httpRequest, responseStatusCode, +// responseHeaders, bodyAsObject, deserializedHeaders); +// }catch (IllegalAccessException | InvocationTargetException +// | InstantiationException e) { +// throw logger.logExceptionAsError(Exceptions.propagate(e)); +// } }; +// return response.getDecodedHeaders() +// .map(headersToResponse) +// .defaultIfEmpty(headersToResponse.apply(null)); default: throw logger.logExceptionAsError(new IllegalStateException( "Response constructor with expected parameters not found.")); From 8115e129a63a07e5c14534927f6c2ae8d04f2a40 Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 11:48:33 -0700 Subject: [PATCH 4/9] Use the reactor way of handling null case --- .../azure/core/implementation/RestProxy.java | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index a75f73f4ccd43..3cbb62b93319c 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -516,13 +516,12 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti if (constructors.isEmpty()) { throw logger.logExceptionAsError(new RuntimeException("Cannot find suitable constructor for class " + cls)); } + // try to create an instance using our list of potential candidates for (Constructor constructor : constructors) { final Constructor> ctor = (Constructor>) constructor; - try { final int paramCount = constructor.getParameterCount(); - switch (paramCount) { case 3: return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders)); @@ -531,31 +530,23 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti bodyAsObject)); case 5: return response.getDecodedHeaders() - .defaultIfEmpty(NullObject.INSTANCE) - .map(headers -> { + .map((Function>) headers -> { try { - if (headers instanceof NullObject) { - return ctor.newInstance(httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, null); - } return ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, bodyAsObject, headers); } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { throw logger.logExceptionAsError(Exceptions.propagate(e)); } - }); -// Function> headersToResponse = (deserializedHeaders) -> { -// try { -// return ctor.newInstance(httpRequest, responseStatusCode, -// responseHeaders, bodyAsObject, deserializedHeaders); -// }catch (IllegalAccessException | InvocationTargetException -// | InstantiationException e) { -// throw logger.logExceptionAsError(Exceptions.propagate(e)); -// } }; -// return response.getDecodedHeaders() -// .map(headersToResponse) -// .defaultIfEmpty(headersToResponse.apply(null)); + }).switchIfEmpty(Mono.defer((Supplier>>) () -> { + try { + return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, + responseHeaders, bodyAsObject, null)); + } catch (IllegalAccessException | InvocationTargetException + | InstantiationException e) { + throw logger.logExceptionAsError(Exceptions.propagate(e)); + } + })); default: throw logger.logExceptionAsError(new IllegalStateException( "Response constructor with expected parameters not found.")); From 025c9de98dfe7a667a8ab1b43b0f63f77b65f49f Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 11:54:34 -0700 Subject: [PATCH 5/9] Use the reactor way of handling null case --- .../src/main/java/com/azure/core/implementation/RestProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index 3cbb62b93319c..4f9ad44bfd9dc 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -516,7 +516,7 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti if (constructors.isEmpty()) { throw logger.logExceptionAsError(new RuntimeException("Cannot find suitable constructor for class " + cls)); } - + // try to create an instance using our list of potential candidates for (Constructor constructor : constructors) { final Constructor> ctor = (Constructor>) constructor; From 8fb56a6caa8f29657044e2406b619f9873a979dd Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 12:05:46 -0700 Subject: [PATCH 6/9] Revert some changes back to origin --- .../com/azure/core/implementation/RestProxy.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index 4f9ad44bfd9dc..065ab7991276d 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -462,9 +462,10 @@ private Mono handleRestResponseReturnType(HttpDecodedResponse response, Swagg .then(createResponse(response, entityType, null)); } else { asyncResult = handleBodyReturnType(response, methodParser, bodyType) - .flatMap((Function>) bodyAsObject -> createResponse(response, entityType, + .flatMap((Function>>) bodyAsObject -> createResponse(response, entityType, bodyAsObject)) - .switchIfEmpty(createResponse(response, entityType, null)); + .switchIfEmpty(Mono.defer((Supplier>>) () -> createResponse(response, + entityType, null))); } } else { // For now we're just throwing if the Maybe didn't emit a value. @@ -474,12 +475,6 @@ private Mono handleRestResponseReturnType(HttpDecodedResponse response, Swagg return asyncResult; } - private static final class NullObject { - private NullObject() { - } - public static final NullObject INSTANCE = new NullObject(); - } - @SuppressWarnings("unchecked") private Mono> createResponse(HttpDecodedResponse response, Type entityType, Object bodyAsObject) { final HttpResponse httpResponse = response.getSourceResponse(); @@ -522,6 +517,7 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti final Constructor> ctor = (Constructor>) constructor; try { final int paramCount = constructor.getParameterCount(); + switch (paramCount) { case 3: return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders)); From d0f16498c250cd0a298ca539c0896437997079f7 Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 12:30:46 -0700 Subject: [PATCH 7/9] Clean up some try/catch block --- .../azure/core/implementation/RestProxy.java | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index 065ab7991276d..f4eb3ba0737a8 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -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; @@ -515,46 +517,42 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti // try to create an instance using our list of potential candidates for (Constructor constructor : constructors) { final Constructor> ctor = (Constructor>) constructor; - try { - final int paramCount = constructor.getParameterCount(); - - switch (paramCount) { - case 3: - return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders)); - case 4: - return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, responseHeaders, - bodyAsObject)); - case 5: - return response.getDecodedHeaders() - .map((Function>) headers -> { - try { - return ctor.newInstance(httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, headers); - } catch (IllegalAccessException | InvocationTargetException - | InstantiationException e) { - throw logger.logExceptionAsError(Exceptions.propagate(e)); - } - }).switchIfEmpty(Mono.defer((Supplier>>) () -> { - try { - return Mono.just(ctor.newInstance(httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, null)); - } catch (IllegalAccessException | InvocationTargetException - | InstantiationException e) { - throw logger.logExceptionAsError(Exceptions.propagate(e)); - } - })); - 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>) headers -> { + return newInstanceHelper.apply(ctor, new Object[] {httpRequest, responseStatusCode, + responseHeaders, bodyAsObject, headers}); + }).switchIfEmpty(Mono.defer((Supplier>>) () -> { + 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>,Object[], Response> newInstanceHelper = (ctor, args) -> { + try { + return ctor.newInstance(args); + } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { + throw logger.logExceptionAsError(Exceptions.propagate(e)); + } + }; + protected final Mono handleBodyReturnType(final HttpDecodedResponse response, final SwaggerMethodParser methodParser, final Type entityType) { final int responseStatusCode = response.getSourceResponse().getStatusCode(); From 495a831f2978ce7aab20dce9147f6e26e198fa33 Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 13:13:42 -0700 Subject: [PATCH 8/9] Convert helper to method --- .../azure/core/implementation/RestProxy.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index f4eb3ba0737a8..c15e65ad5cc89 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -37,8 +37,6 @@ 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; @@ -521,20 +519,19 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti switch (paramCount) { case 3: - return Mono.just(newInstanceHelper.apply(ctor, - new Object[] {httpRequest, responseStatusCode, responseHeaders})); + return Mono.just(createResponse(ctor, new Object[] + {httpRequest, responseStatusCode, responseHeaders})); case 4: - return Mono.just(newInstanceHelper.apply(ctor, new Object[] {httpRequest, responseStatusCode, + return Mono.just(createResponse(ctor, new Object[] {httpRequest, responseStatusCode, responseHeaders, bodyAsObject})); case 5: return response.getDecodedHeaders() .map((Function>) headers -> { - return newInstanceHelper.apply(ctor, new Object[] {httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, headers}); + return createResponse(ctor, new Object[] + {httpRequest, responseStatusCode, responseHeaders, bodyAsObject, headers}); }).switchIfEmpty(Mono.defer((Supplier>>) () -> { - return Mono.just(newInstanceHelper.apply(ctor, - new Object[] {httpRequest, responseStatusCode, - responseHeaders, bodyAsObject, null})); + return Mono.just(createResponse(ctor, new Object[] + {httpRequest, responseStatusCode, responseHeaders, bodyAsObject, null})); })); default: throw logger.logExceptionAsError(new IllegalStateException( @@ -545,13 +542,13 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti throw logger.logExceptionAsError(new RuntimeException("Cannot find suitable constructor for class " + cls)); } - private BiFunction>,Object[], Response> newInstanceHelper = (ctor, args) -> { + private Response createResponse(Constructor> ctor, Object[] args) { try { return ctor.newInstance(args); } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) { throw logger.logExceptionAsError(Exceptions.propagate(e)); } - }; + } protected final Mono handleBodyReturnType(final HttpDecodedResponse response, final SwaggerMethodParser methodParser, final Type entityType) { From 89b0885d58265f7441e486e344f18ff130e61c9f Mon Sep 17 00:00:00 2001 From: Sima Zhu Date: Mon, 16 Sep 2019 13:25:46 -0700 Subject: [PATCH 9/9] Fix linting --- .../src/main/java/com/azure/core/implementation/RestProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java index c15e65ad5cc89..c568fcba6de07 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/RestProxy.java @@ -523,7 +523,7 @@ private Mono> createResponse(HttpDecodedResponse response, Type enti {httpRequest, responseStatusCode, responseHeaders})); case 4: return Mono.just(createResponse(ctor, new Object[] {httpRequest, responseStatusCode, - responseHeaders, bodyAsObject})); + responseHeaders, bodyAsObject})); case 5: return response.getDecodedHeaders() .map((Function>) headers -> {