diff --git a/docs/ApiExecutor.md b/docs/ApiExecutor.md index 4023c456..d90629e5 100644 --- a/docs/ApiExecutor.md +++ b/docs/ApiExecutor.md @@ -8,7 +8,7 @@ Direct HTTP access to OpenFGA endpoints. OpenFgaClient client = new OpenFgaClient(config); // Build request -ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/check") +ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/check") .pathParam("store_id", storeId) .body(Map.of("tuple_key", Map.of("user", "user:jon", "relation", "reader", "object", "doc:1"))) .build(); @@ -26,7 +26,7 @@ ApiResponse rawResponse = client.apiExecutor().send(request).get(); **Factory:** ```java -ApiExecutorRequestBuilder.builder(String method, String path) +ApiExecutorRequestBuilder.builder(HttpMethod method, String path) ``` **Methods:** @@ -40,7 +40,7 @@ ApiExecutorRequestBuilder.builder(String method, String path) **Example:** ```java -ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/write") +ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/write") .pathParam("store_id", "01ABC") .queryParam("dry_run", "true") .header("X-Request-ID", "uuid") @@ -74,7 +74,7 @@ T getData() // Deserialized data ### GET Request ```java -ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}/feature") +ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}/feature") .pathParam("store_id", storeId) .build(); @@ -84,7 +84,7 @@ client.apiExecutor().send(request, FeatureResponse.class) ### POST with Body ```java -ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/bulk-delete") +ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/bulk-delete") .pathParam("store_id", storeId) .queryParam("force", "true") .body(new BulkDeleteRequest("2023-01-01", "user", 1000)) diff --git a/examples/api-executor/README.md b/examples/api-executor/README.md index 8622c1a7..a01c983f 100644 --- a/examples/api-executor/README.md +++ b/examples/api-executor/README.md @@ -56,7 +56,7 @@ All requests will succeed (except #5 which intentionally triggers an error for d Build requests using the builder pattern: ```java -ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/custom-endpoint") +ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/custom-endpoint") .pathParam("store_id", storeId) .queryParam("page_size", "20") .queryParam("continuation_token", "eyJwayI6...") diff --git a/examples/api-executor/src/main/java/dev/openfga/sdk/example/ApiExecutorExample.java b/examples/api-executor/src/main/java/dev/openfga/sdk/example/ApiExecutorExample.java index a3c9e59d..b19426f8 100644 --- a/examples/api-executor/src/main/java/dev/openfga/sdk/example/ApiExecutorExample.java +++ b/examples/api-executor/src/main/java/dev/openfga/sdk/example/ApiExecutorExample.java @@ -1,5 +1,6 @@ package dev.openfga.sdk.example; +import dev.openfga.sdk.api.client.HttpMethod; import dev.openfga.sdk.api.client.OpenFgaClient; import dev.openfga.sdk.api.client.ApiExecutorRequestBuilder; import dev.openfga.sdk.api.configuration.ClientConfiguration; @@ -63,7 +64,7 @@ public static void main(String[] args) throws Exception { private static String listStoresExample(OpenFgaClient fgaClient) { try { // Build the raw request for GET /stores - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores").build(); + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores").build(); // Execute with typed response var response = fgaClient @@ -101,7 +102,7 @@ private static String listStoresExample(OpenFgaClient fgaClient) { */ private static String createStoreForExamples(OpenFgaClient fgaClient) throws Exception { String storeName = "api-executor-example-" + UUID.randomUUID().toString().substring(0, 8); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .body(Map.of("name", storeName)) .build(); @@ -116,7 +117,7 @@ private static String createStoreForExamples(OpenFgaClient fgaClient) throws Exc */ private static void getStoreRawJsonExample(OpenFgaClient fgaClient, String storeId) { try { - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}") .pathParam("store_id", storeId) .build(); @@ -137,7 +138,7 @@ private static void getStoreRawJsonExample(OpenFgaClient fgaClient, String store */ private static void listStoresWithPaginationExample(OpenFgaClient fgaClient) { try { - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores") .queryParam("page_size", "2") .build(); @@ -167,7 +168,7 @@ private static void listStoresWithPaginationExample(OpenFgaClient fgaClient) { private static void createStoreWithHeadersExample(OpenFgaClient fgaClient) { try { String storeName = "raw-api-custom-headers-" + UUID.randomUUID().toString().substring(0, 8); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .header("X-Example-Header", "custom-value") .header("X-Request-ID", "req-" + UUID.randomUUID()) .body(Map.of("name", storeName)) @@ -192,8 +193,7 @@ private static void createStoreWithHeadersExample(OpenFgaClient fgaClient) { */ private static void errorHandlingExample(OpenFgaClient fgaClient) { try { - // Try to get a non-existent store - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}") .pathParam("store_id", "01ZZZZZZZZZZZZZZZZZZZZZZZ9") .build(); diff --git a/src/main/java/dev/openfga/sdk/api/client/ApiExecutor.java b/src/main/java/dev/openfga/sdk/api/client/ApiExecutor.java index 0523a283..a6271e34 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ApiExecutor.java +++ b/src/main/java/dev/openfga/sdk/api/client/ApiExecutor.java @@ -14,7 +14,7 @@ * *

