Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ docs/RelationshipCondition.md
docs/SourceInfo.md
docs/Status.md
docs/Store.md
docs/StreamResultOfStreamedListObjectsResponse.md
docs/StreamedListObjectsResponse.md
docs/Tuple.md
docs/TupleChange.md
docs/TupleKey.md
Expand Down Expand Up @@ -155,6 +157,8 @@ src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java
src/main/java/dev/openfga/sdk/api/model/SourceInfo.java
src/main/java/dev/openfga/sdk/api/model/Status.java
src/main/java/dev/openfga/sdk/api/model/Store.java
src/main/java/dev/openfga/sdk/api/model/StreamResultOfStreamedListObjectsResponse.java
src/main/java/dev/openfga/sdk/api/model/StreamedListObjectsResponse.java
src/main/java/dev/openfga/sdk/api/model/Tuple.java
src/main/java/dev/openfga/sdk/api/model/TupleChange.java
src/main/java/dev/openfga/sdk/api/model/TupleKey.java
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ try {
| [**readAuthorizationModel**](docs/OpenFgaApi.md#readauthorizationmodel) | **GET** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model |
| [**readAuthorizationModels**](docs/OpenFgaApi.md#readauthorizationmodels) | **GET** /stores/{store_id}/authorization-models | Return all the authorization models for a particular store |
| [**readChanges**](docs/OpenFgaApi.md#readchanges) | **GET** /stores/{store_id}/changes | Return a list of all the tuple changes |
| [**streamedListObjects**](docs/OpenFgaApi.md#streamedlistobjects) | **POST** /stores/{store_id}/streamed-list-objects | Stream all objects of the given type that the user has a relation with |
| [**write**](docs/OpenFgaApi.md#write) | **POST** /stores/{store_id}/write | Add or delete tuples from the store |
| [**writeAssertions**](docs/OpenFgaApi.md#writeassertions) | **PUT** /stores/{store_id}/assertions/{authorization_model_id} | Upsert assertions for an authorization model ID |
| [**writeAuthorizationModel**](docs/OpenFgaApi.md#writeauthorizationmodel) | **POST** /stores/{store_id}/authorization-models | Create a new authorization model |
Expand Down Expand Up @@ -1310,6 +1311,10 @@ try {

- [Store](https://github.com/openfga/java-sdk/blob/main/docs/Store.md)

- [StreamResultOfStreamedListObjectsResponse](https://github.com/openfga/java-sdk/blob/main/docs/StreamResultOfStreamedListObjectsResponse.md)

- [StreamedListObjectsResponse](https://github.com/openfga/java-sdk/blob/main/docs/StreamedListObjectsResponse.md)

- [Tuple](https://github.com/openfga/java-sdk/blob/main/docs/Tuple.md)

- [TupleChange](https://github.com/openfga/java-sdk/blob/main/docs/TupleChange.md)
Expand Down
163 changes: 163 additions & 0 deletions docs/OpenFgaApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ All URIs are relative to *http://localhost*
| [**readAuthorizationModelsWithHttpInfo**](OpenFgaApi.md#readAuthorizationModelsWithHttpInfo) | **GET** /stores/{store_id}/authorization-models | Return all the authorization models for a particular store |
| [**readChanges**](OpenFgaApi.md#readChanges) | **GET** /stores/{store_id}/changes | Return a list of all the tuple changes |
| [**readChangesWithHttpInfo**](OpenFgaApi.md#readChangesWithHttpInfo) | **GET** /stores/{store_id}/changes | Return a list of all the tuple changes |
| [**streamedListObjects**](OpenFgaApi.md#streamedListObjects) | **POST** /stores/{store_id}/streamed-list-objects | Stream all objects of the given type that the user has a relation with |
| [**streamedListObjectsWithHttpInfo**](OpenFgaApi.md#streamedListObjectsWithHttpInfo) | **POST** /stores/{store_id}/streamed-list-objects | Stream all objects of the given type that the user has a relation with |
| [**write**](OpenFgaApi.md#write) | **POST** /stores/{store_id}/write | Add or delete tuples from the store |
| [**writeWithHttpInfo**](OpenFgaApi.md#writeWithHttpInfo) | **POST** /stores/{store_id}/write | Add or delete tuples from the store |
| [**writeAssertions**](OpenFgaApi.md#writeAssertions) | **PUT** /stores/{store_id}/assertions/{authorization_model_id} | Upsert assertions for an authorization model ID |
Expand Down Expand Up @@ -2301,6 +2303,167 @@ No authorization required
| **500** | Request failed due to internal server error. | - |


## streamedListObjects

> CompletableFuture<StreamResultOfStreamedListObjectsResponse> streamedListObjects(storeId, body)

Stream all objects of the given type that the user has a relation with

The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: 1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. 2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE.

### Example

```java
// Import classes:
import dev.openfga.sdk.api.client.ApiClient;
import dev.openfga.sdk.api.client.ApiException;
import dev.openfga.sdk.api.configuration.Configuration;
import dev.openfga.sdk.api.client.models.*;
import dev.openfga.sdk.api.OpenFgaApi;
import java.util.concurrent.CompletableFuture;

public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("http://localhost");

OpenFgaApi apiInstance = new OpenFgaApi(defaultClient);
String storeId = "storeId_example"; // String |
ListObjectsRequest body = new ListObjectsRequest(); // ListObjectsRequest |
try {
CompletableFuture<StreamResultOfStreamedListObjectsResponse> result = apiInstance.streamedListObjects(storeId, body);
System.out.println(result.get());
} catch (ApiException e) {
System.err.println("Exception when calling OpenFgaApi#streamedListObjects");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
```

### Parameters


| Name | Type | Description | Notes |
|------------- | ------------- | ------------- | -------------|
| **storeId** | **String**| | |
| **body** | [**ListObjectsRequest**](ListObjectsRequest.md)| | |

### Return type

CompletableFuture<[**StreamResultOfStreamedListObjectsResponse**](StreamResultOfStreamedListObjectsResponse.md)>


### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: application/json
- **Accept**: application/json

### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
| **200** | A successful response.(streaming responses) | - |
| **400** | Request failed due to invalid input. | - |
| **401** | Not authenticated. | - |
| **403** | Forbidden. | - |
| **404** | Request failed due to incorrect path. | - |
| **409** | Request was aborted due a transaction conflict. | - |
| **422** | Request timed out due to excessive request throttling. | - |
| **500** | Request failed due to internal server error. | - |

## streamedListObjectsWithHttpInfo

> CompletableFuture<ApiResponse<StreamResultOfStreamedListObjectsResponse>> streamedListObjects streamedListObjectsWithHttpInfo(storeId, body)

Stream all objects of the given type that the user has a relation with

The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: 1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. 2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE.

### Example

```java
// Import classes:
import dev.openfga.sdk.api.client.ApiClient;
import dev.openfga.sdk.api.client.ApiException;
import dev.openfga.sdk.api.client.ApiResponse;
import dev.openfga.sdk.api.configuration.Configuration;
import dev.openfga.sdk.api.client.models.*;
import dev.openfga.sdk.api.OpenFgaApi;
import java.util.concurrent.CompletableFuture;

public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("http://localhost");

OpenFgaApi apiInstance = new OpenFgaApi(defaultClient);
String storeId = "storeId_example"; // String |
ListObjectsRequest body = new ListObjectsRequest(); // ListObjectsRequest |
try {
CompletableFuture<ApiResponse<StreamResultOfStreamedListObjectsResponse>> response = apiInstance.streamedListObjectsWithHttpInfo(storeId, body);
System.out.println("Status code: " + response.get().getStatusCode());
System.out.println("Response headers: " + response.get().getHeaders());
System.out.println("Response body: " + response.get().getData());
} catch (InterruptedException | ExecutionException e) {
ApiException apiException = (ApiException)e.getCause();
System.err.println("Exception when calling OpenFgaApi#streamedListObjects");
System.err.println("Status code: " + apiException.getCode());
System.err.println("Response headers: " + apiException.getResponseHeaders());
System.err.println("Reason: " + apiException.getResponseBody());
e.printStackTrace();
} catch (ApiException e) {
System.err.println("Exception when calling OpenFgaApi#streamedListObjects");
System.err.println("Status code: " + e.getCode());
System.err.println("Response headers: " + e.getResponseHeaders());
System.err.println("Reason: " + e.getResponseBody());
e.printStackTrace();
}
}
}
```

### Parameters


| Name | Type | Description | Notes |
|------------- | ------------- | ------------- | -------------|
| **storeId** | **String**| | |
| **body** | [**ListObjectsRequest**](ListObjectsRequest.md)| | |

### Return type

CompletableFuture<ApiResponse<[**StreamResultOfStreamedListObjectsResponse**](StreamResultOfStreamedListObjectsResponse.md)>>


### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: application/json
- **Accept**: application/json

### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
| **200** | A successful response.(streaming responses) | - |
| **400** | Request failed due to invalid input. | - |
| **401** | Not authenticated. | - |
| **403** | Forbidden. | - |
| **404** | Request failed due to incorrect path. | - |
| **409** | Request was aborted due a transaction conflict. | - |
| **422** | Request timed out due to excessive request throttling. | - |
| **500** | Request failed due to internal server error. | - |


## write

> CompletableFuture<Object> write(storeId, body)
Expand Down
14 changes: 14 additions & 0 deletions docs/StreamResultOfStreamedListObjectsResponse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@


# StreamResultOfStreamedListObjectsResponse


## Properties

| Name | Type | Description | Notes |
|------------ | ------------- | ------------- | -------------|
|**result** | [**StreamedListObjectsResponse**](StreamedListObjectsResponse.md) | | [optional] |
|**error** | [**Status**](Status.md) | | [optional] |



14 changes: 14 additions & 0 deletions docs/StreamedListObjectsResponse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@


# StreamedListObjectsResponse

The response for a StreamedListObjects RPC.

## Properties

| Name | Type | Description | Notes |
|------------ | ------------- | ------------- | -------------|
|**_object** | **String** | | |



11 changes: 11 additions & 0 deletions examples/streamed-list-objects/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# OpenFGA Configuration (REQUIRED)
FGA_API_URL=http://localhost:8080
FGA_STORE_ID=store_id_here
FGA_MODEL_ID=model_id_here

# Authentication (optional - for authenticated OpenFGA instances)
FGA_CLIENT_ID=client_id_here
FGA_CLIENT_SECRET=client_secret_here
FGA_API_AUDIENCE=api_audience_here
FGA_API_TOKEN_ISSUER=api_issuer_here

15 changes: 15 additions & 0 deletions examples/streamed-list-objects/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: all build run run-openfga

all: build

openfga_version=latest

build:
./gradlew build

run:
./gradlew run

run-openfga:
docker pull docker.io/openfga/openfga:${openfga_version} && \
docker run -p 8080:8080 docker.io/openfga/openfga:${openfga_version} run
117 changes: 117 additions & 0 deletions examples/streamed-list-objects/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Streamed List Objects Example

This example demonstrates working with [OpenFGA's `/streamed-list-objects` endpoint](https://openfga.dev/api/service#/Relationship%20Queries/StreamedListObjects) using the Java SDK's `streamedListObjects()` method.

## What is Streamed ListObjects?

The StreamedListObjects API is similar to the regular ListObjects API, but with key differences:

1. **Streaming Response**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected
2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the server configuration (`OPENFGA_LIST_OBJECTS_DEADLINE`)
3. **Immediate Processing**: You can start processing results as they arrive, without waiting for the entire result set

## When to Use Streamed ListObjects

Use the Streamed ListObjects API when:

- You expect a large number of results that would take a long time to collect
- You want to start processing results immediately rather than waiting for the complete set
- You might not need all results (e.g., you want to stop after finding a certain number)
- You want to avoid timeout issues with very large result sets

## Prerequisites

- Java 11+
- OpenFGA running on `localhost:8080`

You can start OpenFGA with Docker by running the following command:

```bash
docker pull openfga/openfga && docker run -it --rm -p 8080:8080 openfga/openfga run
```

## Running the Example

No additional setup is required to run this example. Simply run the following command:

```bash
make run
```

### Environment Variables (Optional)

For authenticated OpenFGA instances, set the following environment variables:

```bash
export FGA_API_URL=http://localhost:8080 # Your OpenFGA server URL
export FGA_CLIENT_ID=your_client_id
export FGA_CLIENT_SECRET=your_client_secret
export FGA_API_TOKEN_ISSUER=your_token_issuer
export FGA_API_AUDIENCE=your_audience
```

## Code Examples

### Basic Usage

```java
// Create a request
var request = new ClientListObjectsRequest()
.type("document")
.relation("owner")
.user("user:anne");

// Call the streaming API and ensure proper resource cleanup
try (var objectStream = fgaClient.streamedListObjects(request).get()) {
// Collect all results
List<String> objects = objectStream
.map(StreamedListObjectsResponse::getObject)
.collect(Collectors.toList());
}
```

### Early Termination

```java
// Get only the first 10 results, ensuring the stream is closed properly
try (var objectStream = fgaClient.streamedListObjects(request).get()) {
List<String> firstTen = objectStream
.map(StreamedListObjectsResponse::getObject)
.limit(10)
.collect(Collectors.toList());
}
```

### Process as You Go

```java
// Process each object immediately as it arrives
try (var objectStream = fgaClient.streamedListObjects(request).get()) {
objectStream
.map(StreamedListObjectsResponse::getObject)
.forEach(obj -> {
// Do something with each object
System.out.println("Processing: " + obj);
});
}
```

### With Options

```java
// Use options to specify consistency preference
var options = new ClientListObjectsOptions()
.consistency(ConsistencyPreference.HIGHER_CONSISTENCY)
.authorizationModelId("01GXSXXXXXXXXXXXXXXXX");

var objectStream = fgaClient.streamedListObjects(request, options).get();
```

## Comparison with Regular ListObjects

| Feature | ListObjects | Streamed ListObjects |
|---------|-------------|---------------------|
| Result Collection | Waits for all results | Streams results as computed |
| Result Limit | Limited by server pagination | Limited only by execution timeout |
| Processing | Must wait for complete response | Can process immediately |
| Use Case | Small to medium result sets | Large result sets, immediate processing |
Loading
Loading