Skip to content

[Java SDK] Add ValueState.read(T defaultValue) overload#37824

Open
Ri1a wants to merge 1 commit intoapache:masterfrom
Ri1a:valuestate-read-default
Open

[Java SDK] Add ValueState.read(T defaultValue) overload#37824
Ri1a wants to merge 1 commit intoapache:masterfrom
Ri1a:valuestate-read-default

Conversation

@Ri1a
Copy link

@Ri1a Ri1a commented Mar 11, 2026

Fixes #18174

This change adds a convenience overload ValueState.read(T defaultValue) to simplify handling of uninitialized state. Currently, ValueState.read() returns null if the value has never been written. As a result, users frequently need to write boilerplate code such as:

Integer count = state.read();
if (count == null) {
  count = 0;
}

or:

Integer count = MoreObjects.firstNonNull(state.read(), 0);

This PR introduces a default method:

default T read(T defaultValue)

which returns the stored value if present, or defaultValue if the state has not been written yet.

Tests

Added ValueStateTest to verify:

  • read(defaultValue) returns the default when the state is empty
  • read(defaultValue) returns the stored value when present
  • readLater() continues to return the same state instance

Compatibility

This change is fully backward compatible:

  • existing implementations of ValueState do not need modification
  • the new method is implemented as a Java 8 default interface method

@github-actions github-actions bot added the java label Mar 11, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the ValueState interface in the Java SDK by introducing a new read method overload. This addition simplifies the handling of uninitialized state by allowing developers to specify a default value directly, eliminating the need for manual null checks and making state management more concise and less error-prone.

Highlights

  • New ValueState Overload: Introduced a new default method read(T defaultValue) to the ValueState interface, providing a convenient way to retrieve a default value when the state is uninitialized, thereby reducing boilerplate code.
  • Test Coverage: Added ValueStateTest to thoroughly verify the behavior of the new read(defaultValue) method, ensuring it correctly returns default values for empty states and stored values when present, and confirming readLater() returns the same state instance.
  • Backward Compatibility: Ensured full backward compatibility by implementing the new read(T defaultValue) method as a Java 8 default interface method, meaning existing implementations of ValueState do not require modification.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • sdks/java/core/src/main/java/org/apache/beam/sdk/state/ValueState.java
    • Added a new default method read(T defaultValue) to the ValueState interface.
  • sdks/java/core/src/test/java/org/apache/beam/sdk/state/ValueStateTest.java
    • Added ValueStateTest to provide comprehensive test coverage for the ValueState interface.
    • Included tests to verify read(defaultValue) returns the specified default when the state is empty.
    • Included tests to verify read(defaultValue) returns the stored value when the state is present.
    • Included a test to confirm that readLater() returns the same state instance.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Ri1a
Copy link
Author

Ri1a commented Mar 11, 2026

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a convenient read(T defaultValue) overload to ValueState, which simplifies handling of uninitialized state. The implementation is sound and the change is backward compatible. My review includes a suggestion to clarify the Javadoc for the new method to more accurately describe its behavior, particularly regarding null values. I also recommend adding a couple of test cases to cover edge scenarios like clear() and writing null to the state, which will make the test suite more robust.

Comment on lines +40 to +43
/**
* Returns the current value of the state, or {@code defaultValue} if the value has never been
* written.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The Javadoc states that defaultValue is returned 'if the value has never been written'. However, the implementation returns defaultValue whenever read() returns null. This can occur not only when the state is uninitialized, but also when null has been explicitly written or the state has been cleared. To avoid confusion, the Javadoc should be updated to accurately reflect this behavior.

Suggested change
/**
* Returns the current value of the state, or {@code defaultValue} if the value has never been
* written.
*/
/**
* Returns the current value of the state, or {@code defaultValue} if the current value is {@code
* null}. This can happen if the value has never been written or if {@code null} was written.
*/


/** Tests for {@link ValueState}. */
@RunWith(JUnit4.class)
public class ValueStateTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The tests for the new functionality are a good start. To make them more comprehensive, consider adding test cases for edge scenarios. Specifically, testing the behavior after state.clear() is called, and after null is explicitly written to the state, would strengthen the test suite and clarify the contract of the new method.

For example:

@Test
public void testReadReturnsDefaultValueAfterClear() {
  TestValueState<Integer> state = new TestValueState<>();
  state.write(10);
  state.clear();
  assertEquals(Integer.valueOf(5), state.read(5));
}

@Test
public void testReadReturnsDefaultValueWhenNullIsWritten() {
  TestValueState<Integer> state = new TestValueState<>();
  state.write(null);
  assertEquals(Integer.valueOf(5), state.read(5));
}

@github-actions
Copy link
Contributor

Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment assign set of reviewers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ValueState could use an initial/default value

1 participant