Example:

*
{@code
- * ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/endpoint")
+ * ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/endpoint")
  *     .pathParam("store_id", storeId)
  *     .body(requestData)
  *     .build();
diff --git a/src/main/java/dev/openfga/sdk/api/client/ApiExecutorRequestBuilder.java b/src/main/java/dev/openfga/sdk/api/client/ApiExecutorRequestBuilder.java
index 7214d38e..56998819 100644
--- a/src/main/java/dev/openfga/sdk/api/client/ApiExecutorRequestBuilder.java
+++ b/src/main/java/dev/openfga/sdk/api/client/ApiExecutorRequestBuilder.java
@@ -2,7 +2,6 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * Fluent builder for constructing HTTP requests to OpenFGA API endpoints.
@@ -11,7 +10,7 @@
  *
  * 

Example:

*
{@code
- * ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/endpoint")
+ * ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/endpoint")
  *     .pathParam("store_id", storeId)
  *     .queryParam("limit", "50")
  *     .body(requestObject)
@@ -19,17 +18,14 @@
  * }
*/ public class ApiExecutorRequestBuilder { - private static final Set VALID_HTTP_METHODS = - Set.of("GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"); - - private final String method; + private final HttpMethod method; private final String path; private final Map pathParams; private final Map queryParams; private final Map headers; private Object body; - private ApiExecutorRequestBuilder(String method, String path) { + private ApiExecutorRequestBuilder(HttpMethod method, String path) { this.method = method; this.path = path; this.pathParams = new HashMap<>(); @@ -41,26 +37,20 @@ private ApiExecutorRequestBuilder(String method, String path) { /** * Creates a new ApiExecutorRequestBuilder instance. * - * @param method HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) + * @param method HTTP method enum value (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) * @param path API path with optional placeholders like {store_id} * @return New ApiExecutorRequestBuilder instance * @throws IllegalArgumentException if method or path is invalid */ - public static ApiExecutorRequestBuilder builder(String method, String path) { - if (method == null || method.trim().isEmpty()) { - throw new IllegalArgumentException("HTTP method cannot be null or empty"); + public static ApiExecutorRequestBuilder builder(HttpMethod method, String path) { + if (method == null) { + throw new IllegalArgumentException("HTTP method cannot be null"); } if (path == null || path.trim().isEmpty()) { throw new IllegalArgumentException("Path cannot be null or empty"); } - String upperMethod = method.toUpperCase(); - if (!VALID_HTTP_METHODS.contains(upperMethod)) { - throw new IllegalArgumentException( - "Invalid HTTP method: " + method + ". Valid methods: " + VALID_HTTP_METHODS); - } - - return new ApiExecutorRequestBuilder(upperMethod, path); + return new ApiExecutorRequestBuilder(method, path); } /** @@ -115,6 +105,7 @@ public ApiExecutorRequestBuilder body(Object body) { this.body = body; return this; } + /** * Builds and returns the request for use with the API Executor. * This method must be called to complete request construction. @@ -129,7 +120,7 @@ public ApiExecutorRequestBuilder build() { } String getMethod() { - return method; + return method.name(); } String getPath() { diff --git a/src/main/java/dev/openfga/sdk/api/client/HttpMethod.java b/src/main/java/dev/openfga/sdk/api/client/HttpMethod.java new file mode 100644 index 00000000..976899be --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/client/HttpMethod.java @@ -0,0 +1,44 @@ +package dev.openfga.sdk.api.client; + +/** + * Enumeration of standard HTTP methods supported by the OpenFGA API. + * This enum provides type safety and prevents invalid HTTP methods from being used. + * + * @since 0.8.0 + */ +public enum HttpMethod { + /** + * HTTP GET method - used for retrieving resources. + */ + GET, + + /** + * HTTP POST method - used for creating resources or submitting data. + */ + POST, + + /** + * HTTP PUT method - used for updating or replacing resources. + */ + PUT, + + /** + * HTTP DELETE method - used for deleting resources. + */ + DELETE, + + /** + * HTTP PATCH method - used for partially updating resources. + */ + PATCH, + + /** + * HTTP HEAD method - used for retrieving resource metadata without the body. + */ + HEAD, + + /** + * HTTP OPTIONS method - used for describing communication options. + */ + OPTIONS +} diff --git a/src/test-integration/java/dev/openfga/sdk/api/client/ApiExecutorIntegrationTest.java b/src/test-integration/java/dev/openfga/sdk/api/client/ApiExecutorIntegrationTest.java index f2cca941..780c2fc5 100644 --- a/src/test-integration/java/dev/openfga/sdk/api/client/ApiExecutorIntegrationTest.java +++ b/src/test-integration/java/dev/openfga/sdk/api/client/ApiExecutorIntegrationTest.java @@ -51,7 +51,7 @@ public void rawRequest_listStores() throws Exception { // Use ApiExecutor to list stores (equivalent to GET /stores) ApiExecutorRequestBuilder request = - ApiExecutorRequestBuilder.builder("GET", "/stores").build(); + ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores").build(); ApiResponse response = fga.apiExecutor().send(request, ListStoresResponse.class).get(); @@ -84,7 +84,7 @@ public void rawRequest_createStore_typedResponse() throws Exception { requestBody.put("name", storeName); // Use ApiExecutor to create store (equivalent to POST /stores) - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .body(requestBody) .build(); @@ -115,7 +115,7 @@ public void rawRequest_createStore_rawJsonResponse() throws Exception { requestBody.put("name", storeName); // Use ApiExecutor to create store and get raw JSON response - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .body(requestBody) .build(); @@ -147,7 +147,7 @@ public void rawRequest_getStore_withPathParams() throws Exception { String storeId = createStoreUsingRawRequest(storeName); // Use ApiExecutor to get store details (equivalent to GET /stores/{store_id}) - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}") .pathParam("store_id", storeId) .build(); @@ -176,8 +176,8 @@ public void rawRequest_automaticStoreIdReplacement() throws Exception { fga.setStoreId(storeId); // Use ApiExecutor WITHOUT providing store_id path param - it should be auto-replaced - ApiExecutorRequestBuilder request = - ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}").build(); + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}") + .build(); ApiResponse response = fga.apiExecutor().send(request, GetStoreResponse.class).get(); @@ -228,7 +228,7 @@ public void rawRequest_writeAuthorizationModel() throws Exception { // Use ApiExecutor to write authorization model ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( - "POST", "/stores/{store_id}/authorization-models") + HttpMethod.POST, "/stores/{store_id}/authorization-models") .body(requestBody) .build(); @@ -261,7 +261,7 @@ public void rawRequest_readAuthorizationModels_withQueryParams() throws Exceptio // Use ApiExecutor to read authorization models with query parameters ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( - "GET", "/stores/{store_id}/authorization-models") + HttpMethod.GET, "/stores/{store_id}/authorization-models") .queryParam("page_size", "10") .queryParam("continuation_token", "") .build(); @@ -308,7 +308,8 @@ public void rawRequest_check() throws Exception { tupleKey.put("object", "document:budget"); checkBody.put("tuple_key", tupleKey); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/check") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( + HttpMethod.POST, "/stores/{store_id}/check") .body(checkBody) .build(); @@ -331,7 +332,7 @@ public void rawRequest_withCustomHeaders() throws Exception { requestBody.put("name", storeName); // Use ApiExecutor with custom headers - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .body(requestBody) .header("X-Custom-Header", "custom-value") .header("X-Request-ID", "test-123") @@ -353,7 +354,7 @@ public void rawRequest_withCustomHeaders() throws Exception { @Test public void rawRequest_errorHandling_notFound() throws Exception { // Try to get a non-existent store - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}") .pathParam("store_id", "non-existent-store-id") .build(); @@ -383,7 +384,7 @@ public void rawRequest_listStores_withPagination() throws Exception { } // Use ApiExecutor to list stores with pagination - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores") .queryParam("page_size", "2") .build(); @@ -409,7 +410,7 @@ private String createStoreUsingRawRequest(String storeName) throws Exception { Map requestBody = new HashMap<>(); requestBody.put("name", storeName); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") .body(requestBody) .build(); @@ -445,7 +446,7 @@ private String writeSimpleAuthorizationModel(String storeId) throws Exception { requestBody.put("type_definitions", typeDefinitions); ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( - "POST", "/stores/{store_id}/authorization-models") + HttpMethod.POST, "/stores/{store_id}/authorization-models") .pathParam("store_id", storeId) .body(requestBody) .build(); @@ -467,7 +468,8 @@ private void writeTupleUsingRawRequest(String storeId, String user, String relat Map requestBody = new HashMap<>(); requestBody.put("writes", Map.of("tuple_keys", List.of(tupleKey))); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", "/stores/{store_id}/write") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( + HttpMethod.POST, "/stores/{store_id}/write") .pathParam("store_id", storeId) .body(requestBody) .build(); diff --git a/src/test/java/dev/openfga/sdk/api/client/ApiExecutorTest.java b/src/test/java/dev/openfga/sdk/api/client/ApiExecutorTest.java index 725bca7c..6db3cf50 100644 --- a/src/test/java/dev/openfga/sdk/api/client/ApiExecutorTest.java +++ b/src/test/java/dev/openfga/sdk/api/client/ApiExecutorTest.java @@ -65,7 +65,7 @@ public void rawApi_canAccessViaClient() throws Exception { @Test public void rawRequestBuilder_canBuildBasicRequest() { - ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}/test") + ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}/test") .build(); assertNotNull(builder); @@ -75,7 +75,7 @@ public void rawRequestBuilder_canBuildBasicRequest() { @Test public void rawRequestBuilder_canAddPathParameters() { - ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}/test") + ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores/{store_id}/test") .pathParam("store_id", "my-store") .build(); @@ -86,7 +86,7 @@ public void rawRequestBuilder_canAddPathParameters() { @Test public void rawRequestBuilder_canAddQueryParameters() { - ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder("GET", "/test") + ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/test") .queryParam("page", "1") .queryParam("limit", "10") .build(); @@ -99,7 +99,7 @@ public void rawRequestBuilder_canAddQueryParameters() { @Test public void rawRequestBuilder_canAddHeaders() { - ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder("GET", "/test") + ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/test") .header("X-Custom-Header", "custom-value") .build(); @@ -113,8 +113,9 @@ public void rawRequestBuilder_canAddBody() { Map body = new HashMap<>(); body.put("key", "value"); - ApiExecutorRequestBuilder builder = - ApiExecutorRequestBuilder.builder("POST", "/test").body(body).build(); + ApiExecutorRequestBuilder builder = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/test") + .body(body) + .build(); assertTrue(builder.hasBody()); assertEquals(body, builder.getBody()); @@ -125,38 +126,25 @@ public void rawRequestBuilder_throwsExceptionForNullMethod() { assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder(null, "/test")); } - @Test - public void rawRequestBuilder_throwsExceptionForEmptyMethod() { - assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder("", "/test")); - } - @Test public void rawRequestBuilder_throwsExceptionForNullPath() { - assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder("GET", null)); + assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder(HttpMethod.GET, null)); } @Test public void rawRequestBuilder_throwsExceptionForEmptyPath() { - assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder("GET", "")); - } - - @Test - public void rawRequestBuilder_throwsExceptionForInvalidHttpMethod() { - IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder("INVALID", "/test")); - assertTrue(exception.getMessage().contains("Invalid HTTP method")); + assertThrows(IllegalArgumentException.class, () -> ApiExecutorRequestBuilder.builder(HttpMethod.GET, "")); } @Test public void rawRequestBuilder_acceptsValidHttpMethods() { - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("GET", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("POST", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("PUT", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("PATCH", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("DELETE", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("HEAD", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("OPTIONS", "/test")); - assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder("get", "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.PUT, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.PATCH, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.DELETE, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.HEAD, "/test")); + assertDoesNotThrow(() -> ApiExecutorRequestBuilder.builder(HttpMethod.OPTIONS, "/test")); } @Test @@ -171,7 +159,7 @@ public void rawApi_canSendGetRequestWithTypedResponse() throws Exception { // Build and send request OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .build(); @@ -206,7 +194,7 @@ public void rawApi_canSendPostRequestWithBody() throws Exception { requestBody.put("name", "test"); requestBody.put("value", 123); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("POST", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.POST, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .body(requestBody) .build(); @@ -236,7 +224,7 @@ public void rawApi_canSendRequestWithQueryParameters() throws Exception { .withBody("{\"success\":true,\"count\":10,\"message\":\"Success\"}"))); // Build and send request OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .queryParam("force", "true") .queryParam("limit", "10") @@ -267,7 +255,7 @@ public void rawApi_canReturnRawJsonString() throws Exception { // Build and send request OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .build(); @@ -288,7 +276,8 @@ public void rawApi_handlesHttpErrors() throws Exception { // Build and send request OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", "/stores/{store_id}/non-existent") + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder( + HttpMethod.GET, "/stores/{store_id}/non-existent") .pathParam("store_id", DEFAULT_STORE_ID) .build(); @@ -308,7 +297,7 @@ public void rawApi_handlesServerErrors() throws Exception { // Build and send request OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .build(); @@ -331,7 +320,7 @@ public void rawApi_supportsCustomHeaders() throws Exception { // Build and send request with custom header OpenFgaClient client = createClient(); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", DEFAULT_STORE_ID) .header("X-Custom-Header", "custom-value") .header("X-Request-ID", "12345") @@ -364,7 +353,7 @@ public void rawApi_encodesPathParameters() throws Exception { ClientConfiguration config = new ClientConfiguration().apiUrl(fgaApiUrl).storeId("store with spaces"); OpenFgaClient client = new OpenFgaClient(config); - ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder("GET", EXPERIMENTAL_ENDPOINT) + ApiExecutorRequestBuilder request = ApiExecutorRequestBuilder.builder(HttpMethod.GET, EXPERIMENTAL_ENDPOINT) .pathParam("store_id", "store with spaces") .build(); @@ -389,7 +378,7 @@ public void rawApi_throwsExceptionForNullBuilder() throws Exception { public void rawApi_throwsExceptionForNullResponseType() throws Exception { OpenFgaClient client = createClient(); ApiExecutorRequestBuilder request = - ApiExecutorRequestBuilder.builder("GET", "/test").build(); + ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/test").build(); assertThrows(IllegalArgumentException.class, () -> client.apiExecutor().send(request, null)); } } diff --git a/src/test/java/dev/openfga/sdk/api/client/HttpMethodCompilationTest.java b/src/test/java/dev/openfga/sdk/api/client/HttpMethodCompilationTest.java new file mode 100644 index 00000000..8e6ac96d --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/client/HttpMethodCompilationTest.java @@ -0,0 +1,38 @@ +package dev.openfga.sdk.api.client; + +/** + * Simple compilation test to verify HttpMethod enum and ApiExecutorRequestBuilder work together. + */ +public class HttpMethodCompilationTest { + public static void main(String[] args) { + // Test 1: Using HttpMethod enum (new way) + ApiExecutorRequestBuilder request1 = ApiExecutorRequestBuilder.builder(HttpMethod.GET, "/stores") + .queryParam("page_size", "10") + .build(); + + System.out.println("✓ HttpMethod.GET works: " + request1.getMethod()); + + // Test 2: Using HttpMethod enum with POST + ApiExecutorRequestBuilder request2 = ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores") + .body("test") + .build(); + + System.out.println("✓ HttpMethod.POST works: " + request2.getMethod()); + + // Test 3: All HTTP methods + for (HttpMethod method : HttpMethod.values()) { + ApiExecutorRequestBuilder request = + ApiExecutorRequestBuilder.builder(method, "/test").build(); + System.out.println("✓ " + method + " works: " + request.getMethod()); + } + + // Test 4: Verify getMethod() returns string + ApiExecutorRequestBuilder request4 = + ApiExecutorRequestBuilder.builder(HttpMethod.PUT, "/test").build(); + String methodString = request4.getMethod(); + assert "PUT".equals(methodString) : "Expected 'PUT' but got '" + methodString + "'"; + System.out.println("✓ getMethod() returns correct string: " + methodString); + + System.out.println("\n✓✓✓ All compilation tests passed! ✓✓✓"); + } +}