diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 5b3f3b6..966dcc2 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -90,6 +90,7 @@ src/main/java/dev/openfga/sdk/api/client/ClientListRelationsRequest.java src/main/java/dev/openfga/sdk/api/client/ClientReadRequest.java src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java +src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java src/main/java/dev/openfga/sdk/api/configuration/ApiToken.java src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java @@ -166,6 +167,11 @@ src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java src/main/java/dev/openfga/sdk/api/model/WriteRequest.java src/main/java/dev/openfga/sdk/errors/ApiException.java +src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java +src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java +src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java +src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java +src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java src/main/java/dev/openfga/sdk/errors/FgaInvalidParameterException.java src/main/java/dev/openfga/sdk/util/Pair.java src/main/java/dev/openfga/sdk/util/StringUtil.java diff --git a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java index f5be21a..6c01c0f 100644 --- a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java +++ b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java @@ -13,7 +13,6 @@ package dev.openfga.sdk.api; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.openfga.sdk.api.auth.*; import dev.openfga.sdk.api.client.*; import dev.openfga.sdk.api.configuration.*; @@ -40,9 +39,7 @@ import dev.openfga.sdk.errors.*; import dev.openfga.sdk.util.Pair; import java.io.IOException; -import java.io.InputStream; import java.net.URI; -import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; @@ -50,7 +47,6 @@ import java.util.List; import java.util.StringJoiner; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; /** * A low-level API representation of an OpenFGA server. @@ -58,28 +54,21 @@ * Most code should favor the simpler and higher-level {@link OpenFgaClient} when calling an OpenFGA server. */ public class OpenFgaApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; private final Configuration configuration; + + private final ApiClient apiClient; private final OAuth2Client oAuth2Client; - private final Consumer memberVarInterceptor; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; public OpenFgaApi(Configuration configuration) throws FgaInvalidParameterException { this(configuration, new ApiClient()); } public OpenFgaApi(Configuration configuration, ApiClient apiClient) throws FgaInvalidParameterException { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); + this.apiClient = apiClient; this.configuration = configuration; - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); if (configuration.getCredentials().getCredentialsMethod() == CredentialsMethod.CLIENT_CREDENTIALS) { - this.oAuth2Client = new OAuth2Client(configuration, apiClient.getHttpClient(), apiClient.getObjectMapper()); + this.oAuth2Client = new OAuth2Client(configuration, apiClient); } else { this.oAuth2Client = null; } @@ -116,24 +105,10 @@ public CompletableFuture check( private CompletableFuture check(String storeId, CheckRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = checkRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("check", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + checkRequestBuilder(storeId, body, configuration).build(); + return new HttpRequestAttempt<>(request, "check", CheckResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -172,11 +147,13 @@ private CompletableFuture> checkWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = checkRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("check", localVarResponse)); @@ -188,8 +165,9 @@ private CompletableFuture> checkWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -228,7 +206,7 @@ private HttpRequest.Builder checkRequestBuilder(String storeId, CheckRequest bod } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -237,8 +215,8 @@ private HttpRequest.Builder checkRequestBuilder(String storeId, CheckRequest bod if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -272,24 +250,9 @@ public CompletableFuture createStore( private CompletableFuture createStore(CreateStoreRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = createStoreRequestBuilder(body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("createStore", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = createStoreRequestBuilder(body, configuration).build(); + return new HttpRequestAttempt<>(request, "createStore", CreateStoreResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -325,11 +288,13 @@ private CompletableFuture> createStoreWithHttpI CreateStoreRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = createStoreRequestBuilder(body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("createStore", localVarResponse)); @@ -341,8 +306,11 @@ private CompletableFuture> createStoreWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -377,7 +345,7 @@ private HttpRequest.Builder createStoreRequestBuilder(CreateStoreRequest body, C } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -386,8 +354,8 @@ private HttpRequest.Builder createStoreRequestBuilder(CreateStoreRequest body, C if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -419,15 +387,10 @@ public CompletableFuture deleteStore(String storeId, ConfigurationOverride private CompletableFuture deleteStore(String storeId, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = deleteStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("deleteStore", localVarResponse)); - } - return CompletableFuture.completedFuture(null); - }); + HttpRequest request = + deleteStoreRequestBuilder(storeId, configuration).build(); + return new HttpRequestAttempt<>(request, "deleteStore", Void.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -463,11 +426,13 @@ private CompletableFuture> deleteStoreWithHttpInfo(String stor throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = deleteStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("deleteStore", localVarResponse)); @@ -510,8 +475,8 @@ private HttpRequest.Builder deleteStoreRequestBuilder(String storeId, Configurat if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -547,24 +512,10 @@ public CompletableFuture expand( private CompletableFuture expand(String storeId, ExpandRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = expandRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("expand", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + expandRequestBuilder(storeId, body, configuration).build(); + return new HttpRequestAttempt<>(request, "expand", ExpandResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -603,11 +554,13 @@ private CompletableFuture> expandWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = expandRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("expand", localVarResponse)); @@ -619,8 +572,9 @@ private CompletableFuture> expandWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -660,7 +614,7 @@ private HttpRequest.Builder expandRequestBuilder(String storeId, ExpandRequest b } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -669,8 +623,8 @@ private HttpRequest.Builder expandRequestBuilder(String storeId, ExpandRequest b if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -703,24 +657,9 @@ public CompletableFuture getStore(String storeId, Configuratio private CompletableFuture getStore(String storeId, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = getStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("getStore", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = getStoreRequestBuilder(storeId, configuration).build(); + return new HttpRequestAttempt<>(request, "getStore", GetStoreResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -756,11 +695,13 @@ private CompletableFuture> getStoreWithHttpInfo( String storeId, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = getStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("getStore", localVarResponse)); @@ -772,8 +713,10 @@ private CompletableFuture> getStoreWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -811,8 +754,8 @@ private HttpRequest.Builder getStoreRequestBuilder(String storeId, Configuration if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -849,24 +792,10 @@ private CompletableFuture listObjects( String storeId, ListObjectsRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = listObjectsRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("listObjects", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + listObjectsRequestBuilder(storeId, body, configuration).build(); + return new HttpRequestAttempt<>(request, "listObjects", ListObjectsResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -905,11 +834,13 @@ private CompletableFuture> listObjectsWithHttpI throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = listObjectsRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("listObjects", localVarResponse)); @@ -921,8 +852,11 @@ private CompletableFuture> listObjectsWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -963,7 +897,7 @@ private HttpRequest.Builder listObjectsRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -972,8 +906,8 @@ private HttpRequest.Builder listObjectsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1010,25 +944,10 @@ private CompletableFuture listStores( Integer pageSize, String continuationToken, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - listStoresRequestBuilder(pageSize, continuationToken, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("listStores", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = listStoresRequestBuilder(pageSize, continuationToken, configuration) + .build(); + return new HttpRequestAttempt<>(request, "listStores", ListStoresResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1068,11 +987,13 @@ private CompletableFuture> listStoresWithHttpInf try { HttpRequest.Builder localVarRequestBuilder = listStoresRequestBuilder(pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("listStores", localVarResponse)); @@ -1084,8 +1005,10 @@ private CompletableFuture> listStoresWithHttpInf localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1138,8 +1061,8 @@ private HttpRequest.Builder listStoresRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1175,24 +1098,10 @@ public CompletableFuture read( private CompletableFuture read(String storeId, ReadRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = readRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("read", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + readRequestBuilder(storeId, body, configuration).build(); + return new HttpRequestAttempt<>(request, "read", ReadResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1231,11 +1140,13 @@ private CompletableFuture> readWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = readRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("read", localVarResponse)); @@ -1247,8 +1158,9 @@ private CompletableFuture> readWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1287,7 +1199,7 @@ private HttpRequest.Builder readRequestBuilder(String storeId, ReadRequest body, } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -1296,8 +1208,8 @@ private HttpRequest.Builder readRequestBuilder(String storeId, ReadRequest body, if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1334,25 +1246,11 @@ private CompletableFuture readAssertions( String storeId, String authorizationModelId, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - readAssertionsRequestBuilder(storeId, authorizationModelId, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("readAssertions", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = readAssertionsRequestBuilder(storeId, authorizationModelId, configuration) + .build(); + return new HttpRequestAttempt<>( + request, "readAssertions", ReadAssertionsResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1393,11 +1291,13 @@ private CompletableFuture> readAssertionsWit try { HttpRequest.Builder localVarRequestBuilder = readAssertionsRequestBuilder(storeId, authorizationModelId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("readAssertions", localVarResponse)); @@ -1409,8 +1309,11 @@ private CompletableFuture> readAssertionsWit localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1456,8 +1359,8 @@ private HttpRequest.Builder readAssertionsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1493,27 +1396,15 @@ public CompletableFuture readAuthorizationModel( private CompletableFuture readAuthorizationModel( String storeId, String id, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - readAuthorizationModelRequestBuilder(storeId, id, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture( - new ApiException("readAuthorizationModel", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = readAuthorizationModelRequestBuilder(storeId, id, configuration) + .build(); + return new HttpRequestAttempt<>( + request, + "readAuthorizationModel", + ReadAuthorizationModelResponse.class, + apiClient, + configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1552,11 +1443,13 @@ private CompletableFuture> readAutho try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelRequestBuilder(storeId, id, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -1569,9 +1462,11 @@ private CompletableFuture> readAutho localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1615,8 +1510,8 @@ private HttpRequest.Builder readAuthorizationModelRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1657,27 +1552,16 @@ private CompletableFuture readAuthorizationMode String storeId, Integer pageSize, String continuationToken, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - readAuthorizationModelsRequestBuilder(storeId, pageSize, continuationToken, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture( - new ApiException("readAuthorizationModels", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = readAuthorizationModelsRequestBuilder( + storeId, pageSize, continuationToken, configuration) + .build(); + return new HttpRequestAttempt<>( + request, + "readAuthorizationModels", + ReadAuthorizationModelsResponse.class, + apiClient, + configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1721,11 +1605,13 @@ private CompletableFuture> readAuth try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelsRequestBuilder(storeId, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -1738,9 +1624,11 @@ private CompletableFuture> readAuth localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1799,8 +1687,8 @@ private HttpRequest.Builder readAuthorizationModelsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1847,25 +1735,10 @@ private CompletableFuture readChanges( String storeId, String type, Integer pageSize, String continuationToken, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - readChangesRequestBuilder(storeId, type, pageSize, continuationToken, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("readChanges", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = readChangesRequestBuilder(storeId, type, pageSize, continuationToken, configuration) + .build(); + return new HttpRequestAttempt<>(request, "readChanges", ReadChangesResponse.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -1915,11 +1788,13 @@ private CompletableFuture> readChangesWithHttpI try { HttpRequest.Builder localVarRequestBuilder = readChangesRequestBuilder(storeId, type, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("readChanges", localVarResponse)); @@ -1931,8 +1806,11 @@ private CompletableFuture> readChangesWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1992,8 +1870,8 @@ private HttpRequest.Builder readChangesRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2029,24 +1907,10 @@ public CompletableFuture write( private CompletableFuture write(String storeId, WriteRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = writeRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("write", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + writeRequestBuilder(storeId, body, configuration).build(); + return new HttpRequestAttempt<>(request, "write", Object.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -2085,11 +1949,13 @@ private CompletableFuture> writeWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = writeRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("write", localVarResponse)); @@ -2101,8 +1967,9 @@ private CompletableFuture> writeWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2141,7 +2008,7 @@ private HttpRequest.Builder writeRequestBuilder(String storeId, WriteRequest bod } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2150,8 +2017,8 @@ private HttpRequest.Builder writeRequestBuilder(String storeId, WriteRequest bod if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2194,17 +2061,10 @@ private CompletableFuture writeAssertions( String storeId, String authorizationModelId, WriteAssertionsRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - writeAssertionsRequestBuilder(storeId, authorizationModelId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture( - new ApiException("writeAssertions", localVarResponse)); - } - return CompletableFuture.completedFuture(null); - }); + HttpRequest request = writeAssertionsRequestBuilder(storeId, authorizationModelId, body, configuration) + .build(); + return new HttpRequestAttempt<>(request, "writeAssertions", Void.class, apiClient, configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -2251,11 +2111,13 @@ private CompletableFuture> writeAssertionsWithHttpInfo( try { HttpRequest.Builder localVarRequestBuilder = writeAssertionsRequestBuilder(storeId, authorizationModelId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -2308,7 +2170,7 @@ private HttpRequest.Builder writeAssertionsRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("PUT", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2317,8 +2179,8 @@ private HttpRequest.Builder writeAssertionsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2355,27 +2217,15 @@ private CompletableFuture writeAuthorizationMod String storeId, WriteAuthorizationModelRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = - writeAuthorizationModelRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture( - new ApiException("writeAuthorizationModel", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = writeAuthorizationModelRequestBuilder(storeId, body, configuration) + .build(); + return new HttpRequestAttempt<>( + request, + "writeAuthorizationModel", + WriteAuthorizationModelResponse.class, + apiClient, + configuration) + .attemptHttpRequest(); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -2415,11 +2265,13 @@ private CompletableFuture> writeAut try { HttpRequest.Builder localVarRequestBuilder = writeAuthorizationModelRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + var responseInterceptor = apiClient.getAsyncResponseInterceptor(); + if (responseInterceptor != null) { + responseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -2432,9 +2284,11 @@ private CompletableFuture> writeAut localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2476,7 +2330,7 @@ private HttpRequest.Builder writeAuthorizationModelRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2485,8 +2339,8 @@ private HttpRequest.Builder writeAuthorizationModelRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } diff --git a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java index 5c74533..118a3e2 100644 --- a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java +++ b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java @@ -12,23 +12,19 @@ package dev.openfga.sdk.api.auth; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.openfga.sdk.api.client.ApiClient; +import dev.openfga.sdk.api.client.HttpRequestAttempt; import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.errors.ApiException; import dev.openfga.sdk.errors.FgaInvalidParameterException; import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.http.HttpClient; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.time.Instant; import java.util.concurrent.CompletableFuture; public class OAuth2Client { - private final HttpClient httpClient; + private final ApiClient apiClient; private final Credentials credentials; - private final ObjectMapper mapper; private final AccessToken token = new AccessToken(); private final CredentialsFlowRequest authRequest; private final String apiTokenIssuer; @@ -37,14 +33,11 @@ public class OAuth2Client { * Initializes a new instance of the {@link OAuth2Client} class * * @param configuration Configuration, including credentials, that can be used to retrieve an access tokens - * @param httpClient Http client */ - public OAuth2Client(Configuration configuration, HttpClient httpClient, ObjectMapper mapper) - throws FgaInvalidParameterException { + public OAuth2Client(Configuration configuration, ApiClient apiClient) throws FgaInvalidParameterException { this.credentials = configuration.getCredentials(); - this.httpClient = httpClient; - this.mapper = mapper; + this.apiClient = apiClient; this.apiTokenIssuer = credentials.getClientCredentials().getApiTokenIssuer(); this.authRequest = new CredentialsFlowRequest(); this.authRequest.setClientId(credentials.getClientCredentials().getClientId()); @@ -78,27 +71,15 @@ public CompletableFuture getAccessToken() throws FgaInvalidParameterExce private CompletableFuture exchangeToken() throws ApiException, FgaInvalidParameterException { try { - byte[] body = mapper.writeValueAsBytes(authRequest); + byte[] body = apiClient.getObjectMapper().writeValueAsBytes(authRequest); Configuration config = new Configuration().apiUrl("https://" + apiTokenIssuer); HttpRequest request = ApiClient.requestBuilder("POST", "/oauth/token", body, config) .build(); - return httpClient - .sendAsync(request, HttpResponse.BodyHandlers.ofString()) - .thenCompose(httpResponse -> { - if (httpResponse.statusCode() != HttpURLConnection.HTTP_OK) { - return CompletableFuture.failedFuture(new ApiException("exchangeToken", httpResponse)); - } - try { - CredentialsFlowResponse response = - mapper.readValue(httpResponse.body(), CredentialsFlowResponse.class); - return CompletableFuture.completedFuture(response); - } catch (Exception e) { - return CompletableFuture.failedFuture(e); - } - }); + return new HttpRequestAttempt<>(request, "exchangeToken", CredentialsFlowResponse.class, apiClient, config) + .attemptHttpRequest(); } catch (IOException e) { throw new ApiException(e); } diff --git a/src/main/java/dev/openfga/sdk/api/client/ApiClient.java b/src/main/java/dev/openfga/sdk/api/client/ApiClient.java index 6901fae..89ae992 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ApiClient.java +++ b/src/main/java/dev/openfga/sdk/api/client/ApiClient.java @@ -266,6 +266,17 @@ public HttpClient getHttpClient() { return builder.build(); } + /** + * Get the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient.Builder getHttpClientBuilder() { + return builder; + } + /** * Set a custom {@link ObjectMapper} to serialize and deserialize the request * and response bodies. diff --git a/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java new file mode 100644 index 0000000..9372948 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java @@ -0,0 +1,111 @@ +package dev.openfga.sdk.api.client; + +import static dev.openfga.sdk.util.StringUtil.isNullOrWhitespace; + +import dev.openfga.sdk.api.configuration.BaseConfiguration; +import dev.openfga.sdk.errors.*; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.concurrent.*; + +public class HttpRequestAttempt { + private final ApiClient apiClient; + private final BaseConfiguration configuration; + private final Class clazz; + private final String name; + private final HttpRequest request; + + public HttpRequestAttempt( + HttpRequest request, String name, Class clazz, ApiClient apiClient, BaseConfiguration configuration) + throws FgaInvalidParameterException { + if (configuration.getMaxRetries() == null) { + throw new FgaInvalidParameterException("maxRetries", "Configuration"); + } + this.apiClient = apiClient; + this.configuration = configuration; + this.name = name; + this.request = request; + this.clazz = clazz; + } + + public CompletableFuture attemptHttpRequest() throws ApiException { + int retryNumber = 0; + return attemptHttpRequest(apiClient.getHttpClient(), retryNumber, null); + } + + private CompletableFuture attemptHttpRequest(HttpClient httpClient, int retryNumber, Throwable previousError) { + return httpClient + .sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenCompose(response -> { + try { + checkStatus(name, response, previousError); + } catch (FgaApiRateLimitExceededError | FgaApiInternalError retryableError) { + if (retryNumber < configuration.getMaxRetries()) { + HttpClient delayingClient = getDelayedHttpClient(); + return attemptHttpRequest(delayingClient, retryNumber + 1, retryableError); + } + return CompletableFuture.failedFuture(retryableError); + } catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + + return deserializeResponse(response); + }); + } + + private CompletableFuture deserializeResponse(HttpResponse response) { + if (clazz == Void.class && isNullOrWhitespace(response.body())) { + return CompletableFuture.completedFuture(null); + } + + try { + T deserialized = apiClient.getObjectMapper().readValue(response.body(), clazz); + return CompletableFuture.completedFuture(deserialized); + } catch (IOException e) { + // Malformed response. + return CompletableFuture.failedFuture(new ApiException(e)); + } + } + + private HttpClient getDelayedHttpClient() { + Duration retryDelay = configuration.getMinimumRetryDelay(); + return apiClient + .getHttpClientBuilder() + .executor(CompletableFuture.delayedExecutor(retryDelay.toNanos(), TimeUnit.NANOSECONDS)) + .build(); + } + + private static void checkStatus(String name, HttpResponse response, Throwable previousError) + throws ApiException { + int status = response.statusCode(); + String body = response.body(); + + switch (status) { + case HttpURLConnection.HTTP_BAD_REQUEST: + case 422: // HTTP 422 Unprocessable Entity + throw new FgaApiValidationError(name, previousError, status, response.headers(), body); + + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw new FgaApiAuthenticationError(name, previousError, status, response.headers(), body); + + case HttpURLConnection.HTTP_NOT_FOUND: + throw new FgaApiNotFoundError(name, previousError, status, response.headers(), body); + + case 429: // HTTP 429 Too Many Requests + throw new FgaApiRateLimitExceededError(name, previousError, status, response.headers(), body); + + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw new FgaApiInternalError(name, previousError, status, response.headers(), body); + } + + // FGA and OAuth2 servers are only expected to return HTTP 2xx responses. + if (status < 200 || 300 <= status) { + throw new ApiException(name, previousError, status, response.headers(), body); + } + } +} diff --git a/src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java b/src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java index d69162b..d302294 100644 --- a/src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java +++ b/src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java @@ -22,4 +22,8 @@ public interface BaseConfiguration { Duration getReadTimeout(); Duration getConnectTimeout(); + + Integer getMaxRetries(); + + Duration getMinimumRetryDelay(); } diff --git a/src/main/java/dev/openfga/sdk/api/configuration/ClientConfiguration.java b/src/main/java/dev/openfga/sdk/api/configuration/ClientConfiguration.java index 5cd9bb5..3d10d0f 100644 --- a/src/main/java/dev/openfga/sdk/api/configuration/ClientConfiguration.java +++ b/src/main/java/dev/openfga/sdk/api/configuration/ClientConfiguration.java @@ -132,4 +132,16 @@ public ClientConfiguration connectTimeout(Duration connectTimeout) { super.connectTimeout(connectTimeout); return this; } + + @Override + public ClientConfiguration maxRetries(int maxRetries) { + super.maxRetries(maxRetries); + return this; + } + + @Override + public ClientConfiguration minimumRetryDelay(Duration minimumRetryDelay) { + super.minimumRetryDelay(minimumRetryDelay); + return this; + } } diff --git a/src/main/java/dev/openfga/sdk/api/configuration/Configuration.java b/src/main/java/dev/openfga/sdk/api/configuration/Configuration.java index a45f915..82b6d99 100644 --- a/src/main/java/dev/openfga/sdk/api/configuration/Configuration.java +++ b/src/main/java/dev/openfga/sdk/api/configuration/Configuration.java @@ -39,6 +39,8 @@ public class Configuration implements BaseConfiguration { private String userAgent; private Duration readTimeout; private Duration connectTimeout; + private int maxRetries; + private Duration minimumRetryDelay; public Configuration() { this.apiUrl = DEFAULT_API_URL; @@ -101,6 +103,12 @@ public Configuration override(ConfigurationOverride configurationOverride) { Duration overrideConnectTimeout = configurationOverride.getConnectTimeout(); result.connectTimeout(overrideConnectTimeout != null ? overrideConnectTimeout : connectTimeout); + Integer overrideMaxRetries = configurationOverride.getMaxRetries(); + result.maxRetries(overrideMaxRetries != null ? overrideMaxRetries : maxRetries); + + Duration overrideMinimumRetryDelay = configurationOverride.getMinimumRetryDelay(); + result.minimumRetryDelay(overrideMinimumRetryDelay != null ? overrideMinimumRetryDelay : minimumRetryDelay); + return result; } @@ -231,4 +239,24 @@ public Configuration connectTimeout(Duration connectTimeout) { public Duration getConnectTimeout() { return connectTimeout; } + + public Configuration maxRetries(int maxRetries) { + this.maxRetries = maxRetries; + return this; + } + + @Override + public Integer getMaxRetries() { + return maxRetries; + } + + public Configuration minimumRetryDelay(Duration minimumRetryDelay) { + this.minimumRetryDelay = minimumRetryDelay; + return this; + } + + @Override + public Duration getMinimumRetryDelay() { + return minimumRetryDelay; + } } diff --git a/src/main/java/dev/openfga/sdk/api/configuration/ConfigurationOverride.java b/src/main/java/dev/openfga/sdk/api/configuration/ConfigurationOverride.java index d2b31dc..1d54a00 100644 --- a/src/main/java/dev/openfga/sdk/api/configuration/ConfigurationOverride.java +++ b/src/main/java/dev/openfga/sdk/api/configuration/ConfigurationOverride.java @@ -29,6 +29,8 @@ public class ConfigurationOverride implements BaseConfiguration { private String userAgent; private Duration readTimeout; private Duration connectTimeout; + private Integer maxRetries; + private Duration minimumRetryDelay; public ConfigurationOverride() { this.apiUrl = null; @@ -157,4 +159,24 @@ public ConfigurationOverride connectTimeout(Duration connectTimeout) { public Duration getConnectTimeout() { return connectTimeout; } + + public ConfigurationOverride maxRetries(int maxRetries) { + this.maxRetries = maxRetries; + return this; + } + + @Override + public Integer getMaxRetries() { + return maxRetries; + } + + public ConfigurationOverride minimumRetryDelay(Duration minimumRetryDelay) { + this.minimumRetryDelay = minimumRetryDelay; + return this; + } + + @Override + public Duration getMinimumRetryDelay() { + return minimumRetryDelay; + } } diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java new file mode 100644 index 0000000..14a4b2d --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiAuthenticationError extends ApiException { + public FgaApiAuthenticationError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiAuthenticationError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java new file mode 100644 index 0000000..2ccf52c --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiInternalError extends ApiException { + public FgaApiInternalError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiInternalError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java new file mode 100644 index 0000000..5c395c9 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiNotFoundError extends ApiException { + public FgaApiNotFoundError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiNotFoundError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java new file mode 100644 index 0000000..73454b6 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiRateLimitExceededError extends ApiException { + public FgaApiRateLimitExceededError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiRateLimitExceededError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java new file mode 100644 index 0000000..b915ab7 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiValidationError extends ApiException { + public FgaApiValidationError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiValidationError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java index d47efb6..4572fc0 100644 --- a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java +++ b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java @@ -22,6 +22,7 @@ import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.api.model.*; import dev.openfga.sdk.errors.*; +import java.net.http.HttpClient; import java.time.Duration; import java.util.List; import java.util.concurrent.ExecutionException; @@ -40,26 +41,36 @@ public class OpenFgaApiTest { private static final String DEFAULT_TYPE = "document"; private static final String DEFAULT_OBJECT = "document:budget"; private static final String DEFAULT_SCHEMA_VERSION = "1.1"; - public static final String EMPTY_RESPONSE_BODY = "{}"; + private static final String EMPTY_RESPONSE_BODY = "{}"; + private static final int DEFAULT_MAX_RETRIES = 3; + private static final Duration DEFAULT_RETRY_DELAY = Duration.ofMillis(100); private final ObjectMapper mapper = new ObjectMapper(); private OpenFgaApi fga; private Configuration mockConfiguration; private ApiClient mockApiClient; private HttpClientMock mockHttpClient; + private HttpClient.Builder mockHttpClientBuilder; @BeforeEach public void beforeEachTest() throws Exception { mockHttpClient = new HttpClientMock(); + mockHttpClientBuilder = mock(HttpClient.Builder.class); + when(mockHttpClientBuilder.executor(any())).thenReturn(mockHttpClientBuilder); + when(mockHttpClientBuilder.build()).thenReturn(mockHttpClient); + mockConfiguration = mock(Configuration.class); when(mockConfiguration.getApiUrl()).thenReturn("https://localhost"); when(mockConfiguration.getReadTimeout()).thenReturn(Duration.ofMillis(250)); when(mockConfiguration.getCredentials()).thenReturn(new Credentials()); + when(mockConfiguration.getMaxRetries()).thenReturn(DEFAULT_MAX_RETRIES); + when(mockConfiguration.getMinimumRetryDelay()).thenReturn(DEFAULT_RETRY_DELAY); mockApiClient = mock(ApiClient.class); when(mockApiClient.getObjectMapper()).thenReturn(mapper); when(mockApiClient.getHttpClient()).thenReturn(mockHttpClient); + when(mockApiClient.getHttpClientBuilder()).thenReturn(mockHttpClientBuilder); fga = new OpenFgaApi(mockConfiguration, mockApiClient); } @@ -104,7 +115,7 @@ public void listStores_400() { // Then mockHttpClient.verify().get("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -127,7 +138,7 @@ public void listStores_404() throws Exception { // Then mockHttpClient.verify().get("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -148,8 +159,8 @@ public void listStores_500() throws Exception { .get()); // Then - mockHttpClient.verify().get("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get("https://localhost/stores").called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -189,7 +200,7 @@ public void createStore_bodyRequired() { ExecutionException.class, () -> fga.createStore(null).get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling createStore", exception.getMessage()); } @@ -207,7 +218,7 @@ public void createStore_400() throws Exception { // Then mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -228,7 +239,7 @@ public void createStore_404() throws Exception { // Then mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -247,8 +258,8 @@ public void createStore_500() throws Exception { .get()); // Then - mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post("https://localhost/stores").called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -280,7 +291,7 @@ public void getStore_storeIdRequired() { assertThrows(ExecutionException.class, () -> fga.getStore(null).get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling getStore", exception.getMessage()); } @@ -298,7 +309,7 @@ public void getStore_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -319,7 +330,7 @@ public void getStore_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -338,8 +349,8 @@ public void getStore_500() throws Exception { ExecutionException.class, () -> fga.getStore(DEFAULT_STORE_ID).get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -368,7 +379,7 @@ public void deleteStore_storeIdRequired() { ExecutionException.class, () -> fga.deleteStore(null).get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling deleteStore", exception.getMessage()); } @@ -387,7 +398,7 @@ public void deleteStore_400() throws Exception { // Then mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -409,7 +420,7 @@ public void deleteStore_404() throws Exception { // Then mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -429,8 +440,8 @@ public void deleteStore_500() throws Exception { .get()); // Then - mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().delete(deleteUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -472,7 +483,7 @@ public void readAuthorizationModels_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'storeId' when calling readAuthorizationModels", exception.getMessage()); @@ -495,7 +506,7 @@ public void readAuthorizationModels_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -519,7 +530,7 @@ public void readAuthorizationModels_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -541,8 +552,8 @@ public void readAuthorizationModels_500() throws Exception { .get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -580,7 +591,7 @@ public void writeAuthorizationModel_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'storeId' when calling writeAuthorizationModel", exception.getMessage()); @@ -594,7 +605,7 @@ public void writeAuthorizationModel_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'body' when calling writeAuthorizationModel", exception.getMessage()); } @@ -614,7 +625,7 @@ DEFAULT_STORE_ID, new WriteAuthorizationModelRequest()) // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -636,7 +647,7 @@ DEFAULT_STORE_ID, new WriteAuthorizationModelRequest()) // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -656,8 +667,8 @@ DEFAULT_STORE_ID, new WriteAuthorizationModelRequest()) .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -695,7 +706,7 @@ public void readAuthorizationModel_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'storeId' when calling readAuthorizationModel", exception.getMessage()); } @@ -708,7 +719,7 @@ public void readAuthorizationModel_idRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'id' when calling readAuthorizationModel", exception.getMessage()); } @@ -728,7 +739,7 @@ public void readAuthorizationModel_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -751,7 +762,7 @@ public void readAuthorizationModel_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -772,8 +783,8 @@ public void readAuthorizationModel_500() throws Exception { .get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -817,7 +828,7 @@ public void readChanges_storeIdRequired() throws Exception { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling readChanges", exception.getMessage()); } @@ -839,7 +850,7 @@ public void readChanges_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -864,7 +875,7 @@ public void readChanges_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -887,8 +898,8 @@ public void readChanges_500() throws Exception { .get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -936,7 +947,7 @@ public void read_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling read", exception.getMessage()); } @@ -947,7 +958,7 @@ public void read_bodyRequired() { ExecutionException.class, () -> fga.read(DEFAULT_STORE_ID, null).get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling read", exception.getMessage()); } @@ -966,7 +977,7 @@ public void read_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -988,7 +999,7 @@ public void read_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1008,8 +1019,8 @@ public void read_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1075,7 +1086,7 @@ public void write_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling write", exception.getMessage()); } @@ -1087,7 +1098,7 @@ public void write_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling write", exception.getMessage()); } @@ -1106,7 +1117,7 @@ public void write_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1128,7 +1139,7 @@ public void write_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1148,8 +1159,8 @@ public void write_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1192,7 +1203,7 @@ public void check_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling check", exception.getMessage()); } @@ -1204,7 +1215,7 @@ public void check_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling check", exception.getMessage()); } @@ -1223,7 +1234,7 @@ public void check_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1245,7 +1256,7 @@ public void check_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1265,8 +1276,8 @@ public void check_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1320,7 +1331,7 @@ public void expand_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling expand", exception.getMessage()); } @@ -1332,7 +1343,7 @@ public void expand_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling expand", exception.getMessage()); } @@ -1351,7 +1362,7 @@ public void expand_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1373,7 +1384,7 @@ public void expand_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1393,8 +1404,8 @@ public void expand_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1436,7 +1447,7 @@ public void listObjects_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling listObjects", exception.getMessage()); } @@ -1448,7 +1459,7 @@ public void listObjects_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling listObjects", exception.getMessage()); } @@ -1467,7 +1478,7 @@ public void listObjects_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1489,7 +1500,7 @@ public void listObjects_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1509,8 +1520,8 @@ public void listObjects_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1552,7 +1563,7 @@ public void readAssertions_storeIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling readAssertions", exception.getMessage()); } @@ -1564,7 +1575,7 @@ public void readAssertions_authModelIdRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'authorizationModelId' when calling readAssertions", exception.getMessage()); @@ -1585,7 +1596,7 @@ public void readAssertions_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1607,7 +1618,7 @@ public void readAssertions_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1627,8 +1638,8 @@ public void readAssertions_500() throws Exception { .get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1668,7 +1679,7 @@ null, DEFAULT_AUTH_MODEL_ID, new WriteAssertionsRequest()) .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'storeId' when calling writeAssertions", exception.getMessage()); } @@ -1680,7 +1691,7 @@ DEFAULT_STORE_ID, null, new WriteAssertionsRequest()) .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'authorizationModelId' when calling writeAssertions", exception.getMessage()); @@ -1694,7 +1705,7 @@ public void writeAssertions_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling writeAssertions", exception.getMessage()); } @@ -1713,7 +1724,7 @@ DEFAULT_STORE_ID, DEFAULT_AUTH_MODEL_ID, new WriteAssertionsRequest()) // Then mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1735,7 +1746,7 @@ DEFAULT_STORE_ID, DEFAULT_AUTH_MODEL_ID, new WriteAssertionsRequest()) // Then mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1755,8 +1766,8 @@ DEFAULT_STORE_ID, DEFAULT_AUTH_MODEL_ID, new WriteAssertionsRequest()) .get()); // Then - mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().put(putUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); diff --git a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java index 8819c66..1a6a847 100644 --- a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java @@ -2,9 +2,12 @@ import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.fasterxml.jackson.databind.ObjectMapper; import com.pgssoft.httpclient.HttpClientMock; +import dev.openfga.sdk.api.client.ApiClient; import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.errors.FgaInvalidParameterException; import org.junit.jupiter.api.BeforeEach; @@ -36,7 +39,11 @@ public void setup() throws FgaInvalidParameterException { var configuration = new Configuration().apiUrl("").credentials(credentials); - oAuth2 = new OAuth2Client(configuration, mockHttpClient, mapper); + var apiClient = mock(ApiClient.class); + when(apiClient.getHttpClient()).thenReturn(mockHttpClient); + when(apiClient.getObjectMapper()).thenReturn(mapper); + + oAuth2 = new OAuth2Client(configuration, apiClient); } @Test diff --git a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java index ed83e90..3747da9 100644 --- a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java @@ -21,6 +21,7 @@ import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.api.model.*; import dev.openfga.sdk.errors.*; +import java.net.http.HttpClient; import java.time.Duration; import java.util.List; import java.util.concurrent.ExecutionException; @@ -39,26 +40,36 @@ public class OpenFgaClientTest { private static final String DEFAULT_TYPE = "document"; private static final String DEFAULT_OBJECT = "document:budget"; private static final String DEFAULT_SCHEMA_VERSION = "1.1"; - public static final String EMPTY_RESPONSE_BODY = "{}"; + private static final String EMPTY_RESPONSE_BODY = "{}"; + private static final int DEFAULT_MAX_RETRIES = 3; + private static final Duration DEFAULT_RETRY_DELAY = Duration.ofMillis(100); private OpenFgaClient fga; private ClientConfiguration clientConfiguration; private HttpClientMock mockHttpClient; + private HttpClient.Builder mockHttpClientBuilder; @BeforeEach public void beforeEachTest() throws Exception { mockHttpClient = new HttpClientMock(); + mockHttpClientBuilder = mock(HttpClient.Builder.class); + when(mockHttpClientBuilder.executor(any())).thenReturn(mockHttpClientBuilder); + when(mockHttpClientBuilder.build()).thenReturn(mockHttpClient); + clientConfiguration = new ClientConfiguration() .storeId(DEFAULT_STORE_ID) .authorizationModelId(DEFAULT_AUTH_MODEL_ID) .apiUrl("https://localhost") .credentials(new Credentials()) - .readTimeout(Duration.ofMillis(250)); + .readTimeout(Duration.ofMillis(250)) + .maxRetries(DEFAULT_MAX_RETRIES) + .minimumRetryDelay(DEFAULT_RETRY_DELAY); ApiClient mockApiClient = mock(ApiClient.class); when(mockApiClient.getHttpClient()).thenReturn(mockHttpClient); when(mockApiClient.getObjectMapper()).thenReturn(new ObjectMapper()); + when(mockApiClient.getHttpClientBuilder()).thenReturn(mockHttpClientBuilder); fga = new OpenFgaClient(clientConfiguration, mockApiClient); } @@ -229,7 +240,7 @@ public void createStore_bodyRequired() { ExecutionException.class, () -> fga.createStore(null).get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals("Missing the required parameter 'body' when calling createStore", exception.getMessage()); } @@ -247,7 +258,7 @@ public void createStore_400() throws Exception { // Then mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -268,7 +279,7 @@ public void createStore_404() throws Exception { // Then mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -287,8 +298,8 @@ public void createStore_500() throws Exception { .get()); // Then - mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post("https://localhost/stores").called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -341,7 +352,7 @@ public void getStore_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -362,7 +373,7 @@ public void getStore_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -381,8 +392,8 @@ public void getStore_500() throws Exception { assertThrows(ExecutionException.class, () -> fga.getStore().get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -432,7 +443,7 @@ public void deleteStore_400() { // Then mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -453,7 +464,7 @@ public void deleteStore_404() { // Then mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -472,8 +483,8 @@ public void deleteStore_500() { assertThrows(ExecutionException.class, () -> fga.deleteStore().get()); // Then - mockHttpClient.verify().delete(deleteUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().delete(deleteUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -536,7 +547,7 @@ public void readAuthorizationModels_400() { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -559,7 +570,7 @@ public void readAuthorizationModels_404() { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -580,8 +591,8 @@ public void readAuthorizationModels_500() throws Exception { .get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -689,7 +700,7 @@ public void writeAuthorizationModel_bodyRequired() { .get()); // Then - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(ApiException.class, execException.getCause()); assertEquals( "Missing the required parameter 'body' when calling writeAuthorizationModel", exception.getMessage()); } @@ -709,7 +720,7 @@ public void writeAuthorizationModel_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -731,7 +742,7 @@ public void writeAuthorizationModel_404() { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -751,8 +762,8 @@ public void writeAuthorizationModel_500() { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -849,7 +860,7 @@ public void readAuthorizationModel_400() { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -871,7 +882,7 @@ public void readAuthorizationModel_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -891,8 +902,8 @@ public void readAuthorizationModel_500() throws Exception { ExecutionException.class, () -> fga.readAuthorizationModel().get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -960,7 +971,7 @@ public void read_400() { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -982,7 +993,7 @@ public void read_404() { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1002,8 +1013,8 @@ public void read_500() { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1126,7 +1137,7 @@ public void write_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1148,7 +1159,7 @@ public void write_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1168,8 +1179,8 @@ public void write_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1229,7 +1240,7 @@ public void check_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1251,7 +1262,7 @@ public void check_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1271,8 +1282,8 @@ public void check_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1347,7 +1358,7 @@ public void expand_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1369,7 +1380,7 @@ public void expand_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1389,8 +1400,8 @@ public void expand_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1451,7 +1462,7 @@ public void listObjects_400() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1473,7 +1484,7 @@ public void listObjects_404() throws Exception { // Then mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1493,8 +1504,8 @@ public void listObjects_500() throws Exception { .get()); // Then - mockHttpClient.verify().post(postUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1572,7 +1583,7 @@ public void readAssertions_400() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1594,7 +1605,7 @@ public void readAssertions_404() throws Exception { // Then mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1614,8 +1625,8 @@ public void readAssertions_500() throws Exception { ExecutionException.class, () -> fga.readAssertions().get()); // Then - mockHttpClient.verify().get(getUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().get(getUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody()); @@ -1690,7 +1701,7 @@ public void writeAssertions_400() throws Exception { // Then mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", @@ -1712,7 +1723,7 @@ public void writeAssertions_404() throws Exception { // Then mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + var exception = assertInstanceOf(FgaApiNotFoundError.class, execException.getCause()); assertEquals(404, exception.getCode()); assertEquals( "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}", exception.getResponseBody()); @@ -1732,8 +1743,8 @@ public void writeAssertions_500() throws Exception { ExecutionException.class, () -> fga.writeAssertions(List.of()).get()); // Then - mockHttpClient.verify().put(putUrl).called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + mockHttpClient.verify().put(putUrl).called(1 + DEFAULT_MAX_RETRIES); + var exception = assertInstanceOf(FgaApiInternalError.class, execException.getCause()); assertEquals(500, exception.getCode()); assertEquals( "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}", exception.getResponseBody());