Skip to content

Detect custom deserialized NullValue instances in AbstractValueAdaptingCache #36727

@Nyamiou

Description

@Nyamiou

Hello,

I have an application based on Spring Boot 4.0.1 and that is using JCache with Redisson for the cache. I have a method with @CacheResult(cacheName = "foo") which can return null. When calling the method the first time with a param that make it return null there is no problem, the method returns null. However, when calling the method a second time, there is problem because I get the following error:

java.lang.ClassCastException: class org.springframework.cache.support.NullValue cannot be cast to class myClass (org.springframework.cache.support.NullValue and myClass are in unnamed module of loader 'app')

Note: I replaced the full class declaration with myClass here.

I gave a look to AbstractValueAdaptingCache which is the one responsible to convert null to NullValue.INSTANCE in the method toStoreValue(...) and is supposed to convert it back in the method fromStoreValue(...). But while debugging I found that in:

	protected @Nullable Object fromStoreValue(@Nullable Object storeValue) {
		if (this.allowNullValues && storeValue == NullValue.INSTANCE) {
			return null;
		}
		return storeValue;
	}

The storeValue I get is not NullValue.INSTANCE but another instance of NullValue (probably because Redisson de-serialized it into another instance), so the test storeValue == NullValue.INSTANCE fails.

I found out that in RedisCache this is worked around (with BINARY_NULL_VALUE) where any instance of NullValue is serialized as BINARY_NULL_VALUE and BINARY_NULL_VALUE is always de-serialized as NullValue.INSTANCE. But no such workaround seems to exists when using JCache.

Can't the test in fromStoreValue(...) be changed to storeValue instanceof NullValue so it wouldn't be affected by serialization/de-serialization? Or should I ask Redisson to implement a similar workaround?

Thank you

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: enhancementA general enhancement

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions