Skip to content

DATAREDIS-1034 - Fix dataraces in RedisTemplate. #479

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

Closed
wants to merge 1 commit into from
Closed

DATAREDIS-1034 - Fix dataraces in RedisTemplate. #479

wants to merge 1 commit into from

Conversation

cac03
Copy link
Contributor

@cac03 cac03 commented Sep 12, 2019

Previously it was possible in multi-threaded environment to:

  • get a null from opsFor* methods in RedisTemplate.
  • fail with a NullPointerException when working with a not-null reference returned from RedisTemplate.opsFor* methods.

Introduced changes initialize the fields eagerly to avoid a datarace when accessing them and add a final modifier to the AbstractOperations#template field.

Please note that these changes still require a client to publish a reference to RedisTemplate safely (getting a reference from an ApplicationContext is fine).
Also note that escaping a reference to this in RedisTemplate initializer should also be ok, because putting a bean into ApplicationContext happens-before its subsequent retrieval.

Original pull request: #???.

  • You have read the Spring Data contribution guidelines.
  • There is a ticket in the bug tracker for the project in our JIRA.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

Previously it was possible in multi-threaded environment to:
* get a `null` from `opsFor*` methods in RedisTemplate.
* fail with a `NullPointerException` when working with a not-`null` reference returned from `RedisTemplate.opsFor*` methods.

Introduced changes initialize the fields eagerly to avoid a datarace when accessing them and add a `final` modifier to the `AbstractOperations#template` field.

Please note that these changes still require a client to publish a reference to RedisTemplate safely (getting a reference from an `ApplicationContext` is fine).
Also note that escaping a reference to `this` in `RedisTemplate` initializer should also be ok, because putting a bean into `ApplicationContext` happens-before its subsequent retrieval.

Original pull request: #479.
mp911de pushed a commit that referenced this pull request Sep 25, 2019
Previously it was possible in multi-threaded environment to:
* get a `null` from `opsFor*` methods in RedisTemplate.
* fail with a `NullPointerException` when working with a not-`null` reference returned from `RedisTemplate.opsFor*` methods.

Introduced changes initialize the fields eagerly to avoid visibility issues when accessing them and add a `final` modifier to the `AbstractOperations#template` field.

Original pull request: #479.
mp911de added a commit that referenced this pull request Sep 25, 2019
Pre-allocate operations objects for immutable serializationContext in ReactiveRedisTemplate.

Original pull request: #479.
mp911de pushed a commit that referenced this pull request Sep 25, 2019
Previously it was possible in multi-threaded environment to:
* get a `null` from `opsFor*` methods in RedisTemplate.
* fail with a `NullPointerException` when working with a not-`null` reference returned from `RedisTemplate.opsFor*` methods.

Introduced changes initialize the fields eagerly to avoid visibility issues when accessing them and add a `final` modifier to the `AbstractOperations#template` field.

Original pull request: #479.
mp911de added a commit that referenced this pull request Sep 25, 2019
Pre-allocate operations objects for immutable serializationContext in ReactiveRedisTemplate.

Original pull request: #479.
@mp911de
Copy link
Member

mp911de commented Sep 25, 2019

Thanks a lot. That's merged, backported, and polished now.

@mp911de mp911de closed this Sep 25, 2019
@cac03
Copy link
Contributor Author

cac03 commented Sep 25, 2019

Thanks for merging, Mark

@vpavic
Copy link

vpavic commented Sep 26, 2019

These changes appear to have broken Spring Session build after picking them up via the latest Spring Data Redis snapshot:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.session.data.redis.RedisIndexedSessionRepository]: Factory method 'sessionRepository' threw exception; nested exception is java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:640)
	... 102 more
Caused by: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
	at org.springframework.data.convert.CustomConversions.<clinit>(CustomConversions.java:54)
	at org.springframework.data.redis.hash.ObjectHashMapper.<init>(ObjectHashMapper.java:83)
	at org.springframework.data.redis.core.RedisTemplate.<init>(RedisTemplate.java:109)
	at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration.createRedisTemplate(RedisHttpSessionConfiguration.java:277)
	at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration.sessionRepository(RedisHttpSessionConfiguration.java:117)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 103 more
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 113 more

Since ObjectHashMapper is now eagerly instantiated, which in turn instantiates RedisCustomConversions, things are now blowing up as RedisCustomConversions's base class, CustomConversions, is annotated with Lombok's @Slf4j.

@christophstrobl
Copy link
Member

@vpavic is there a specific reason why org.slf4j is excluded in spring-session-data-redis.gradle

@mp911de
Copy link
Member

mp911de commented Sep 26, 2019

SLF4J is required for Spring Data (as a general rule of thumb). We migrated some projects away from SLF4J towards JCL, maybe we should follow that path consistently.

@vpavic
Copy link

vpavic commented Sep 26, 2019

Thanks for the feedback @christophstrobl and @mp911de.

Ever since spring-jcl was introduced in Framework 5.0, Spring Session has ensured it's the only logging dependency we require. I would assume this should be a common strategy across Spring projects.

@mp911de
Copy link
Member

mp911de commented Sep 26, 2019

It makes sense to revisit our logging dependencies with the next release train. I'm not sure what the rationale was to use SLF4J.

@vpavic
Copy link

vpavic commented Sep 26, 2019

With next release train you're not referring to Moore I assume? 🙂

Because we'll need something for Moore-RELEASE to resolve this situation.

@mp911de
Copy link
Member

mp911de commented Sep 26, 2019

Sorry, I wasn't precise enough. I meant Neumann with the next release train as we need to go over all of our projects if we wanted to remove SLF4J and switch to JCL.

For now, please include SLF4J. It was a lucky coincidence that excluding SLF4J worked until now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants