Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## [Unreleased](https://github.com/openfga/java-sdk/compare/v0.9.2...HEAD)
- feat: Add `streamedListObjects` API endpoint with consumer callback support (#252)

## v0.9.2

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



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

project_name=.
openfga_version=latest
language=java

build:
./gradlew -P language=$(language) build

run:
./gradlew -P language=$(language) run

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

This example demonstrates working with the `POST` `/stores/:id/streamed-list-objects` endpoint in OpenFGA using the Java SDK.

## Prerequisites

If you do not already have an OpenFGA instance running, you can start one using the following command:

```bash
make run-openfga
```

Or directly with docker:

```bash
docker run -d -p 8080:8080 openfga/openfga run
```

## Configure the example

You may need to configure the example for your environment by setting environment variables:

```bash
export FGA_API_URL=http://localhost:8080
```

Optional authentication configuration:
```bash
export FGA_CLIENT_ID=your-client-id
export FGA_CLIENT_SECRET=your-client-secret
export FGA_API_AUDIENCE=your-api-audience
export FGA_API_TOKEN_ISSUER=your-token-issuer
```

## Running the example

Build the project:

```bash
make build
```

Run the example:

```bash
make run
```

This will:
1. Create a temporary store
2. Create an authorization model
3. Write 100 mock tuples
4. Stream all objects using the `streamedListObjects` API
5. Display each object as it's received
6. Clean up the temporary store

## What to expect

The example will output each object as it's streamed from the server:

```
Created temporary store (01HXXX...)
Created temporary authorization model (01GXXX...)
Writing 100 mock tuples to store.
Listing objects using streaming endpoint:
document:0
document:1
document:2
...
document:99
API returned 100 objects.
Deleted temporary store (01HXXX...)
Finished.
```

## Note

The streaming API is particularly useful when dealing with large result sets, as it:
- Reduces memory usage by processing objects one at a time
- Provides faster time-to-first-result
- Allows for real-time processing of results
- Is only limited by execution timeout rather than result set size
Loading
Loading