Skip to content

Commit 956e135

Browse files
Add 3.x to 4.x migration guide.
Signed-off-by: viktoriya.kutsarova <viktoriya.kutsarova@redis.com>
1 parent 3e5d97a commit 956e135

1 file changed

Lines changed: 255 additions & 2 deletions

File tree

src/main/antora/modules/ROOT/pages/upgrading.adoc

Lines changed: 255 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,261 @@
33

44
This section contains details about migration steps, deprecations, and removals.
55

6+
[[upgrading.3-to-4]]
7+
== Upgrading from 3.x to 4.x
8+
9+
Spring Data Redis 4.0 is part of the Spring Data 2025.1 release train and requires Spring Framework 7.0.
10+
Upgrade to the latest Spring Data Redis 3.5.x release and replace APIs deprecated for removal before moving to 4.x.
11+
12+
Spring Data 2025.1 retains the Java 17 baseline and upgrades to Jakarta EE 11 and Kotlin 2.2.
13+
Review the https://github.com/spring-projects/spring-data-commons/wiki/Spring-Data-2025.1-Release-Notes[Spring Data 2025.1 release notes] and the https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-7.0-Release-Notes[Spring Framework 7.0 release notes] for baseline changes.
14+
See the xref:commons/upgrade.adoc[Spring Data Commons upgrade documentation] for changes shared by all Spring Data modules.
15+
16+
[[upgrading.3-to-4.nullability]]
17+
=== JSpecify Nullability
18+
19+
Spring Data Redis 4.0 uses https://jspecify.dev/[JSpecify] nullability annotations and null-marks its packages by default.
20+
Spring's `org.springframework.lang` nullability annotations are deprecated in Spring Framework 7.0 in favor of JSpecify.
21+
JSpecify can describe the nullability of generic type arguments and array elements.
22+
Java nullness tools and Kotlin can report additional errors or warnings.
23+
See the Spring Framework documentation on https://docs.spring.io/spring-framework/reference/core/null-safety.html[null-safety] for details.
24+
25+
Recompile custom implementations and Kotlin code against Spring Data Redis 4.0.
26+
Review any new nullability errors and warnings.
27+
In particular, `RedisSerializer.serialize(Object)` must now return a non-null byte array.
28+
Custom serializers that previously returned `null` must return a non-null representation, such as an empty byte array for a `null` value.
29+
`RedisSerializer.deserialize(byte[])` can still return `null`.
30+
31+
[[upgrading.3-to-4.jackson]]
32+
=== Jackson 3
33+
34+
Spring Data Redis 4.0 adds Jackson 3 serializers and a Jackson 3 hash mapper.
35+
Jackson 3 implementation types are in the `tools.jackson` package.
36+
The separate `jackson-annotations` artifact remains in `com.fasterxml.jackson.annotation`.
37+
See the https://github.com/FasterXML/jackson/blob/main/jackson3/MIGRATING_TO_JACKSON_3.md[Jackson 3 migration guide] for Jackson-wide changes.
38+
Jackson 3 serializers require `tools.jackson.core:jackson-databind` on the classpath.
39+
Jackson 2 and Jackson 3 can coexist on the classpath because their implementation packages differ.
40+
41+
The deprecated Jackson 2 types remain available during migration:
42+
43+
|===
44+
|Purpose |Jackson 3 API |Jackson 2 API (deprecated)
45+
46+
|Generic JSON serializer
47+
|`GenericJacksonJsonRedisSerializer`
48+
|`GenericJackson2JsonRedisSerializer`
49+
50+
|Typed JSON serializer
51+
|`JacksonJsonRedisSerializer`
52+
|`Jackson2JsonRedisSerializer`
53+
54+
|Hash mapper
55+
|`JacksonHashMapper`
56+
|`Jackson2HashMapper`
57+
58+
|Custom reader and writer contracts
59+
|`JacksonObjectReader` and `JacksonObjectWriter`
60+
|`Jackson2ObjectReader` and `Jackson2ObjectWriter`
61+
62+
|===
63+
64+
In 3.x, `JacksonObjectReader` and `JacksonObjectWriter` were Jackson 2 contracts.
65+
In 4.x, the same names are Jackson 3 contracts.
66+
Code that still uses Jackson 2 must use `Jackson2ObjectReader` and `Jackson2ObjectWriter`.
67+
This also applies to `GenericJackson2JsonRedisSerializer` and `Jackson2JsonRedisSerializer` constructor arguments and to the generic serializer builder's `reader(...)` and `writer(...)` methods.
68+
69+
`RedisSerializer.json()` now returns a `GenericJacksonJsonRedisSerializer` instead of a `GenericJackson2JsonRedisSerializer`.
70+
Jackson 2 and Jackson 3 can produce different JSON.
71+
Applications that must read data written by Spring Data Redis 3.x can keep the Jackson 2 serializer until the stored data is migrated:
72+
73+
[source,java]
74+
----
75+
RedisSerializer<Object> serializer = new GenericJackson2JsonRedisSerializer();
76+
----
77+
78+
`JacksonHashMapper` has a compatibility mode that reads hashes written by `Jackson2HashMapper` and writes hashes that `Jackson2HashMapper` can read:
79+
80+
[source,java]
81+
----
82+
JacksonHashMapper mapper = JacksonHashMapper.builder()
83+
.jackson2CompatibilityMode()
84+
.build();
85+
----
86+
87+
Select `flatten()` or `hierarchical()` on the builder to match the existing hash representation.
88+
The Jackson 2 serializers and hash mapper are deprecated for removal and should only be used during migration.
89+
90+
[[upgrading.3-to-4.cache]]
91+
=== Redis Cache
92+
93+
`RedisCacheWriter` now uses the Spring Cache API method names for eviction.
94+
`remove(String, byte[])` and `clean(String, byte[])` are deprecated in favor of `evict(String, byte[])` and `clear(String, byte[])`.
95+
The old methods remain as default methods, but `evict` and `clear` are new abstract methods.
96+
Custom `RedisCacheWriter` implementations must implement the new methods.
97+
98+
If the configured `RedisConnectionFactory` also implements `ReactiveRedisConnectionFactory`, the default `RedisCacheWriter` can perform writes asynchronously.
99+
`LettuceConnectionFactory` implements both interfaces.
100+
A write, eviction, or clear operation may finish after the calling method returns.
101+
Use `Cache.evictIfPresent(Object)` or `Cache.invalidate()` when an individual operation requires immediate visibility.
102+
To require immediate visibility for all cache writes, create the writer with `immediateWrites()`:
103+
104+
[source,java]
105+
----
106+
RedisCacheWriter cacheWriter = RedisCacheWriter.create(connectionFactory,
107+
configurer -> configurer.immediateWrites());
108+
----
109+
110+
With a reactive connection factory, immediate writes use blocking access.
111+
112+
.Cache API Changes
113+
|===
114+
|3.x API |4.x replacement
115+
116+
|`RedisCacheConfiguration.getTtl()`
117+
|`RedisCacheConfiguration.getTtlFunction()`. Evaluate the function with the cache key and value when a `Duration` is required.
118+
119+
|`RedisCacheManager(RedisCacheWriter, RedisCacheConfiguration, Map, boolean)`
120+
|`RedisCacheManager(RedisCacheWriter, RedisCacheConfiguration, boolean, Map)`
121+
122+
|`RedisCacheWriter.remove(String, byte[])`
123+
|`RedisCacheWriter.evict(String, byte[])`
124+
125+
|`RedisCacheWriter.clean(String, byte[])`
126+
|`RedisCacheWriter.clear(String, byte[])`
127+
128+
|===
129+
130+
[[upgrading.3-to-4.string-redis-template]]
131+
=== StringRedisTemplate Connection Callbacks
132+
133+
`StringRedisTemplate` no longer wraps the `RedisConnection` supplied to `RedisCallback` code in a `DefaultStringRedisConnection`.
134+
Remove casts from the supplied connection to `StringRedisConnection`.
135+
Use the binary `RedisConnection` API directly or wrap the connection explicitly:
136+
137+
[source,java]
138+
----
139+
String value = stringRedisTemplate.execute(connection -> {
140+
StringRedisConnection strings = new DefaultStringRedisConnection(connection);
141+
return strings.get("key");
142+
});
143+
----
144+
145+
The template still uses string serializers for keys and values.
146+
Only direct connection access inside callbacks changes.
147+
148+
[[upgrading.3-to-4.lettuce-observability]]
149+
=== Lettuce Observability
150+
151+
Spring Data Redis 4.0 removes the deprecated observability adapter.
152+
The removed public types are `MicrometerTracingAdapter`, `LettuceObservationContext`, and `RedisObservation` from `org.springframework.data.redis.connection.lettuce.observability`.
153+
154+
Replace `MicrometerTracingAdapter` with Lettuce's `io.lettuce.core.tracing.MicrometerTracing`:
155+
156+
[source,java]
157+
----
158+
MicrometerTracing tracing = new MicrometerTracing(observationRegistry, "Redis");
159+
160+
ClientResources clientResources = ClientResources.builder()
161+
.tracing(tracing)
162+
.build();
163+
----
164+
165+
Configure these `ClientResources` on `LettuceClientConfiguration`.
166+
See the Lettuce https://redis.github.io/lettuce/advanced-usage/observability/#micrometer-tracing[Micrometer Tracing documentation] for configuration details.
167+
168+
[[upgrading.3-to-4.drivers]]
169+
=== Driver and Dependency Upgrades
170+
171+
Spring Data Redis 4.0 updates its driver and networking baselines.
172+
Patch versions vary by maintenance release.
173+
Use the versions managed by the Spring Data BOM.
174+
175+
|===
176+
|Dependency |3.5 baseline |4.0 baseline |Migration notes
177+
178+
|Jedis
179+
|6.x
180+
|7.x
181+
|Review the https://redis.github.io/jedis/migration-guides/v6-to-v7/[Jedis 7 migration guide], especially if application code uses native Jedis APIs.
182+
183+
|Lettuce
184+
|6.6.x
185+
|6.8.x
186+
|Review the Lettuce https://redis.github.io/lettuce/new-features/#whats-new-in-lettuce-68[6.8 release notes] if application code uses native Lettuce APIs.
187+
188+
|Netty, through Lettuce
189+
|4.1.x
190+
|4.2.x
191+
|Align explicitly managed Netty modules and native transports with the managed version.
192+
193+
|===
194+
195+
[[upgrading.3-to-4.changed-api]]
196+
=== Other Removed and Changed APIs
197+
198+
Most removed APIs were deprecated in 3.x.
199+
Replace them on the latest 3.5.x release before upgrading to 4.x.
200+
201+
.Configuration, Operations, and Utilities
202+
|===
203+
|3.x API |4.x replacement or action
204+
205+
|`new RedisClusterConfiguration(PropertySource)`
206+
|`RedisClusterConfiguration.of(PropertySource)`
207+
208+
|`new RedisSentinelConfiguration(PropertySource)`
209+
|`RedisSentinelConfiguration.of(PropertySource)`
210+
211+
|`BoundSetOperations.diff(...)`
212+
|`BoundSetOperations.difference(...)`
213+
214+
|`BoundZSetOperations`, `ZSetOperations`, and `RedisZSet` overloads accepting `RedisZSetCommands.Range`
215+
|Use the overloads accepting `org.springframework.data.domain.Range<String>`.
216+
217+
|`RedisPersistentEntity.hasExplictTimeToLiveProperty()`
218+
|`RedisPersistentEntity.hasExplicitTimeToLiveProperty()`
219+
220+
|`Converters.toBoolean(Long)` returning `Boolean`
221+
|The method now returns primitive `boolean`.
222+
223+
|`Converters.toTimeMillis(...)` returning `Long`
224+
|The methods now return primitive `long`.
225+
226+
|`LettuceConverters.toBytesList(Collection<byte[]>)`
227+
|Use the collection directly or create a `List` from it.
228+
229+
|`ByteUtils.extractBytes(ByteBuffer)`
230+
|`ByteUtils.getBytes(ByteBuffer)`
231+
232+
|`RedisAssertions`
233+
|Use `org.springframework.util.Assert`, `java.util.Objects`, or an explicit check and exception.
234+
235+
|`DecodeUtils`
236+
|Use `java.util.Base64` directly.
237+
238+
|===
239+
240+
.Extension APIs
241+
|===
242+
|3.x API |4.x replacement or action
243+
244+
|`org.springframework.data.util.TypeInformation`
245+
|`org.springframework.data.core.TypeInformation`. This package change affects Redis mapping extension points including `IndexResolver`, `IndexDefinition.IndexingContext`, `BasicRedisPersistentEntity`, and `RedisMappingContext`.
246+
247+
|`new ScanIteration(long, Collection)` and `ScanIteration.getCursorId()`
248+
|Use `new ScanIteration(Cursor.CursorId, Collection)` and `ScanIteration.getId()`.
249+
250+
|`ScanCursor.doOpen(long)` and `ScanCursor.isFinished(long)`
251+
|Override the variants accepting `Cursor.CursorId`.
252+
253+
|`RedisPartTreeQuery` constructor accepting `QueryMethodEvaluationContextProvider`
254+
|Use the constructor accepting `ValueExpressionDelegate`.
255+
256+
|`JedisClusterTopologyProvider.shouldUseCachedValue()`
257+
|Override `shouldUseCachedValue(JedisClusterTopology)`.
258+
259+
|===
260+
6261
[[upgrading.2-to-3]]
7262
== Upgrading from 2.x to 3.x
8263

@@ -264,5 +519,3 @@ This effects methods on `LettuceConnectionFactory` and `LettuceConnection`.
264519

265520
`AuthenticatingRedisClient` has been removed without replacement.
266521
Please refer to the https://lettuce.io/core/release/reference/index.html#basic.redisuri[driver documentation] for `RedisURI` to set authentication data.
267-
268-

0 commit comments

Comments
 (0)