question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The org.springframework.boot.context.properties.bind.MapBinder#merge works in wrong result by deleting the cofniguration

See original GitHub issue

the code like this:

@Data
@ToString
@ConfigurationProperties(value = MonitorPluginConfiguration.PREFIX)
public class MonitorPluginConfiguration {
    public static final String PREFIX = "monitor";
    private Map<String, String> plugins;
}

the yaml configuration in nacos:

monitor:
  plugins:
    p1: 1
    p2: 2
    p3: 3
    p4: 4

if i delete the key-value p4: 4 in the configuration from nacos ,the value for field MonitorPluginConfiguration#plugins will not be deleted.

the changed configuration in nacos after delete the the key-value p4: 4

monitor:
  plugins:
    p1: 1
    p2: 2
    p3: 3

I trace the code , i find the method in org.springframework.boot.context.properties.bind.MapBinder#merge

        @Override
	protected Map<Object, Object> merge(Supplier<Map<Object, Object>> existing, Map<Object, Object> additional) {
		Map<Object, Object> existingMap = getExistingIfPossible(existing);
		if (existingMap == null) {
			return additional;
		}
		try {
			existingMap.putAll(additional);
			return copyIfPossible(existingMap);
		}
		catch (UnsupportedOperationException ex) {
			Map<Object, Object> result = createNewMap(additional.getClass(), existingMap);
			result.putAll(additional);
			return result;
		}
	}

the parmater additional value is {p1=1, p2=2, p3=3} image

and the variable existingMap value is {p1=1, p2=2, p3=3, p4=4} image

for the code existingMap.putAll(additional), it will save the original value {p1=1, p2=2, p3=3, p4=4}. so the result is bad. I think that it is good to execute existingMap.clear() before executing the code existingMap.putAll(additional) The code like this:

        @Override
	protected Map<Object, Object> merge(Supplier<Map<Object, Object>> existing, Map<Object, Object> additional) {
		Map<Object, Object> existingMap = getExistingIfPossible(existing);
		if (existingMap == null) {
			return additional;
		}
		try {
			existingMap.clear(); // add this line
			existingMap.putAll(additional);
			return copyIfPossible(existingMap);
		}
		catch (UnsupportedOperationException ex) {
			Map<Object, Object> result = createNewMap(additional.getClass(), existingMap);
			result.putAll(additional);
			return result;
		}
	}

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
wilkinsonacommented, Oct 26, 2022

Thanks. From a Spring Boot perspective, this is working as designed and documented.

I believe the bug is in Spring Cloud. When they are rebinding configuration properties, an existing instance of MonitorPluginConfiguration should not be re-used. Instead, a fresh instance should be created and then have properties bound to it. This has been raised before but the Spring Cloud team declined it as a duplicate of https://github.com/spring-cloud/spring-cloud-commons/issues/818. You may want to raise the problem again as, IMO, it should be documented as a limitation at the least.

0reactions
wilkinsonacommented, Oct 26, 2022

@winjaychan Have you read the reference documentation that I linked to earlier? It describes the difference in behaviour for binding lists and maps. Lists are only ever bound from a single source (so they are cleared). Maps can be bound from multiple sources (so they are not cleared).

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Failed to bind properties under 'xxx.yyy' to com.example.demo ...
This works well under Spring Boot 2.0.0 I have included a small sample application that reproduces the ... org.springframework.boot.context.properties.bind.
Read more >
spring boot configuration properties not working - Stack Overflow
Based on OP's edit, here's a fully working solution. ... Using either of those. the properties bean should be set by the test....
Read more >
Core Features - Spring
Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments.
Read more >
Spring Boot, Maven and Eclipse Errors and TroubleShooting ...
Hal Browser and Spring Boot Actuator are not working! Configure 2.3.1. ... ClassCastException: org.springframework.boot.context.event.
Read more >
HD93626: SWI - INCORRECT QUESTION WHEN DELETING ...
APAR status. Closed as unreproducible in next release. Error description. When deleting a configuration in SolidWorks, SmarTeam will ask a question, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found