From 18c540b4df402170d759ee128fc684163ec3484d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 14 Nov 2025 13:56:29 +0100 Subject: [PATCH 1/9] Prepare next development iteration. See #3240 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1662c1df41..f125bee4bc 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 4.0.0 + 4.0.1-SNAPSHOT Spring Data Redis Spring Data module for Redis From c45193cece13f660df8e2e23046d16b4063f3967 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 14 Nov 2025 13:56:30 +0100 Subject: [PATCH 2/9] After release cleanups. See #3240 --- Jenkinsfile | 2 +- pom.xml | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2a26afa638..edc046f282 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { triggers { pollSCM 'H/10 * * * *' - upstream(upstreamProjects: "spring-data-keyvalue/main", threshold: hudson.model.Result.SUCCESS) + upstream(upstreamProjects: "spring-data-keyvalue/4.0.x", threshold: hudson.model.Result.SUCCESS) } options { diff --git a/pom.xml b/pom.xml index f125bee4bc..5efec13826 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,12 @@ org.springframework.data.build spring-data-parent - 4.0.0 + 4.0.1-SNAPSHOT - 4.0.0 - 4.0.0 + 4.0.1-SNAPSHOT + 4.0.1-SNAPSHOT 1.11.0 1.4.21 2.11.1 @@ -410,7 +410,19 @@ - - + + spring-snapshot + https://repo.spring.io/snapshot + + true + + + false + + + + spring-milestone + https://repo.spring.io/milestone + From 41cca8323ba2d9bde1d527a32e77321a3096f3ca Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Dec 2025 08:35:04 +0100 Subject: [PATCH 3/9] Update CI Properties. See #3263 --- ci/pipeline.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/pipeline.properties b/ci/pipeline.properties index bb47db3273..9ce2972a2e 100644 --- a/ci/pipeline.properties +++ b/ci/pipeline.properties @@ -18,8 +18,8 @@ docker.redis.8.version=8.2.2 docker.valkey.8.version=8.1.1 # Docker environment settings -docker.java.inside.basic=-v $HOME:/tmp/jenkins-home -docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home +docker.java.inside.basic=-v $HOME:/tmp/jenkins-home --ulimit nofile=32000:32000 +docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home --ulimit nofile=32000:32000 # Credentials docker.registry= From 751775d067dacc6d4548e767b2b410e73694c7a3 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 11 Dec 2025 16:16:41 +0100 Subject: [PATCH 4/9] Use Jackson default factory to create JavaType. Original pull request #3277 Closes #3271 Signed-off-by: Christoph Strobl (cherry picked from commit 3eb2c69b0d6e2400d946508ec38df3fdea7eeb45) --- .../JacksonJsonRedisSerializer.java | 2 +- .../JacksonJsonRedisSerializerTests.java | 129 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java diff --git a/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java index bb4bd2e5a8..2e04fc004e 100644 --- a/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java @@ -164,7 +164,7 @@ public T deserialize(byte @Nullable [] bytes) throws SerializationException { * @return the java type */ protected JavaType getJavaType(Class clazz) { - return TypeFactory.unsafeSimpleType(clazz); + return TypeFactory.createDefaultInstance().constructType(clazz); } } diff --git a/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java new file mode 100644 index 0000000000..d92f4e9665 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java @@ -0,0 +1,129 @@ +/* + * Copyright 2014-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.serializer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.type.TypeFactory; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.springframework.data.redis.Person; +import org.springframework.data.redis.PersonObjectFactory; + +/** + * Unit tests for {@link JacksonJsonRedisSerializer}. + * + * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch + */ +class JacksonJsonRedisSerializerTests { + + private JacksonJsonRedisSerializer serializer = new JacksonJsonRedisSerializer<>(Person.class); + + @Test // GH-3271 + void canDeserializeSerialized() { + + JacksonJsonRedisSerializer redisSerializer = new JacksonJsonRedisSerializer<>(SessionToken.class); + + SessionToken source = new SessionToken(UUID.randomUUID().toString()); + + byte[] serialized = redisSerializer.serialize(source); + assertThat(redisSerializer.deserialize(serialized)).isEqualTo(source); + } + + @Test // DATAREDIS-241 + void testJacksonJsonSerializerShouldReturnEmptyByteArrayWhenSerializingNull() { + assertThat(serializer.serialize(null)).isEqualTo(new byte[0]); + } + + @Test // DTATREDIS-241 + void testJacksonJsonSerializerShouldReturnNullWhenDerserializingEmptyByteArray() { + assertThat(serializer.deserialize(new byte[0])).isNull(); + } + + @Test // DTATREDIS-241 + void testJacksonJsonSerializerShouldThrowExceptionWhenDeserializingInvalidByteArray() { + + Person person = new PersonObjectFactory().instance(); + byte[] serializedValue = serializer.serialize(person); + Arrays.sort(serializedValue); // corrupt serialization result + + assertThatExceptionOfType(SerializationException.class).isThrownBy(() -> serializer.deserialize(serializedValue)); + } + + @Test // GH-2322 + void shouldConsiderWriter() { + + serializer = new JacksonJsonRedisSerializer<>(new JsonMapper(), + TypeFactory.createDefaultInstance().constructType(Person.class), JacksonObjectReader.create(), + (mapper, source) -> "foo".getBytes()); + Person person = new PersonObjectFactory().instance(); + assertThat(serializer.serialize(person)).isEqualTo("foo".getBytes()); + } + + static class SessionToken implements Serializable { + + private String userUuid; + + private SessionToken() { + // why jackson? + } + + public SessionToken(String userUuid) { + this.userUuid = userUuid; + } + + public String getUserUuid() { + return userUuid; + } + + public void setUserUuid(String userUuid) { + this.userUuid = userUuid; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionToken token = (SessionToken) o; + return Objects.equals(userUuid, token.userUuid); + } + + @Override + public int hashCode() { + return Objects.hash(userUuid); + } + + @Override + public String toString() { + return "SessionToken{" + "userUuid='" + userUuid + '\'' + '}'; + } + + } + +} From 42e3d5dfa5adb5ef246fd1ae8390b1407f87e41d Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Thu, 11 Dec 2025 21:25:04 -0600 Subject: [PATCH 5/9] Polishing. Update newly added tests to reproduce the associated issue by serializing a non-standard public property style POJO. Original pull request #3277 See #3271 Signed-off-by: Chris Bono (cherry picked from commit 8156530574555aa130dbe16dce8aa8521d135cd2) --- .../JacksonJsonRedisSerializerTests.java | 76 ++++++++----------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java index d92f4e9665..04e3b762f3 100644 --- a/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java +++ b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerTests.java @@ -23,7 +23,6 @@ import java.io.Serializable; import java.util.Arrays; -import java.util.Objects; import java.util.UUID; import org.junit.jupiter.api.Test; @@ -36,22 +35,12 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Chris Bono */ class JacksonJsonRedisSerializerTests { private JacksonJsonRedisSerializer serializer = new JacksonJsonRedisSerializer<>(Person.class); - @Test // GH-3271 - void canDeserializeSerialized() { - - JacksonJsonRedisSerializer redisSerializer = new JacksonJsonRedisSerializer<>(SessionToken.class); - - SessionToken source = new SessionToken(UUID.randomUUID().toString()); - - byte[] serialized = redisSerializer.serialize(source); - assertThat(redisSerializer.deserialize(serialized)).isEqualTo(source); - } - @Test // DATAREDIS-241 void testJacksonJsonSerializerShouldReturnEmptyByteArrayWhenSerializingNull() { assertThat(serializer.serialize(null)).isEqualTo(new byte[0]); @@ -82,48 +71,47 @@ void shouldConsiderWriter() { assertThat(serializer.serialize(person)).isEqualTo("foo".getBytes()); } - static class SessionToken implements Serializable { + @Test // GH-3271 + void canDeserializeSerializedStandardPojo() { - private String userUuid; + // Where "Standard" is POJO w/ private fields w/ getters/setters - private SessionToken() { - // why jackson? - } + Person person = new PersonObjectFactory().instance(); + byte[] serializedPerson = JsonMapper.shared().writeValueAsString(person).getBytes(); - public SessionToken(String userUuid) { - this.userUuid = userUuid; - } + Person deserializedPerson = serializer.deserialize(serializedPerson); - public String getUserUuid() { - return userUuid; - } + // The bug was that the fields would be null upon deserialization + assertThat(deserializedPerson).isEqualTo(person); + } - public void setUserUuid(String userUuid) { - this.userUuid = userUuid; - } + @Test // GH-3271 + void canDeserializeSerializedPropertyPojo() { - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SessionToken token = (SessionToken) o; - return Objects.equals(userUuid, token.userUuid); - } + // Where "Property" is POJO w/ public fields and no getters/setters - @Override - public int hashCode() { - return Objects.hash(userUuid); - } + JacksonJsonRedisSerializer redisSerializer = new JacksonJsonRedisSerializer<>(JsonMapper.shared(), SessionTokenPropertyPojo.class); + + SessionTokenPropertyPojo sessionToken = new SessionTokenPropertyPojo(UUID.randomUUID().toString()); + byte[] serializedSessionToken = redisSerializer.serialize(sessionToken);//JsonMapper.shared().writeValueAsString(sessionToken).getBytes(); + + SessionTokenPropertyPojo deserializedSessionToken = redisSerializer.deserialize(serializedSessionToken); - @Override - public String toString() { - return "SessionToken{" + "userUuid='" + userUuid + '\'' + '}'; + // The bug was that the fields would be null upon deserialization + assertThat(deserializedSessionToken.userUuid).isEqualTo(sessionToken.userUuid); + } + + static class SessionTokenPropertyPojo implements Serializable { + + public String userUuid; + + private SessionTokenPropertyPojo() { } + SessionTokenPropertyPojo(String userUuid) { + this(); + this.userUuid = userUuid; + } } } From cd0e5e60d59dbc1a8706d13a4d7d7dca0c67588d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 12 Dec 2025 12:20:16 +0100 Subject: [PATCH 6/9] Prepare 4.0.1 (2025.1.1). See #3263 --- pom.xml | 22 +++++----------------- src/main/resources/notice.txt | 3 ++- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 5efec13826..50841025fc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,12 @@ org.springframework.data.build spring-data-parent - 4.0.1-SNAPSHOT + 4.0.1 - 4.0.1-SNAPSHOT - 4.0.1-SNAPSHOT + 4.0.1 + 4.0.1 1.11.0 1.4.21 2.11.1 @@ -410,19 +410,7 @@ - - spring-snapshot - https://repo.spring.io/snapshot - - true - - - false - - - - spring-milestone - https://repo.spring.io/milestone - + + diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 9e7c59b0f9..3a15f3355d 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data Redis 4.0 GA (2025.1.0) +Spring Data Redis 4.0.1 (2025.1.1) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -16,3 +16,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 4e1f3be64c3f010636e1803caffb4e4e102afb16 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 12 Dec 2025 12:20:34 +0100 Subject: [PATCH 7/9] Release version 4.0.1 (2025.1.1). See #3263 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 50841025fc..57e2224f85 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 4.0.1-SNAPSHOT + 4.0.1 Spring Data Redis Spring Data module for Redis From ef0ef0e017606b62b44b3cf81596a80c480eb1c7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 12 Dec 2025 12:22:55 +0100 Subject: [PATCH 8/9] Prepare next development iteration. See #3263 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 57e2224f85..6d52d919f4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 4.0.1 + 4.0.2-SNAPSHOT Spring Data Redis Spring Data module for Redis From ee151791cb31f924373c9af2f2934b89fb8fd07a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 12 Dec 2025 12:22:56 +0100 Subject: [PATCH 9/9] After release cleanups. See #3263 --- pom.xml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 6d52d919f4..30c03f822b 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,12 @@ org.springframework.data.build spring-data-parent - 4.0.1 + 4.0.2-SNAPSHOT - 4.0.1 - 4.0.1 + 4.0.2-SNAPSHOT + 4.0.2-SNAPSHOT 1.11.0 1.4.21 2.11.1 @@ -410,7 +410,19 @@ - - + + spring-snapshot + https://repo.spring.io/snapshot + + true + + + false + + + + spring-milestone + https://repo.spring.io/milestone +