Skip to content

feat(java): add multi-flag resolve with deferred apply#273

Closed
nicklasl wants to merge 6 commits intomainfrom
nicklasl/java-multi-flag-resolve
Closed

feat(java): add multi-flag resolve with deferred apply#273
nicklasl wants to merge 6 commits intomainfrom
nicklasl/java-multi-flag-resolve

Conversation

@nicklasl
Copy link
Member

Summary

  • Add resolve() method to OpenFeatureLocalResolveProvider for resolving multiple flags at once with apply=false
  • Add applyFlag() method for deferred flag application using the resolve token
  • Add applyFlags WASM export to WasmResolveApi and propagate through resolver chain

Usage

// Resolve with apply=false (default)
ResolveFlagsResponse response = provider.resolve(ctx, List.of("feature-a", "feature-b"));

// Later, when actually using the flag:
ResolvedFlag flag = response.getResolvedFlags(0);
if (flag.getShouldApply()) {
    provider.applyFlag(response.getResolveToken(), "feature-a");
}

Test plan

  • Added integration tests for multi-flag resolve with apply=false
  • Added integration tests for multi-flag resolve with apply=true
  • Added integration tests for deferred apply workflow
  • All existing tests pass

🤖 Generated with Claude Code

nicklasl and others added 2 commits February 11, 2026 15:38
Add resolve() and applyFlag() methods to OpenFeatureLocalResolveProvider
for resolving multiple flags at once with apply=false, returning
ResolveFlagsResponse with resolveToken for deferred application.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ResolveFlagsRequest.newBuilder()
.addAllFlags(requestFlagNames)
.setApply(apply)
.setClientSecret(clientSecret)
Copy link
Member Author

@nicklasl nicklasl Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure we should set this but it follows the same design as the JS provider equivalens.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more reasoning about this:
This provider has been initialized with a clientSecret. That's client is the only state it will be able to fetch currently. This mean that we cannot risk taking a client secret from the request.

.toCompletableFuture()
.get();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException("Failed to resolve flags", e);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to throw here? Probably not?

instance.applyFlags(request);
} catch (IsClosedException e) {
if (closedRetries >= MAX_CLOSED_RETRIES) {
throw new RuntimeException(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here... really throw?

@nicklasl nicklasl closed this Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant