Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LinkedCaseInsensitiveMap#putIfAbsent does not honor the case where the key is associated with a null value #26868

Closed
metaruslan opened this issue Apr 27, 2021 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@metaruslan
Copy link

metaruslan commented Apr 27, 2021

Seems to be a bug that LinkedCaseInsensitiveMap#putIfAbsent does not honor the case where the key is associated with a null value.

Here is the javadoc inherited from java.util.Map.

If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.

Here is the code showing the difference with the normal map:

        Map<String, String> normalMap = new HashMap<>();
        Map<String, String> caseInsensitiveMap = new LinkedCaseInsensitiveMap<>();
        normalMap.put("key", null);
        System.out.println("normal map:" + normalMap);
        normalMap.putIfAbsent("key", "value");
        System.out.println("normal map:" + normalMap);

        caseInsensitiveMap.put("key", null);
        System.out.println("case insensitive map" + caseInsensitiveMap);
        caseInsensitiveMap.putIfAbsent("key", "value");
        System.out.println("case insensitive map" + caseInsensitiveMap);

Output:

normal map:{key=null}
normal map:{key=value}
case insensitive map{key=null}
case insensitive map{key=null}

According to the javadoc it should return null and make the change, but the code only returns null. The line: return this.targetMap.get(oldKey).

The implementation:

        @Override
	@Nullable
	public V putIfAbsent(String key, @Nullable V value) {
		String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key);
		if (oldKey != null) {
			return this.targetMap.get(oldKey);
		}
		return this.targetMap.putIfAbsent(key, value);
	}

Spring version: 5.3.5

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 27, 2021
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Apr 27, 2021
@poutsma poutsma self-assigned this Apr 30, 2021
@poutsma poutsma added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 30, 2021
@jhoeller jhoeller added this to the 5.3.7 milestone Apr 30, 2021
@jhoeller
Copy link
Contributor

I suppose the same check is also necessary in the computeIfAbsent implementation?

@poutsma
Copy link
Contributor

poutsma commented Apr 30, 2021

Looks like that method has the same contract, so I'll fix that one as well.

@poutsma poutsma reopened this Apr 30, 2021
Zoran0104 pushed a commit to Zoran0104/spring-framework that referenced this issue Aug 20, 2021
This commit makes sure that LinkedCaseInsensitiveMap::putIfAbsent honors
the contract of the method, and also replaces the old entry if that
mapped to null.

Closes spring-projectsgh-26868
Zoran0104 pushed a commit to Zoran0104/spring-framework that referenced this issue Aug 20, 2021
This commit makes sure that LinkedCaseInsensitiveMap::computeIfAbsent
honors the contract of the method, and also replaces the old entry if
that mapped to null.

Closes spring-projectsgh-26868
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
This commit makes sure that LinkedCaseInsensitiveMap::putIfAbsent honors
the contract of the method, and also replaces the old entry if that
mapped to null.

Closes spring-projectsgh-26868
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
This commit makes sure that LinkedCaseInsensitiveMap::computeIfAbsent
honors the contract of the method, and also replaces the old entry if
that mapped to null.

Closes spring-projectsgh-26868
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants