Skip to content

Compare config tree values by content on refresh - #1741

Open
arimu1 wants to merge 2 commits into
spring-cloud:mainfrom
arimu1:fix/1687-configtree-refresh-equals
Open

arimu1 wants to merge 2 commits into
spring-cloud:mainfrom
arimu1:fix/1687-configtree-refresh-equals

Conversation

@arimu1

@arimu1 arimu1 commented Sep 12, 2026

Copy link
Copy Markdown

Summary

  • Fix change detection in ContextRefresher when the environment uses Spring Boot ConfigTreePropertySource.
  • ConfigTreePropertySource.Value (including PropertyFileContent) does not implement equals/hashCode, so every refresh incorrectly reported all config tree keys as changed.
  • Compare config tree property values by content via CharSequence/toString() instead of reference equality.

Fixes gh-1687

Test plan

  • ./mvnw -pl spring-cloud-context -am test
  • Added ContextRefresherConfigTreeTests covering unchanged config tree refresh (no spurious keys) and changed content (key reported).

ContextRefresher used reference equality for property changes, so
ConfigTreePropertySource values were always reported as changed.

Fixes spring-cloudgh-1687

Signed-off-by: arimu1 <19286898+arimu1@users.noreply.github.com>
if (Objects.equals(one, two)) {
return true;
}
if (one instanceof ConfigTreePropertySource.Value oneValue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we need to be a little more careful here since we are dealing with files on K8S and those files can be updated/removed between the time the refresh occurs and the comparison happens. If one or both of the files is gone when the comparison happens an IllegalStateException may occur so we should wrap this in a try/catch to deal with that case and return false. We should probably add a test to cover this if possible.

}
if (one instanceof ConfigTreePropertySource.Value oneValue
&& two instanceof ConfigTreePropertySource.Value twoValue) {
return oneValue.toString().contentEquals(twoValue);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we might want to compare bytes rather than use toString() since some of these values may be binary data (certs/keystores)

Use byte-level comparison for ConfigTreePropertySource values so binary
mounts (certs/keystores) are handled correctly. Treat missing or
unreadable files during comparison as a change instead of failing refresh.

Signed-off-by: arimu1 <19286898+arimu1@users.noreply.github.com>
@arimu1
arimu1 force-pushed the fix/1687-configtree-refresh-equals branch from 1daf0f4 to e57b4f7 Compare September 21, 2026 10:39
@arimu1

arimu1 commented Sep 21, 2026

Copy link
Copy Markdown
Author

Thanks for the review @ryanjbaxter — addressed both points in e57b4f7.

Missing K8s files during comparison
configTreeValuesEqual now reads both values inside a try/catch. If a mounted file disappears (or is otherwise unreadable) between refresh and comparison, we log at debug and return false so refresh treats it as a change instead of throwing IllegalStateException.

Added equalReturnsFalseWhenConfigTreeFileIsMissingDuringComparison: two ALWAYS_READ values are captured, the backing file is deleted, then equal is invoked — expects false without an exception.

Byte comparison (binary mounts)
Comparison uses Arrays.equals on bytes from Value.getInputStream() instead of toString().contentEquals(...).

Added refreshEnvironmentDoesNotReportUnchangedBinaryConfigTreeProperties with synthetic cert-like bytes to ensure unchanged binary config tree properties do not trigger a false refresh.

Tests run locally
mvn -pl spring-cloud-context -am test -Dtest=ContextRefresherConfigTreeTests (Temurin 21) — all pass.

CI note (run 34726626743)
That failure was in spring-cloud-loadbalancer (reactor.cache / reactor.retry missing); spring-cloud-context (including our module tests) succeeded. Looks upstream/main unrelated to this PR — happy to re-check after the next CI run on this push.

@ryanjbaxter ryanjbaxter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you submit this against the 5.0.x branch?

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Change detection on refreshEnvironment not working properly with configtree

3 participants