-
Notifications
You must be signed in to change notification settings - Fork 38.1k
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
SimpleKeyGenerator does not handle Collections the same way it handles Arrays #23464
Comments
@rlubbat seems sensible, thanks for reporting it. |
@snicoll, @rlubbat: Why do you want to have it in SimpleKeyGenerator? It was implemented to cover the basic simple cases. For other cases other generators should be used (and implemented, if not yet exist). This is a wrong approach to extend simple implementation with new cases. @snicoll: If decide to include it into Spring, please do it at least in a separate class. Don't flood simple implementation with new complex cases. Try to keep Spring code clean. |
@rlubbat I overlooked something. We can apply this to the @mentallurg thanks for sharing your opinion but the only reason why I considered it is for consistency. If we handle a single entry array, not handing a single collection is inconsistent. |
I read the original description backwards so please ignore my comment on @rlubbat the fact that Redis can't serialize the key if it's not a @jhoeller what are your thoughts to extend that check to |
This isn't about Redis specifically, it was only my example case. If you refer to the reported issue, I noted that the Redis cache configuration in my example was using the defaults. I was not doing any special configuration for key serialization so I don't think it is a problem with my configuration. If it is a problem with the Redis implementation, I can't seem to find where in the Spring code the problem would be. This is more about #16130, as you mentioned. It is natural to add Collection for the same reason array was added. I could see leaving Map out of it, but I think the same rationale for array and Collection could also apply to Map. Regarding the question of simplicity, I don't think extending the rationale for array to Collection makes this class any less simple. In fact, it makes it so that developers don't have to do any more complex work like creating a new class and configuring its use on each method that has a Collection as its sole argument. Spring is supposed to help developers by reducing the plumbing code and this request is right in line with that ideal. Thank you both for looking into the issue. |
I don't really understand how you claim this can't be related to Redis considering your original description states:
I'd like us to take a step back now. I've created a sample project which is my understanding of your setup. With that setup and both redis or simple cache, things are working as expected. Even though I think using a I don't understand why the |
Hi @snicoll. You're right, it is related to the conversion service. I've been on vacation this week and let slip the details from my mind :-) I will take a look at the sample project you created and see if I can get it to fail the way I'm experiencing the issue. I get back in a couple of days, so please don't interpret my lack of action as a lack of interest. Thanks! |
Hello. I was able to reproduce the problem, but I don’t have permissions to your sample project to commit the code. I’ve attached a ZIP of the changes.
- I created a new SomethingTwo object. The difference between it and the Something object is that SomethingTwo has two fields (name and hash).
- I created a bean with my proposed key generator enhancement.
- I created two new services, SomeServiceTwo and SomeServiceTwoWithKeyGenerator. They have the same findSomething() method as SomeService except they take a List of SomethingTwo objects.
- SomeServiceTwoWithKeyGenerator annotates the method with @Cacheable and specifies the use of the enhanced key generator. This works.
- SomeServiceTwo annotates the method with @Cacheable alone so that the only difference between it and SomeService is the List element type. This reproduces the error I am seeing.
I know a ZIP is annoying. If you give me permissions I will commit and push the changes and send you a PR. You’re help is greatly appreciated.
Thanks!
|
Sorry, forgot the ZIP attachment.
… On Sep 2, 2019, at 5:45 PM, Ramsey Lubbat ***@***.***> wrote:
Hello. I was able to reproduce the problem, but I don’t have permissions to your sample project to commit the code. I’ve attached a ZIP of the changes.
- I created a new SomethingTwo object. The difference between it and the Something object is that SomethingTwo has two fields (name and hash).
- I created a bean with my proposed key generator enhancement.
- I created two new services, SomeServiceTwo and SomeServiceTwoWithKeyGenerator. They have the same findSomething() method as SomeService except they take a List of SomethingTwo objects.
- SomeServiceTwoWithKeyGenerator annotates the method with @Cacheable and specifies the use of the enhanced key generator. This works.
- SomeServiceTwo annotates the method with @Cacheable alone so that the only difference between it and SomeService is the List element type. This reproduces the error I am seeing.
I know a ZIP is annoying. If you give me permissions I will commit and push the changes and send you a PR. You’re help is greatly appreciated.
Thanks!
|
Ok, never mind the ZIP attachment. I just forked the repo and created a PR. Please let me know how else I can help. Thanks!
|
Thanks for following up. This is, as I suspected, a Redis-specific problem. Redis has an optimization for IMO, your setup is a little brittle. If you want to use |
Created DATAREDIS-1032 to see what we can do about this. |
Affects: spring-context 5.1.6.RELEASE
Issue:
Using the
@Cacheable
annotation on a method with a single argument that is aCollection
orMap
while using aRedisCache
often fails to serialize the argument as the cache key when no keyGenerator is specified (defaults toSimpleKeyGenerator
).Example:
Using a
RedisCache
with configuration defaults except for using JSON serialization for values:RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
This results in a serialization error generating a cache key because there is no conversion service to convert
List<Something>
toString
.The reason
List<Something>
is being used to convert toString
is becauseSimpleKeyGenerator
has a condition when the params array is length 1. If the single param in the array (in our example, theList<Something>
) is not null and is not an array, thenSimpleKeyGenerator
returns that single param to use as the key. If there is more than 1 item in the params array, then aSimpleKey
is returned to use as the key.If
SimpleKeyGenerator
were changed to handleCollection
andMap
as well as array in the case where the params array is length 1, then the example method would work fine since the key would be aSimpleKey
instead of the actualList<Something>
.I propose changing the
SimpleKeyGenerator.generateKey(Object... params)
method to this:The text was updated successfully, but these errors were encountered: