You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Copyright (c) Microsoft Corporation. All rights reserved.// Licensed under the MIT License.packagecom.azure.core.http.rest;
importcom.azure.core.exception.HttpResponseException;
importcom.azure.core.exception.UnexpectedLengthException;
importcom.azure.core.http.*;
importcom.azure.core.http.policy.CookiePolicy;
importcom.azure.core.http.policy.HttpPipelinePolicy;
importcom.azure.core.http.policy.RetryPolicy;
importcom.azure.core.http.policy.UserAgentPolicy;
importcom.azure.core.implementation.AccessibleByteArrayOutputStream;
importcom.azure.core.implementation.TypeUtil;
importcom.azure.core.implementation.http.UnexpectedExceptionInformation;
importcom.azure.core.implementation.serializer.HttpResponseDecoder;
importcom.azure.core.implementation.serializer.HttpResponseDecoder.HttpDecodedResponse;
importcom.azure.core.implementation.util.*;
importcom.azure.core.util.*;
importcom.azure.core.util.logging.ClientLogger;
importcom.azure.core.util.serializer.JacksonAdapter;
importcom.azure.core.util.serializer.SerializerAdapter;
importcom.azure.core.util.serializer.SerializerEncoding;
importcom.azure.core.util.tracing.Tracer;
importcom.azure.core.util.tracing.TracerProxy;
importreactor.core.Exceptions;
importreactor.core.publisher.Flux;
importreactor.core.publisher.Mono;
importreactor.core.publisher.Signal;
importreactor.util.context.ContextView;
importjava.io.*;
importjava.lang.invoke.MethodHandle;
importjava.lang.reflect.*;
importjava.net.URL;
importjava.nio.ByteBuffer;
importjava.nio.charset.StandardCharsets;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Optional;
importjava.util.function.Supplier;
importstaticcom.azure.core.implementation.serializer.HttpResponseBodyDecoder.shouldEagerlyReadResponse;
/** * Type to create a proxy implementation for an interface describing REST API methods. * * RestProxy can create proxy implementations for interfaces with methods that return deserialized Java objects as well * as asynchronous Single objects that resolve to a deserialized Java object. */publicfinalclassSyncRestProxyimplementsInvocationHandler {
privatestaticfinalByteBufferVALIDATION_BUFFER = ByteBuffer.allocate(0);
privatestaticfinalStringBODY_TOO_LARGE = "Request body emitted %d bytes, more than the expected %d bytes.";
privatestaticfinalStringBODY_TOO_SMALL = "Request body emitted %d bytes, less than the expected %d bytes.";
privatestaticfinalStringMUST_IMPLEMENT_PAGE_ERROR =
"Unable to create PagedResponse<T>. Body must be of a type that implements: " + Page.class;
privatestaticfinalResponseConstructorsCacheRESPONSE_CONSTRUCTORS_CACHE = newResponseConstructorsCache();
// RestProxy is a commonly used class, use a static logger.privatestaticfinalClientLoggerLOGGER = newClientLogger(SyncRestProxy.class);
privatefinalHttpPipelinehttpPipeline;
privatefinalSerializerAdapterserializer;
privatefinalSwaggerInterfaceParserinterfaceParser;
privatefinalHttpResponseDecoderdecoder;
/** * Create a RestProxy. * * @param httpPipeline the HttpPipelinePolicy and HttpClient httpPipeline that will be used to send HTTP requests. * @param serializer the serializer that will be used to convert response bodies to POJOs. * @param interfaceParser the parser that contains information about the interface describing REST API methods that * this RestProxy "implements". */privateSyncRestProxy(HttpPipelinehttpPipeline, SerializerAdapterserializer, SwaggerInterfaceParserinterfaceParser) {
this.httpPipeline = httpPipeline;
this.serializer = serializer;
this.interfaceParser = interfaceParser;
this.decoder = newHttpResponseDecoder(this.serializer);
}
Send API
/** * Send the provided request asynchronously, applying any request policies provided to the HttpClient instance. * * @param request the HTTP request to send * @param contextData the context * @return a {@link Mono} that emits HttpResponse asynchronously */publicHttpResponsesend(HttpRequestrequest, ContextcontextData) {
returnhttpPipeline.sendSynchronously(request, contextData);
}
Invoke API
@OverridepublicObjectinvoke(Objectproxy, finalMethodmethod, Object[] args) {
validateResumeOperationIsNotPresent(method);
finalSwaggerMethodParsermethodParser = getMethodParser(method);
HttpRequestrequest;
try {
request = createHttpRequest(methodParser, args);
} catch (IOExceptione) {
throwLOGGER.logExceptionAsError(newUncheckedIOException(e));
}
Contextcontext = methodParser.setContext(args);
RequestOptionsoptions = methodParser.setRequestOptions(args);
context = mergeRequestOptionsContext(context, options);
context = context.addData("caller-method", methodParser.getFullyQualifiedMethodName())
.addData("azure-eagerly-read-response", shouldEagerlyReadResponse(methodParser.getReturnType()));
HttpDecodedResponsedecodedResponse = null;
Throwablethrowable = null;
try {
context = startTracingSpan(method, context);
// If there is 'RequestOptions' apply its request callback operations before validating the body.// This is because the callbacks may mutate the request body.if (options != null) {
options.getRequestCallback().accept(request);
}
if (request.getBody() != null) {
request.setContent(validateLengthSync(request));
}
finalHttpResponseresponse = send(request, context);
decodedResponse = this.decoder.decodeSync(response, methodParser);
returnhandleRestReturnType(decodedResponse, methodParser,
methodParser.getReturnType(), context, options);
} catch (Exceptione) {
throwable = e;
thrownewRuntimeException(e);
} finally {
if (decodedResponse != null || throwable != null) {
endTracingSpan(decodedResponse, throwable, context);
}
}
}
Request Setup
/** * Create a HttpRequest for the provided Swagger method using the provided arguments. * * @param methodParser the Swagger method parser to use * @param args the arguments to use to populate the method's annotation values * @return a HttpRequest * @throws IOException thrown if the body contents cannot be serialized */privateHttpRequestcreateHttpRequest(SwaggerMethodParsermethodParser, Object[] args) throwsIOException {
// Sometimes people pass in a full URL for the value of their PathParam annotated argument.// This definitely happens in paging scenarios. In that case, just use the full URL and// ignore the Host annotation.finalStringpath = methodParser.setPath(args);
finalUrlBuilderpathUrlBuilder = UrlBuilder.parse(path);
finalUrlBuilderurlBuilder;
if (pathUrlBuilder.getScheme() != null) {
urlBuilder = pathUrlBuilder;
} else {
urlBuilder = newUrlBuilder();
methodParser.setSchemeAndHost(args, urlBuilder);
// Set the path after host, concatenating the path// segment in the host.if (path != null && !path.isEmpty() && !"/".equals(path)) {
StringhostPath = urlBuilder.getPath();
if (hostPath == null || hostPath.isEmpty() || "/".equals(hostPath) || path.contains("://")) {
urlBuilder.setPath(path);
} else {
if (path.startsWith("/")) {
urlBuilder.setPath(hostPath + path);
} else {
urlBuilder.setPath(hostPath + "/" + path);
}
}
}
}
methodParser.setEncodedQueryParameters(args, urlBuilder);
finalURLurl = urlBuilder.toUrl();
finalHttpRequestrequest = configRequest(newHttpRequest(methodParser.getHttpMethod(), url),
methodParser, args);
// Headers from Swagger method arguments always take precedence over inferred headers from body typesHttpHeadershttpHeaders = request.getHeaders();
methodParser.setHeaders(args, httpHeaders);
returnrequest;
}
@SuppressWarnings("unchecked")
privateHttpRequestconfigRequest(finalHttpRequestrequest, finalSwaggerMethodParsermethodParser,
finalObject[] args) throwsIOException {
finalObjectbodyContentObject = methodParser.setBody(args);
if (bodyContentObject == null) {
request.getHeaders().set("Content-Length", "0");
} else {
// We read the content type from the @BodyParam annotationStringcontentType = methodParser.getBodyContentType();
// If this is null or empty, the service interface definition is incomplete and should// be fixed to ensure correct definitions are appliedif (contentType == null || contentType.isEmpty()) {
if (bodyContentObjectinstanceofbyte[] || bodyContentObjectinstanceofString) {
contentType = ContentType.APPLICATION_OCTET_STREAM;
} else {
contentType = ContentType.APPLICATION_JSON;
}
}
request.getHeaders().set("Content-Type", contentType);
if (bodyContentObjectinstanceofBinaryData) {
BinaryDatabinaryData = (BinaryData) bodyContentObject;
if (binaryData.getLength() != null) {
request.setHeader("Content-Length", binaryData.getLength().toString());
}
// The request body is not read here. The call to `toFluxByteBuffer()` lazily converts the underlying// content of BinaryData to a Flux<ByteBuffer> which is then read by HttpClient implementations when// sending the request to the service. There is no memory copy that happens here. Sources like// InputStream, File and Flux<ByteBuffer> will not be eagerly copied into memory until it's required// by the HttpClient implementations.request.setContent(binaryData);
returnrequest;
}
// TODO(jogiles) this feels hackybooleanisJson = false;
finalString[] contentTypeParts = contentType.split(";");
for (finalStringcontentTypePart : contentTypeParts) {
if (contentTypePart.trim().equalsIgnoreCase(ContentType.APPLICATION_JSON)) {
isJson = true;
break;
}
}
if (isJson) {
ByteArrayOutputStreamstream = newAccessibleByteArrayOutputStream();
serializer.serialize(bodyContentObject, SerializerEncoding.JSON, stream);
request.setHeader("Content-Length", String.valueOf(stream.size()));
request.setContent(BinaryData.fromStream(newByteArrayInputStream(stream.toByteArray(), 0, stream.size())));
} elseif (bodyContentObjectinstanceofbyte[]) {
request.setBody((byte[]) bodyContentObject);
} elseif (bodyContentObjectinstanceofString) {
finalStringbodyContentString = (String) bodyContentObject;
if (!bodyContentString.isEmpty()) {
request.setBody(bodyContentString);
}
} elseif (bodyContentObjectinstanceofByteBuffer) {
request.setBody(((ByteBuffer) bodyContentObject).array());
} else {
ByteArrayOutputStreamstream = newAccessibleByteArrayOutputStream();
serializer.serialize(bodyContentObject, SerializerEncoding.fromHeaders(request.getHeaders()), stream);
request.setHeader("Content-Length", String.valueOf(stream.size()));
request.setBody(stream.toByteArray());
}
}
returnrequest;
}
Response Handling
privateObjecthandleRestResponseReturnType(finalHttpDecodedResponseresponse,
finalSwaggerMethodParsermethodParser,
finalTypeentityType) {
if (TypeUtil.isTypeOrSubTypeOf(entityType, Response.class)) {
finalTypebodyType = TypeUtil.getRestResponseBodyType(entityType);
if (TypeUtil.isTypeOrSubTypeOf(bodyType, Void.class)) {
response.getSourceResponse().getContent().toBytes();
returncreateResponseSync(response, entityType, null);
} else {
ObjectbodyAsObject = handleBodyReturnTypeSync(response, methodParser, bodyType);
Response<?> httpResponse = createResponseSync(response, entityType, bodyAsObject);
if (httpResponse == null) {
returncreateResponseSync(response, entityType, null);
}
returnhttpResponse;
}
} else {
// For now, we're just throwing if the Maybe didn't emit a value.returnhandleBodyReturnTypeSync(response, methodParser, entityType);
}
}
@SuppressWarnings("unchecked")
privateResponse<?> createResponseSync(HttpDecodedResponseresponse, TypeentityType, ObjectbodyAsObject) {
finalClass<? extendsResponse<?>> cls = (Class<? extendsResponse<?>>) TypeUtil.getRawClass(entityType);
finalHttpResponsehttpResponse = response.getSourceResponse();
finalHttpRequestrequest = httpResponse.getRequest();
finalintstatusCode = httpResponse.getStatusCode();
finalHttpHeadersheaders = httpResponse.getHeaders();
finalObjectdecodedHeaders = response.getDecodedHeaders();
// Inspection of the response type needs to be performed to determine which course of action should be taken to// instantiate the Response<?> from the HttpResponse.//// If the type is either the Response or PagedResponse interface from azure-core a new instance of either// ResponseBase or PagedResponseBase can be returned.if (cls.equals(Response.class)) {
// For Response return a new instance of ResponseBase cast to the class.returncls.cast(newResponseBase<>(request, statusCode, headers, bodyAsObject, decodedHeaders));
} elseif (cls.equals(PagedResponse.class)) {
// For PagedResponse return a new instance of PagedResponseBase cast to the class.//// PagedResponse needs an additional check that the bodyAsObject implements Page.//// If the bodyAsObject is null use the constructor that take items and continuation token with null.// Otherwise, use the constructor that take Page.if (bodyAsObject != null && !TypeUtil.isTypeOrSubTypeOf(bodyAsObject.getClass(), Page.class)) {
throwLOGGER.logExceptionAsError(newRuntimeException(MUST_IMPLEMENT_PAGE_ERROR));
} elseif (bodyAsObject == null) {
return (cls.cast(newPagedResponseBase<>(request, statusCode, headers, null, null,
decodedHeaders)));
} else {
return (cls.cast(newPagedResponseBase<>(request, statusCode, headers, (Page<?>) bodyAsObject,
decodedHeaders)));
}
}
// Otherwise, rely on reflection, for now, to get the best constructor to use to create the Response sub-type.//// Ideally, in the future the SDKs won't need to dabble in reflection here as the Response sub-types should be// given a way to register their constructor as a callback method that consumes HttpDecodedResponse and the// body as an Object.MethodHandlectr = RESPONSE_CONSTRUCTORS_CACHE.get(cls);
if (ctr == null) {
thrownewRuntimeException("Cannot find suitable constructor for class " + cls);
}
returnRESPONSE_CONSTRUCTORS_CACHE.invokeSync(ctr, response, bodyAsObject);
}
privateObjecthandleBodyReturnTypeSync(finalHttpDecodedResponseresponse,
finalSwaggerMethodParsermethodParser, finalTypeentityType) {
finalintresponseStatusCode = response.getSourceResponse().getStatusCode();
finalHttpMethodhttpMethod = methodParser.getHttpMethod();
finalTypereturnValueWireType = methodParser.getReturnValueWireType();
finalObjectresult;
if (httpMethod == HttpMethod.HEAD
&& (TypeUtil.isTypeOrSubTypeOf(
entityType, Boolean.TYPE) || TypeUtil.isTypeOrSubTypeOf(entityType, Boolean.class))) {
booleanisSuccess = (responseStatusCode / 100) == 2;
result = isSuccess;
} elseif (TypeUtil.isTypeOrSubTypeOf(entityType, byte[].class)) {
// byte[]byte[] responseBodyBytes = response.getSourceResponse().getContent().toBytes();
if (returnValueWireType == Base64Url.class) {
// Base64UrlresponseBodyBytes = newBase64Url(responseBodyBytes).decodedBytes();
}
result = responseBodyBytes;
} elseif (TypeUtil.isTypeOrSubTypeOf(entityType, BinaryData.class)) {
// BinaryData// The raw response is directly used to create an instance of BinaryData which then provides// different methods to read the response. The reading of the response is delayed until BinaryData// is read and depending on which format the content is converted into, the response is not necessarily// fully copied into memory resulting in lesser overall memory usage.result = response.getSourceResponse().getContent();
} else {
// Mono<Object> or Mono<Page<T>>result = response.getDecodedBodySync((byte[]) null);
}
returnresult;
}
/** * Handle the provided asynchronous HTTP response and return the deserialized value. * * @param httpDecodedResponse the asynchronous HTTP response to the original HTTP request * @param methodParser the SwaggerMethodParser that the request originates from * @param returnType the type of value that will be returned * @param context Additional context that is passed through the Http pipeline during the service call. * @return the deserialized result */privateObjecthandleRestReturnType(finalHttpDecodedResponsehttpDecodedResponse,
finalSwaggerMethodParsermethodParser,
finalTypereturnType,
finalContextcontext,
finalRequestOptionsoptions) {
finalHttpDecodedResponseexpectedResponse =
ensureExpectedStatus(httpDecodedResponse, methodParser, options);
finalObjectresult;
if (TypeUtil.isTypeOrSubTypeOf(returnType, void.class) || TypeUtil.isTypeOrSubTypeOf(returnType,
Void.class)) {
// ProxyMethod ReturnType: Voidresult = expectedResponse;
} else {
// ProxyMethod ReturnType: T where T != async (Mono, Flux) or sync Void// Block the deserialization until a value T is receivedresult = handleRestResponseReturnType(httpDecodedResponse, methodParser, returnType);
}
returnresult;
}
Tracing Handling
/** * Starts the tracing span for the current service call, additionally set metadata attributes on the span by passing * additional context information. * * @param method Service method being called. * @param context Context information about the current service call. * @return The updated context containing the span context. */privateContextstartTracingSpan(Methodmethod, Contextcontext) {
// First check if tracing is enabled. This is an optimized operation, so it is done first.if (!TracerProxy.isTracingEnabled()) {
returncontext;
}
// Then check if this method disabled tracing. This requires walking a linked list, so do it last.if ((boolean) context.getData(Tracer.DISABLE_TRACING_KEY).orElse(false)) {
returncontext;
}
StringspanName = interfaceParser.getServiceName() + "." + method.getName();
context = TracerProxy.setSpanName(spanName, context);
returnTracerProxy.start(spanName, context);
}
// This handles each onX for the response mono.// The signal indicates the status and contains the metadata we need to end the tracing span.privatestaticvoidendTracingSpan(HttpDecodedResponsehttpDecodedResponse, Throwablethrowable, ContexttracingContext) {
// Get the context that was added to the mono, this will contain the information needed to end the span.ObjectdisableTracingValue = (tracingContext.getData(Tracer.DISABLE_TRACING_KEY).isPresent()
? tracingContext.getData(Tracer.DISABLE_TRACING_KEY).get() : null);
booleandisableTracing = Boolean.TRUE.equals(disableTracingValue != null ? disableTracingValue : false);
if (tracingContext == null || disableTracing) {
return;
}
intstatusCode = 0;
// On next contains the response information.if (httpDecodedResponse != null) {
//noinspection ConstantConditionsstatusCode = httpDecodedResponse.getSourceResponse().getStatusCode();
} elseif (throwable != null) {
// The last status available is on error, this contains the error thrown by the REST response.// Only HttpResponseException contain a status code, this is the base REST response.if (throwableinstanceofHttpResponseException) {
HttpResponseExceptionexception = (HttpResponseException) throwable;
statusCode = exception.getResponse().getStatusCode();
}
}
TracerProxy.end(statusCode, throwable, tracingContext);
}
Helper Methods
@SuppressWarnings("deprecation")
voidvalidateResumeOperationIsNotPresent(Methodmethod) {
// Use the fully-qualified class name as javac will throw deprecation warnings on imports when the class is// marked as deprecated.if (method.isAnnotationPresent(com.azure.core.annotation.ResumeOperation.class)) {
throwLOGGER.logExceptionAsError(newIllegalStateException("'ResumeOperation' isn't supported."));
}
}
staticContextmergeRequestOptionsContext(Contextcontext, RequestOptionsoptions) {
if (options == null) {
returncontext;
}
ContextoptionsContext = options.getContext();
if (optionsContext != null && optionsContext != Context.NONE) {
context = CoreUtils.mergeContexts(context, optionsContext);
}
returncontext;
}
staticBinaryDatavalidateLengthSync(finalHttpRequestrequest) {
finalBinaryDatabinaryData = request.getContent();
if (binaryData == null) {
returnbinaryData;
}
finallongexpectedLength = Long.parseLong(request.getHeaders().getValue("Content-Length"));
Longlength = binaryData.getLength();
BinaryDataContentbdc = BinaryDataHelper.getContent(binaryData);
if (length == null) {
if (bdcinstanceofFluxByteBufferContent) {
thrownewIllegalStateException("Flux Byte Buffer is not supported in Synchronous Rest Proxy.");
} elseif (bdcinstanceofInputStreamContent) {
InputStreamContentinputStreamContent = ((InputStreamContent) bdc);
InputStreaminputStream = inputStreamContent.toStream();
LengthValidatingInputStreamlengthValidatingInputStream =
newLengthValidatingInputStream(inputStream, expectedLength);
returnBinaryData.fromStream(lengthValidatingInputStream);
} else {
byte[] b = (bdc).toBytes();
longlen = b.length;
if (len > expectedLength) {
thrownewUnexpectedLengthException(String.format(BODY_TOO_LARGE,
len, expectedLength), len, expectedLength);
}
returnBinaryData.fromBytes(b);
}
} else {
if (length > expectedLength) {
thrownewUnexpectedLengthException(String.format(BODY_TOO_LARGE,
length, expectedLength), length, expectedLength);
}
returnbinaryData;
}
}
privatestaticExceptioninstantiateUnexpectedException(finalUnexpectedExceptionInformationexception,
finalHttpResponsehttpResponse, finalbyte[] responseContent, finalObjectresponseDecodedContent) {
finalintresponseStatusCode = httpResponse.getStatusCode();
finalStringcontentType = httpResponse.getHeaderValue("Content-Type");
finalStringbodyRepresentation;
if ("application/octet-stream".equalsIgnoreCase(contentType)) {
bodyRepresentation = "(" + httpResponse.getHeaderValue("Content-Length") + "-byte body)";
} else {
bodyRepresentation = responseContent == null || responseContent.length == 0
? "(empty body)"
: "\"" + newString(responseContent, StandardCharsets.UTF_8) + "\"";
}
Exceptionresult;
try {
finalConstructor<? extendsHttpResponseException> exceptionConstructor = exception.getExceptionType()
.getConstructor(String.class, HttpResponse.class, exception.getExceptionBodyType());
result = exceptionConstructor.newInstance("Status code " + responseStatusCode + ", " + bodyRepresentation,
httpResponse, responseDecodedContent);
} catch (ReflectiveOperationExceptione) {
Stringmessage = "Status code " + responseStatusCode + ", but an instance of "
+ exception.getExceptionType().getCanonicalName() + " cannot be created."
+ " Response body: " + bodyRepresentation;
result = newIOException(message, e);
}
returnresult;
}
/** * Create a publisher that (1) emits error if the provided response {@code decodedResponse} has 'disallowed status * code' OR (2) emits provided response if it's status code ia allowed. * * 'disallowed status code' is one of the status code defined in the provided SwaggerMethodParser or is in the int[] * of additional allowed status codes. * * @param decodedResponse The HttpResponse to check. * @param methodParser The method parser that contains information about the service interface method that initiated * the HTTP request. * @return An async-version of the provided decodedResponse. */privateHttpDecodedResponseensureExpectedStatus(finalHttpDecodedResponsedecodedResponse,
finalSwaggerMethodParsermethodParser, RequestOptionsoptions) {
finalintresponseStatusCode = decodedResponse.getSourceResponse().getStatusCode();
// If the response was success or configured to not return an error status when the request fails, return the// decoded response.if (methodParser.isExpectedResponseStatusCode(responseStatusCode)
|| (options != null && options.getErrorOptions().contains(ErrorOptions.NO_THROW))) {
returndecodedResponse;
}
// Otherwise, the response wasn't successful and the error object needs to be parsed.byte[] responseBytes = decodedResponse.getSourceResponse().getContent().toBytes();
if (responseBytes == null || responseBytes.length == 0) {
// No body, create exception empty content string no exception body object.thrownewRuntimeException(instantiateUnexpectedException(
methodParser.getUnexpectedException(responseStatusCode), decodedResponse.getSourceResponse(),
null, null));
} else {
ObjectdecodedBody = decodedResponse.getDecodedBodySync(responseBytes);
// create exception with un-decodable content string and without exception body object.thrownewRuntimeException(instantiateUnexpectedException(
methodParser.getUnexpectedException(responseStatusCode),
decodedResponse.getSourceResponse(), responseBytes, decodedBody));
}
}
/** * Create an instance of the default serializer. * * @return the default serializer */privatestaticSerializerAdaptercreateDefaultSerializer() {
returnJacksonAdapter.createDefaultSerializerAdapter();
}
/** * Create the default HttpPipeline. * * @return the default HttpPipeline */privatestaticHttpPipelinecreateDefaultPipeline() {
List<HttpPipelinePolicy> policies = newArrayList<>();
policies.add(newUserAgentPolicy());
policies.add(newRetryPolicy());
policies.add(newCookiePolicy());
returnnewHttpPipelineBuilder()
.policies(policies.toArray(newHttpPipelinePolicy[0]))
.build();
}
/** * Create a proxy implementation of the provided Swagger interface. * * @param swaggerInterface the Swagger interface to provide a proxy implementation for * @param <A> the type of the Swagger interface * @return a proxy implementation of the provided Swagger interface */publicstatic <A> Acreate(Class<A> swaggerInterface) {
returncreate(swaggerInterface, createDefaultPipeline(), createDefaultSerializer());
}
/** * Create a proxy implementation of the provided Swagger interface. * * @param swaggerInterface the Swagger interface to provide a proxy implementation for * @param httpPipeline the HttpPipelinePolicy and HttpClient pipeline that will be used to send Http requests * @param <A> the type of the Swagger interface * @return a proxy implementation of the provided Swagger interface */publicstatic <A> Acreate(Class<A> swaggerInterface, HttpPipelinehttpPipeline) {
returncreate(swaggerInterface, httpPipeline, createDefaultSerializer());
}
/** * Create a proxy implementation of the provided Swagger interface. * * @param swaggerInterface the Swagger interface to provide a proxy implementation for * @param httpPipeline the HttpPipelinePolicy and HttpClient pipline that will be used to send Http requests * @param serializer the serializer that will be used to convert POJOs to and from request and response bodies * @param <A> the type of the Swagger interface. * @return a proxy implementation of the provided Swagger interface */@SuppressWarnings("unchecked")
publicstatic <A> Acreate(Class<A> swaggerInterface, HttpPipelinehttpPipeline, SerializerAdapterserializer) {
finalSwaggerInterfaceParserinterfaceParser = newSwaggerInterfaceParser(swaggerInterface, serializer);
finalSyncRestProxyrestProxy = newSyncRestProxy(httpPipeline, serializer, interfaceParser);
return (A) Proxy.newProxyInstance(swaggerInterface.getClassLoader(), newClass<?>[]{swaggerInterface},
restProxy);
}
}
[main] INFOcom.azure.core.implementation.jackson.JacksonVersion - Packageversions: jackson-annotations=2.13.1, jackson-core=2.13.1, jackson-databind=2.13.1, jackson-dataformat-xml=2.13.1, jackson-datatype-jsr310=2.13.1, azure-core=1.27.0-beta.1, Troubleshootingversionconflicts: https://aka.ms/azsdk/java/dependency/troubleshoot
[reactor-http-kqueue-2] INFOcom.azure.identity.implementation.HttpPipelineAdapter - [Authenticatedaccount] ClientID: 27d85698-74dd-4dd9-9f2d-8ae0e0e0ac4f, TenantID: c21a53bd-e8d7-412c-b60f-19e9f7fb0c7e, UserPrincipalName: 72f988bf-86f1-41af-91ab-2d7cd011db47, ObjectID (user): NoUserPrincipalNameavailable.)
[ForkJoinPool.commonPool-worker-9] INFOcom.azure.identity.ClientSecretCredential - AzureIdentity => getToken() resultforscopes [https://vault.azure.net/.default]: SUCCESS
[ForkJoinPool.commonPool-worker-9] INFOcom.azure.core.implementation.AccessTokenCache - Acquiredanewaccesstoken.
[reactor-http-kqueue-1] WARNcom.azure.security.keyvault.secrets.SecretAsyncClient - Failedtosetsecret - testStatuscode403, "{"error":{"code":"Forbidden","message":"Theuser, grouporapplication'appid=27d85698-74dd-4dd9-9f2d-8ae0e0e0ac4f;oid=c21a53bd-e8d7-412c-b60f-19e9f7fb0c7e;iss=https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/'doesnothavesecretssetpermissiononkeyvault'vigera-test-secrets;location=westus2'. Forhelpresolvingthisissue, pleaseseehttps://go.microsoft.com/fwlink/?linkid=2125287","innererror":{"code":"AccessDenied"}}}"Exceptioninthread"main"com.azure.core.exception.HttpResponseException: Statuscode403, "{"error":{"code":"Forbidden","message":"The user, group or application 'appid=27d85698-74dd-4dd9-9f2d-8ae0e0e0ac4f;oid=c21a53bd-e8d7-412c-b60f-19e9f7fb0c7e;iss=https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/' does not have secrets set permission on key vault 'vigera-test-secrets;location=westus2'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287","innererror":{"code":"AccessDenied"}}}"
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.azure.core.http.rest.RestProxy.instantiateUnexpectedException(RestProxy.java:390)
at com.azure.core.http.rest.RestProxy.lambda$ensureExpectedStatus$7(RestProxy.java:445)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.signalCached(MonoCacheTime.java:337)
at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onNext(MonoCacheTime.java:354)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onSubscribe(MonoCacheTime.java:293)
at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:192)
at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:143)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2194)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2068)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:174)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
at reactor.core.publisher.Operators$MonoInnerProducerBase.complete(Operators.java:2664)
at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:180)
at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onComplete(MonoFlatMapMany.java:260)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150)
at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onComplete(FluxDoFinally.java:145)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1817)
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159)
at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:213)
at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:269)
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:400)
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:419)
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:473)
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:702)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1371)
at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1245)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1285)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:449)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.kqueue.AbstractKQueueStreamChannel$KQueueStreamUnsafe.readReady(AbstractKQueueStreamChannel.java:544)
at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe.readReady(AbstractKQueueChannel.java:383)
at io.netty.channel.kqueue.KQueueEventLoop.processReady(KQueueEventLoop.java:211)
at io.netty.channel.kqueue.KQueueEventLoop.run(KQueueEventLoop.java:289)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
at reactor.core.publisher.Mono.block(Mono.java:1707)
at com.test.demo.Test.main(Test.java:55)