Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 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
Comment thread
SoulPancake marked this conversation as resolved.
115 changes: 115 additions & 0 deletions examples/streamed-list-objects/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 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
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
var objectStream = fgaClient.streamedListObjects(request).get();
List<String> firstTen = objectStream
.map(StreamedListObjectsResponse::getObject)
.limit(10)
.collect(Collectors.toList());
Comment thread
SoulPancake marked this conversation as resolved.
Outdated
```

### Process as You Go

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

### 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