diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java index f31cdfd28..579281d8c 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java @@ -93,6 +93,7 @@ public class LettuceReactiveKeyCommands implements ReactiveKeyCommands { */ @Override public Flux> keys(Publisher patterns) { + return connection.execute(cmd -> Flux.from(patterns).flatMap(pattern -> { Assert.notNull(pattern, "Pattern must not be null!"); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveGeoOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveGeoOperations.java index cfb1ef52f..d7d996866 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveGeoOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveGeoOperations.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.data.redis.serializer.RedisSerializationContext; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -35,25 +36,31 @@ import org.springframework.data.geo.Point; import org.springframework.data.redis.connection.ReactiveGeoCommands; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveGeoOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Create new instance of {@link DefaultReactiveGeoOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveGeoOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -92,7 +99,7 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations public Mono geoAdd(K key, Map memberCoordinateMap) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(memberCoordinateMap, "Map must not be null!"); + Assert.notNull(memberCoordinateMap, "MemberCoordinateMap must not be null!"); return createMono(connection -> { @@ -129,16 +136,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations public Flux geoAdd(K key, Publisher>> locations) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(locations, "GeoLocations must not be null!"); + Assert.notNull(locations, "Locations must not be null!"); - return createFlux(connection -> { - - return Flux.from(locations) - .map(locationList -> locationList.stream() - .map(location -> new GeoLocation<>(rawValue(location.getName()), location.getPoint())) - .collect(Collectors.toList())) - .flatMap(list -> connection.geoAdd(rawKey(key), list)); - }); + return createFlux(connection -> Flux.from(locations) + .map(locationList -> locationList.stream() + .map(location -> new GeoLocation<>(rawValue(location.getName()), location.getPoint())) + .collect(Collectors.toList())) + .flatMap(list -> connection.geoAdd(rawKey(key), list))); } /* (non-Javadoc) @@ -188,17 +192,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations public final Mono> geoHash(K key, V... members) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(members, "Member must not be null!"); - Assert.notEmpty(members, "Members must not be empty!"); + Assert.notEmpty(members, "Members must not be null or empty!"); Assert.noNullElements(members, "Members must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(members) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.geoHash(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromArray(members) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.geoHash(rawKey(key), serialized))); } /* (non-Javadoc) @@ -221,17 +221,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations public final Mono> geoPos(K key, V... members) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(members, "Member must not be null!"); - Assert.notEmpty(members, "Members must not be empty!"); + Assert.notEmpty(members, "Members must not be null or empty!"); Assert.noNullElements(members, "Members must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(members) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.geoPos(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromArray(members) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.geoPos(rawKey(key), serialized))); } /* (non-Javadoc) @@ -243,13 +239,10 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations Assert.notNull(key, "Key must not be null!"); Assert.notNull(within, "Circle must not be null!"); - return createMono(connection -> { - - return connection.geoRadius(rawKey(key), within) // - .flatMap(Flux::fromIterable) // - .map(location -> new GeoLocation<>(readValue(location.getName()), location.getPoint())) // - .collectList(); - }); + return createMono(connection -> connection.geoRadius(rawKey(key), within) // + .flatMap(Flux::fromIterable) // + .map(location -> new GeoLocation<>(readValue(location.getName()), location.getPoint())) // + .collectList()); } /* (non-Javadoc) @@ -262,16 +255,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations Assert.notNull(within, "Circle must not be null!"); Assert.notNull(args, "GeoRadiusCommandArgs must not be null!"); - return createMono(connection -> { - - return connection.geoRadius(rawKey(key), within, args) // - .flatMap(Flux::fromIterable) // - .map(geoResult -> new GeoResult<>( - new GeoLocation<>(readValue(geoResult.getContent().getName()), geoResult.getContent().getPoint()), - geoResult.getDistance())) // - .collectList() // - .map(GeoResults::new); - }); + return createMono(connection -> connection.geoRadius(rawKey(key), within, args) // + .flatMap(Flux::fromIterable) // + .map(geoResult -> new GeoResult<>( + new GeoLocation<>(readValue(geoResult.getContent().getName()), geoResult.getContent().getPoint()), + geoResult.getDistance())) // + .collectList() // + .map(GeoResults::new)); } /* (non-Javadoc) @@ -283,13 +273,10 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations Assert.notNull(key, "Key must not be null!"); Assert.notNull(member, "Member must not be null!"); - return createMono(connection -> { - - return connection.geoRadiusByMember(rawKey(key), rawValue(member), new Distance(radius)) // - .flatMap(Flux::fromIterable) // - .map(geoLocation -> new GeoLocation<>(readValue(geoLocation.getName()), geoLocation.getPoint())) // - .collectList(); - }); + return createMono(connection -> connection.geoRadiusByMember(rawKey(key), rawValue(member), new Distance(radius)) // + .flatMap(Flux::fromIterable) // + .map(geoLocation -> new GeoLocation<>(readValue(geoLocation.getName()), geoLocation.getPoint())) // + .collectList()); } /* (non-Javadoc) @@ -302,13 +289,10 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations Assert.notNull(member, "Member must not be null!"); Assert.notNull(distance, "Distance must not be null!"); - return createMono(connection -> { - - return connection.geoRadiusByMember(rawKey(key), rawValue(member), distance) // - .flatMap(Flux::fromIterable) // - .map(geoLocation -> new GeoLocation<>(readValue(geoLocation.getName()), geoLocation.getPoint())) // - .collectList(); - }); + return createMono(connection -> connection.geoRadiusByMember(rawKey(key), rawValue(member), distance) // + .flatMap(Flux::fromIterable) // + .map(geoLocation -> new GeoLocation<>(readValue(geoLocation.getName()), geoLocation.getPoint())) // + .collectList()); } /* (non-Javadoc) @@ -323,16 +307,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations Assert.notNull(distance, "Distance must not be null!"); Assert.notNull(args, "GeoRadiusCommandArgs must not be null!"); - return createMono(connection -> { - - return connection.geoRadiusByMember(rawKey(key), rawValue(member), distance, args) // - .flatMap(Flux::fromIterable) // - .map(geoResult -> new GeoResult<>( - new GeoLocation<>(readValue(geoResult.getContent().getName()), geoResult.getContent().getPoint()), - geoResult.getDistance())) // - .collectList() // - .map(GeoResults::new); - }); + return createMono(connection -> connection.geoRadiusByMember(rawKey(key), rawValue(member), distance, args) // + .flatMap(Flux::fromIterable) // + .map(geoResult -> new GeoResult<>( + new GeoLocation<>(readValue(geoResult.getContent().getName()), geoResult.getContent().getPoint()), + geoResult.getDistance())) // + .collectList() // + .map(GeoResults::new)); } /* (non-Javadoc) @@ -343,17 +324,13 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations public final Mono geoRemove(K key, V... members) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(members, "Member must not be null!"); - Assert.notEmpty(members, "Members must not be empty!"); + Assert.notEmpty(members, "Members must not be null or empty!"); Assert.noNullElements(members, "Members must not contain null elements!"); - return template.createMono(connection -> { - - return Flux.fromArray(members) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.zSetCommands().zRem(rawKey(key), serialized)); - }); + return template.createMono(connection -> Flux.fromArray(members) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.zSetCommands().zRem(rawKey(key), serialized))); } /* (non-Javadoc) @@ -382,14 +359,14 @@ public class DefaultReactiveGeoOperations implements ReactiveGeoOperations } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } private V readValue(ByteBuffer buffer) { - return serializationContext.value().read(buffer); + return serializationContext.getValueSerializationPair().read(buffer); } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java index ba9918884..05be4200b 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHashOperations.java @@ -28,25 +28,32 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveHashCommands; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveHashOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveHashOperations implements ReactiveHashOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Creates new instance of {@link DefaultReactiveHashOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveHashOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -64,13 +71,10 @@ public class DefaultReactiveHashOperations implements ReactiveHashOpe Assert.notEmpty(hashKeys, "Hash keys must not be empty!"); Assert.noNullElements(hashKeys, "Hash keys must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(hashKeys) // - .map(o -> (HK) o).map(this::rawHashKey) // - .collectList() // - .then(hks -> connection.hDel(rawKey(key), hks)); - }); + return createMono(connection -> Flux.fromArray(hashKeys) // + .map(o -> (HK) o).map(this::rawHashKey) // + .collectList() // + .then(hks -> connection.hDel(rawKey(key), hks))); } /* (non-Javadoc) @@ -109,20 +113,10 @@ public class DefaultReactiveHashOperations implements ReactiveHashOpe Assert.notNull(hashKeys, "Hash keys must not be null!"); Assert.notEmpty(hashKeys, "Hash keys must not be empty!"); - return createMono(connection -> { - - return Flux.fromIterable(hashKeys) // - .map(this::rawHashKey) // - .collectList() // - .then(hks -> connection.hMGet(rawKey(key), hks)).map(byteBuffers -> { - - List values = new ArrayList(byteBuffers.size()); - for (ByteBuffer byteBuffer : byteBuffers) { - values.add(readHashValue(byteBuffer)); - } - return values; - }); - }); + return createMono(connection -> Flux.fromIterable(hashKeys) // + .map(this::rawHashKey) // + .collectList() // + .then(hks -> connection.hMGet(rawKey(key), hks)).map(this::deserializeHashValues)); } /* (non-Javadoc) @@ -187,13 +181,9 @@ public class DefaultReactiveHashOperations implements ReactiveHashOpe Assert.notNull(key, "Key must not be null!"); Assert.notNull(map, "Map must not be null!"); - return createMono(connection -> { - - return Flux.fromIterable(() -> map.entrySet().iterator()) // - .collectMap(entry -> rawHashKey(entry.getKey()), entry -> rawHashValue(entry.getValue())) // - .flatMap(serialized -> connection.hMSet(rawKey(key), serialized)); - - }); + return createMono(connection -> Flux.fromIterable(() -> map.entrySet().iterator()) // + .collectMap(entry -> rawHashKey(entry.getKey()), entry -> rawHashValue(entry.getValue())) // + .flatMap(serialized -> connection.hMSet(rawKey(key), serialized))); } /* (non-Javadoc) @@ -245,16 +235,7 @@ public class DefaultReactiveHashOperations implements ReactiveHashOpe Assert.notNull(key, "Key must not be null!"); return createMono(connection -> connection.hGetAll(rawKey(key)) // - .map(map -> { - - Map deserialized = new LinkedHashMap<>(map.size()); - - map.forEach((k, v) -> { - deserialized.put(readHashKey(k), readHashValue(v)); - }); - - return deserialized; - })); + .map(this::deserializeHashEntries)); } /* (non-Javadoc) @@ -276,24 +257,44 @@ public class DefaultReactiveHashOperations implements ReactiveHashOpe } private ByteBuffer rawKey(H key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private ByteBuffer rawHashKey(HK key) { - return serializationContext.hashKey().write(key); + return serializationContext.getHashKeySerializationPair().write(key); } private ByteBuffer rawHashValue(HV key) { - return serializationContext.hashValue().write(key); + return serializationContext.getHashValueSerializationPair().write(key); } @SuppressWarnings("unchecked") private HK readHashKey(ByteBuffer value) { - return (HK) serializationContext.hashKey().read(value); + return (HK) serializationContext.getHashKeySerializationPair().read(value); } @SuppressWarnings("unchecked") private HV readHashValue(ByteBuffer value) { - return (HV) serializationContext.hashValue().read(value); + return (HV) serializationContext.getHashValueSerializationPair().read(value); + } + + private Map deserializeHashEntries(Map source) { + + Map deserialized = new LinkedHashMap<>(source.size()); + + source.forEach((k, v) -> { + deserialized.put(readHashKey(k), readHashValue(v)); + }); + + return deserialized; + } + + private List deserializeHashValues(List source) { + + List values = new ArrayList(source.size()); + for (ByteBuffer byteBuffer : source) { + values.add(readHashValue(byteBuffer)); + } + return values; } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperations.java index bec84265b..aaf448b26 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperations.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.data.redis.serializer.RedisSerializationContext; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -23,25 +24,31 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveHyperLogLogCommands; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveHyperLogLogOperations}. * * @author Mark Paluch + * @auhtor Christoph Strobl * @since 2.0 */ public class DefaultReactiveHyperLogLogOperations implements ReactiveHyperLogLogOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Creates new instance of {@link DefaultReactiveHyperLogLogOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveHyperLogLogOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -55,17 +62,13 @@ public class DefaultReactiveHyperLogLogOperations implements ReactiveHyper public final Mono add(K key, V... values) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(values, "Values must not be null!"); - Assert.notEmpty(values, "Values must not be empty!"); + Assert.notEmpty(values, "Values must not be null or empty!"); Assert.noNullElements(values, "Values must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serializedValues -> connection.pfAdd(rawKey(key), serializedValues)); - }); + return createMono(connection -> Flux.fromArray(values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serializedValues -> connection.pfAdd(rawKey(key), serializedValues))); } /* (non-Javadoc) @@ -75,17 +78,13 @@ public class DefaultReactiveHyperLogLogOperations implements ReactiveHyper @SafeVarargs public final Mono size(K... keys) { - Assert.notNull(keys, "Keys must not be null!"); - Assert.notEmpty(keys, "Keys must not be empty!"); + Assert.notEmpty(keys, "Keys must not be null or empty!"); Assert.noNullElements(keys, "Keys must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(connection::pfCount); - }); + return createMono(connection -> Flux.fromArray(keys) // + .map(this::rawKey) // + .collectList() // + .flatMap(connection::pfCount)); } /* (non-Javadoc) @@ -96,17 +95,13 @@ public class DefaultReactiveHyperLogLogOperations implements ReactiveHyper public final Mono union(K destination, K... sourceKeys) { Assert.notNull(destination, "Destination key must not be null!"); - Assert.notNull(sourceKeys, "Source keys must not be null!"); - Assert.notEmpty(sourceKeys, "Source keys must not be empty!"); + Assert.notEmpty(sourceKeys, "Source keys must not be null or empty!"); Assert.noNullElements(sourceKeys, "Source keys must not contain null elements!"); - return createMono(connection -> { - - return Flux.fromArray(sourceKeys) // - .map(this::rawKey) // - .collectList() // - .flatMap(serialized -> connection.pfMerge(rawKey(destination), serialized)); - }); + return createMono(connection -> Flux.fromArray(sourceKeys) // + .map(this::rawKey) // + .collectList() // + .flatMap(serialized -> connection.pfMerge(rawKey(destination), serialized))); } /* (non-Javadoc) @@ -128,10 +123,10 @@ public class DefaultReactiveHyperLogLogOperations implements ReactiveHyper } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveListOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveListOperations.java index 58121bee3..71fca3fd3 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveListOperations.java @@ -31,25 +31,32 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveListCommands; import org.springframework.data.redis.connection.RedisListCommands.Position; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveListOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveListOperations implements ReactiveListOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Create new instance of {@link DefaultReactiveListOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveListOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -63,16 +70,7 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio Assert.notNull(key, "Key must not be null!"); - return createMono(connection -> connection.lRange(rawKey(key), start, end).map(raw -> { - - List result = new ArrayList(raw.size()); - - for (ByteBuffer buffer : raw) { - result.add(readValue(buffer)); - } - - return result; - })); + return createMono(connection -> connection.lRange(rawKey(key), start, end).map(this::deserializeValues)); } /* (non-Javadoc) @@ -112,7 +110,7 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio @SafeVarargs public final Mono leftPushAll(K key, V... values) { - Assert.notNull(values, "Values must not be null!"); + Assert.notEmpty(values, "Values must not be null or empty!"); return leftPushAll(key, Arrays.asList(values)); } @@ -124,16 +122,12 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio public Mono leftPushAll(K key, Collection values) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(values, "Values must not be null!"); - Assert.notEmpty(values, "Values must not be empty!"); + Assert.notEmpty(values, "Values must not be null or empty!"); - return createMono(connection -> { - - return Flux.fromIterable(values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.lPush(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromIterable(values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.lPush(rawKey(key), serialized))); } /* (non-Javadoc) @@ -185,16 +179,12 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio public Mono rightPushAll(K key, Collection values) { Assert.notNull(key, "Key must not be null!"); - Assert.notNull(values, "Values must not be null!"); - Assert.notEmpty(values, "Values must not be empty!"); + Assert.notEmpty(values, "Values must not be null or empty!"); - return createMono(connection -> { - - return Flux.fromIterable(values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.rPush(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromIterable(values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.rPush(rawKey(key), serialized))); } /* (non-Javadoc) @@ -273,7 +263,7 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio Assert.notNull(key, "Key must not be null!"); Assert.notNull(timeout, "Duration must not be null!"); - Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second"); + Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second!"); return createMono(connection -> connection.blPop(Collections.singletonList(rawKey(key)), timeout) .map(popResult -> readValue(popResult.getValue()))); @@ -298,7 +288,7 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio Assert.notNull(key, "Key must not be null!"); Assert.notNull(timeout, "Duration must not be null!"); - Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second"); + Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second!"); return createMono(connection -> connection.brPop(Collections.singletonList(rawKey(key)), timeout) .map(popResult -> readValue(popResult.getValue()))); @@ -326,7 +316,7 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio Assert.notNull(sourceKey, "Source key must not be null!"); Assert.notNull(destinationKey, "Destination key must not be null!"); Assert.notNull(timeout, "Duration must not be null!"); - Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second"); + Assert.isTrue(isZeroOrGreater1Second(timeout), "Duration must be either zero or greater or equal to 1 second!"); return createMono( connection -> connection.bRPopLPush(rawKey(sourceKey), rawKey(destinationKey), timeout).map(this::readValue)); @@ -355,14 +345,25 @@ public class DefaultReactiveListOperations implements ReactiveListOperatio } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } private V readValue(ByteBuffer buffer) { - return serializationContext.value().read(buffer); + return serializationContext.getValueSerializationPair().read(buffer); + } + + private List deserializeValues(List source) { + + List result = new ArrayList(source.size()); + + for (ByteBuffer buffer : source) { + result.add(readValue(buffer)); + } + + return result; } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveSetOperations.java index 7dc4cb667..c88fc5ed1 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveSetOperations.java @@ -29,25 +29,32 @@ import java.util.function.Function; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveSetCommands; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveSetOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveSetOperations implements ReactiveSetOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Creates new {@link DefaultReactiveSetOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveSetOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -65,13 +72,10 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations return createMono(connection -> connection.sAdd(rawKey(key), rawValue(values[0]))); } - return createMono(connection -> { - - return Flux.fromArray(values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.sAdd(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromArray(values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.sAdd(rawKey(key), serialized))); } /* (non-Javadoc) @@ -87,13 +91,10 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations return createMono(connection -> connection.sRem(rawKey(key), rawValue((V) values[0]))); } - return createMono(connection -> { - - return Flux.fromArray((V[]) values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.sRem(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromArray((V[]) values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.sRem(rawKey(key), serialized))); } /* (non-Javadoc) @@ -163,16 +164,11 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(key, "Key must not be null!"); Assert.notNull(otherKeys, "Other keys must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(connection::sInter) // - .map(this::readValueSet); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(connection::sInter) // + .map(this::readValueSet)); } /* (non-Javadoc) @@ -198,15 +194,10 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(otherKeys, "Other keys must not be null!"); Assert.notNull(destKey, "Destination key must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(rawKeys -> connection.sInterStore(rawKey(destKey), rawKeys)); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(rawKeys -> connection.sInterStore(rawKey(destKey), rawKeys))); } /* (non-Javadoc) @@ -230,16 +221,11 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(key, "Key must not be null!"); Assert.notNull(otherKeys, "Other keys must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(connection::sUnion) // - .map(this::readValueSet); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(connection::sUnion) // + .map(this::readValueSet)); } /* (non-Javadoc) @@ -265,15 +251,10 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(otherKeys, "Other keys must not be null!"); Assert.notNull(destKey, "Destination key must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(rawKeys -> connection.sUnionStore(rawKey(destKey), rawKeys)); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(rawKeys -> connection.sUnionStore(rawKey(destKey), rawKeys))); } /* (non-Javadoc) @@ -297,16 +278,11 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(key, "Key must not be null!"); Assert.notNull(otherKeys, "Other keys must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(connection::sDiff) // - .map(this::readValueSet); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(connection::sDiff) // + .map(this::readValueSet)); } /* (non-Javadoc) @@ -332,15 +308,10 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations Assert.notNull(otherKeys, "Other keys must not be null!"); Assert.notNull(destKey, "Destination key must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(rawKeys -> connection.sDiffStore(rawKey(destKey), rawKeys)); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(rawKeys -> connection.sDiffStore(rawKey(destKey), rawKeys))); } /* (non-Javadoc) @@ -406,7 +377,7 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private List getKeys(K key, Collection otherKeys) { @@ -420,11 +391,11 @@ public class DefaultReactiveSetOperations implements ReactiveSetOperations } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } private V readValue(ByteBuffer buffer) { - return serializationContext.value().read(buffer); + return serializationContext.getValueSerializationPair().read(buffer); } private Set readValueSet(Collection raw) { diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveValueOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveValueOperations.java index 25050e20c..f214a3305 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveValueOperations.java @@ -30,26 +30,33 @@ import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveStringCommands; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; -import org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; import org.springframework.util.Assert; /** * Default implementation of {@link ReactiveValueOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveValueOperations implements ReactiveValueOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Creates new {@link DefaultReactiveValueOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveValueOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -170,20 +177,7 @@ public class DefaultReactiveValueOperations implements ReactiveValueOperat Assert.notNull(keys, "Keys must not be null!"); return createMono(connection -> Flux.fromIterable(keys).map(key()::write).collectList().flatMap(connection::mGet) - .map(byteBuffers -> { - List result = new ArrayList<>(byteBuffers.size()); - - for (ByteBuffer buffer : byteBuffers) { - - if (buffer == null) { - result.add(null); - } else { - result.add(readValue(buffer)); - } - } - - return result; - })); + .map(this::deserializeValues)); } /* (non-Javadoc) @@ -195,7 +189,8 @@ public class DefaultReactiveValueOperations implements ReactiveValueOperat Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); - return createMono(connection -> connection.append(rawKey(key), serializationContext.string().write(value))); + return createMono( + connection -> connection.append(rawKey(key), serializationContext.getStringSerializationPair().write(value))); } /* (non-Javadoc) @@ -207,7 +202,7 @@ public class DefaultReactiveValueOperations implements ReactiveValueOperat Assert.notNull(key, "Key must not be null!"); return createMono(connection -> connection.getRange(rawKey(key), start, end) // - .map(string()::read)); + .map(stringSerializationPair()::read)); } /* (non-Javadoc) @@ -273,26 +268,42 @@ public class DefaultReactiveValueOperations implements ReactiveValueOperat } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } private V readValue(ByteBuffer buffer) { - return serializationContext.value().read(buffer); + return serializationContext.getValueSerializationPair().read(buffer); } - private SerializationTuple string() { - return serializationContext.string(); + private SerializationPair stringSerializationPair() { + return serializationContext.getStringSerializationPair(); } - private SerializationTuple key() { - return serializationContext.key(); + private SerializationPair key() { + return serializationContext.getKeySerializationPair(); } - private SerializationTuple value() { - return serializationContext.value(); + private SerializationPair value() { + return serializationContext.getValueSerializationPair(); + } + + private List deserializeValues(List source) { + + List result = new ArrayList<>(source.size()); + + for (ByteBuffer buffer : source) { + + if (buffer == null) { + result.add(null); + } else { + result.add(readValue(buffer)); + } + } + + return result; } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveZSetOperations.java index f9e1d1a26..096be12be 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveZSetOperations.java @@ -34,7 +34,7 @@ import org.springframework.data.redis.connection.ReactiveZSetCommands; import org.springframework.data.redis.connection.RedisZSetCommands.Limit; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.util.ByteUtils; import org.springframework.util.Assert; @@ -42,18 +42,25 @@ import org.springframework.util.Assert; * Default implementation of {@link ReactiveZSetOperations}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public class DefaultReactiveZSetOperations implements ReactiveZSetOperations { private final ReactiveRedisTemplate template; - private final ReactiveSerializationContext serializationContext; + private final RedisSerializationContext serializationContext; + /** + * Creates new {@link DefaultReactiveZSetOperations}. + * + * @param template must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + */ public DefaultReactiveZSetOperations(ReactiveRedisTemplate template, - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { Assert.notNull(template, "ReactiveRedisTemplate must not be null!"); - Assert.notNull(serializationContext, "ReactiveSerializationContext must not be null!"); + Assert.notNull(serializationContext, "RedisSerializationContext must not be null!"); this.template = template; this.serializationContext = serializationContext; @@ -79,13 +86,10 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio Assert.notNull(key, "Key must not be null!"); Assert.notNull(tuples, "Key must not be null!"); - return createMono(connection -> { - - return Flux.fromIterable(tuples) // - .map(t -> new DefaultTuple(ByteUtils.getBytes(rawValue(t.getValue())), t.getScore())) // - .collectList() // - .flatMap(serialized -> connection.zAdd(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromIterable(tuples) // + .map(t -> new DefaultTuple(ByteUtils.getBytes(rawValue(t.getValue())), t.getScore())) // + .collectList() // + .flatMap(serialized -> connection.zAdd(rawKey(key), serialized))); } /* (non-Javadoc) @@ -102,13 +106,10 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio return createMono(connection -> connection.zRem(rawKey(key), rawValue((V) values[0]))); } - return createMono(connection -> { - - return Flux.fromArray((V[]) values) // - .map(this::rawValue) // - .collectList() // - .flatMap(serialized -> connection.zRem(rawKey(key), serialized)); - }); + return createMono(connection -> Flux.fromArray((V[]) values) // + .map(this::rawValue) // + .collectList() // + .flatMap(serialized -> connection.zRem(rawKey(key), serialized))); } /* (non-Javadoc) @@ -378,15 +379,10 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio Assert.notNull(otherKeys, "Other keys must not be null!"); Assert.notNull(destKey, "Destination key must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(serialized -> connection.zUnionStore(rawKey(destKey), serialized)); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(serialized -> connection.zUnionStore(rawKey(destKey), serialized))); } /* (non-Javadoc) @@ -412,15 +408,10 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio Assert.notNull(otherKeys, "Other keys must not be null!"); Assert.notNull(destKey, "Destination key must not be null!"); - List keys = getKeys(key, otherKeys); - - return createMono(connection -> { - - return Flux.fromIterable(keys) // - .map(this::rawKey) // - .collectList() // - .flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized)); - }); + return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) // + .map(this::rawKey) // + .collectList() // + .flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized))); } /* (non-Javadoc) @@ -492,7 +483,7 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio } private ByteBuffer rawKey(K key) { - return serializationContext.key().write(key); + return serializationContext.getKeySerializationPair().write(key); } private List getKeys(K key, Collection otherKeys) { @@ -506,11 +497,11 @@ public class DefaultReactiveZSetOperations implements ReactiveZSetOperatio } private ByteBuffer rawValue(V value) { - return serializationContext.value().write(value); + return serializationContext.getValueSerializationPair().write(value); } private V readValue(ByteBuffer buffer) { - return serializationContext.value().read(buffer); + return serializationContext.getValueSerializationPair().read(buffer); } private Set readValueSet(Collection raw) { diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveRedisOperations.java b/src/main/java/org/springframework/data/redis/core/ReactiveRedisOperations.java index 002630d2d..97dee9e06 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveRedisOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveRedisOperations.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.data.redis.serializer.RedisSerializationContext; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -23,13 +24,13 @@ import java.time.Instant; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.DataType; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; /** * Interface that specified a basic set of Redis operations, implemented by {@link ReactiveRedisTemplate}. Not often * used but a useful option for extensibility and testability (as it can be easily mocked or stubbed). * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ public interface ReactiveRedisOperations { @@ -45,7 +46,7 @@ public interface ReactiveRedisOperations { * * @param return type * @param action callback object that specifies the Redis action - * @return a result object returned by the action or null + * @return a result object returned by the action or {@link Flux#empty()}. */ Flux execute(ReactiveRedisCallback action); @@ -187,12 +188,12 @@ public interface ReactiveRedisOperations { /** * Returns the operations performed on simple values (or Strings in Redis terminology) given a - * {@link ReactiveSerializationContext}. + * {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return value operations. */ - ReactiveValueOperations opsForValue(ReactiveSerializationContext serializationContext); + ReactiveValueOperations opsForValue(RedisSerializationContext serializationContext); /** * Returns the operations performed on list values. @@ -202,12 +203,12 @@ public interface ReactiveRedisOperations { ReactiveListOperations opsForList(); /** - * Returns the operations performed on list values given a {@link ReactiveSerializationContext}. + * Returns the operations performed on list values given a {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return list operations. */ - ReactiveListOperations opsForList(ReactiveSerializationContext serializationContext); + ReactiveListOperations opsForList(RedisSerializationContext serializationContext); /** * Returns the operations performed on set values. @@ -217,12 +218,12 @@ public interface ReactiveRedisOperations { ReactiveSetOperations opsForSet(); /** - * Returns the operations performed on set values given a {@link ReactiveSerializationContext}. + * Returns the operations performed on set values given a {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return set operations. */ - ReactiveSetOperations opsForSet(ReactiveSerializationContext serializationContext); + ReactiveSetOperations opsForSet(RedisSerializationContext serializationContext); /** * Returns the operations performed on zset values (also known as sorted sets). @@ -233,12 +234,12 @@ public interface ReactiveRedisOperations { /** * Returns the operations performed on zset values (also known as sorted sets) given a - * {@link ReactiveSerializationContext}. + * {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return zset operations. */ - ReactiveZSetOperations opsForZSet(ReactiveSerializationContext serializationContext); + ReactiveZSetOperations opsForZSet(RedisSerializationContext serializationContext); /** * Returns the operations performed on multisets using HyperLogLog. @@ -248,12 +249,12 @@ public interface ReactiveRedisOperations { ReactiveHyperLogLogOperations opsForHyperLogLog(); /** - * Returns the operations performed on multisets using HyperLogLog given a {@link ReactiveSerializationContext}. + * Returns the operations performed on multisets using HyperLogLog given a {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return never {@literal null}. */ - ReactiveHyperLogLogOperations opsForHyperLogLog(ReactiveSerializationContext serializationContext); + ReactiveHyperLogLogOperations opsForHyperLogLog(RedisSerializationContext serializationContext); /** * Returns the operations performed on hash values. @@ -265,14 +266,14 @@ public interface ReactiveRedisOperations { ReactiveHashOperations opsForHash(); /** - * Returns the operations performed on hash values given a {@link ReactiveSerializationContext}. + * Returns the operations performed on hash values given a {@link RedisSerializationContext}. * * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @param hash key (or field) type. * @param hash value type. * @return hash operations. */ - ReactiveHashOperations opsForHash(ReactiveSerializationContext serializationContext); + ReactiveHashOperations opsForHash(RedisSerializationContext serializationContext); /** * Returns geospatial specific operations interface. @@ -287,10 +288,10 @@ public interface ReactiveRedisOperations { * @param serializationContext serializers to be used with the returned operations, must not be {@literal null}. * @return geospatial specific operations. */ - ReactiveGeoOperations opsForGeo(ReactiveSerializationContext serializationContext); + ReactiveGeoOperations opsForGeo(RedisSerializationContext serializationContext); /** - * @return the {@link ReactiveSerializationContext}. + * @return the {@link RedisSerializationContext}. */ - ReactiveSerializationContext getSerializationContext(); + RedisSerializationContext getSerializationContext(); } diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java b/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java index 924614ae2..81d321aca 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java @@ -25,60 +25,66 @@ import java.time.Instant; import java.util.List; import org.reactivestreams.Publisher; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.InitializingBean; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.ReactiveRedisConnection; import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Central abstraction for reactive Redis data access. + * Central abstraction for reactive Redis data access implementing {@link ReactiveRedisOperations}. *

* Performs automatic serialization/deserialization between the given objects and the underlying binary data in the - * Redis store. By default, it uses Java serialization for its objects (through {@link JdkSerializationRedisSerializer} - * ). - *

- * Once configured, this class is thread-safe. + * Redis store. *

* Note that while the template is generified, it is up to the serializers/deserializers to properly convert the given * Objects to and from binary data. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 * @param the Redis key type against which the template works (usually a String) * @param the Redis value type against which the template works */ -public class ReactiveRedisTemplate - implements BeanClassLoaderAware, InitializingBean, ReactiveRedisOperations { +public class ReactiveRedisTemplate implements ReactiveRedisOperations { - private ReactiveRedisConnectionFactory connectionFactory; - private boolean exposeConnection = true; - private boolean initialized = false; - private boolean enableDefaultSerializer = true; - private RedisSerializer defaultSerializer; - private ClassLoader classLoader; - private ReactiveSerializationContextSupport serializationContext = new MutableReactiveSerializationContext<>(); - - // cache singleton objects (where possible) - private ReactiveValueOperations valueOps; - private ReactiveListOperations listOps; - private ReactiveSetOperations setOps; - private ReactiveZSetOperations zSetOps; - private ReactiveHyperLogLogOperations hyperLogLogOps; - private ReactiveGeoOperations geoOps; + private final ReactiveRedisConnectionFactory connectionFactory; + private final RedisSerializationContext serializationContext; + private final boolean exposeConnection; /** - * Construct a new {@link ReactiveRedisTemplate} instance. + * Creates new {@link ReactiveRedisTemplate} using given {@link ReactiveRedisConnectionFactory} and + * {@link RedisSerializationContext}. + * + * @param connectionFactory must not be {@literal null}. + * @param serializationContext must not be {@literal null}. */ - public ReactiveRedisTemplate() {} + public ReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory, + RedisSerializationContext serializationContext) { + this(connectionFactory, serializationContext, false); + } + + /** + * Creates new {@link ReactiveRedisTemplate} using given {@link ReactiveRedisConnectionFactory} and + * {@link RedisSerializationContext}. + * + * @param connectionFactory must not be {@literal null}. + * @param serializationContext must not be {@literal null}. + * @param exposeConnection flag indicating to expose the connection used. + */ + public ReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory, + RedisSerializationContext serializationContext, boolean exposeConnection) { + + Assert.notNull(connectionFactory, "ConnectionFactory must not be null!"); + Assert.notNull(serializationContext, "SerializationContext must not be null!"); + + this.connectionFactory = connectionFactory; + this.serializationContext = serializationContext; + this.exposeConnection = exposeConnection; + } /** * Returns the connectionFactory. @@ -89,214 +95,19 @@ public class ReactiveRedisTemplate return connectionFactory; } - /** - * Sets the connection factory. - * - * @param connectionFactory The connectionFactory to set. - */ - public void setConnectionFactory(ReactiveRedisConnectionFactory connectionFactory) { - this.connectionFactory = connectionFactory; - } - - /** - * @param enableDefaultSerializer Whether or not the default serializer should be used. If not, any serializers not - * explicilty set will remain null and values will not be serialized or deserialized. - */ - public void setEnableDefaultSerializer(boolean enableDefaultSerializer) { - this.enableDefaultSerializer = enableDefaultSerializer; - } - - /** - * Returns the default serializer used by this template. - * - * @return template default serializer - */ - public RedisSerializer getDefaultSerializer() { - return defaultSerializer; - } - - /** - * Sets the default serializer to use for this template. All serializers (expect the - * {@link #setStringSerializer(RedisSerializer)}) are initialized to this value unless explicitly set. Defaults to - * {@link JdkSerializationRedisSerializer}. - * - * @param serializer default serializer to use - */ - public void setDefaultSerializer(RedisSerializer serializer) { - this.defaultSerializer = serializer; - } - - /** - * Returns the key serializer used by this template. - * - * @return the key serializer used by this template. - */ - public RedisSerializer getKeySerializer() { - return serializationContext.getKeySerializer(); - } - - /** - * Sets the key serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}. - * - * @param serializer the key serializer to be used by this template. - */ - @SuppressWarnings("unchecked") - public void setKeySerializer(RedisSerializer serializer) { - getMutableSerializationContext().setKeySerializer((RedisSerializer) serializer); - } - - /** - * Returns the value serializer used by this template. - * - * @return the value serializer used by this template. - */ - public RedisSerializer getValueSerializer() { - return serializationContext.getValueSerializer(); - } - - /** - * Sets the value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}. - * - * @param serializer the value serializer to be used by this template. - */ - @SuppressWarnings("unchecked") - public void setValueSerializer(RedisSerializer serializer) { - getMutableSerializationContext().setValueSerializer((RedisSerializer) serializer); - } - - /** - * Returns the hashKeySerializer. - * - * @return Returns the hashKeySerializer - */ - public RedisSerializer getHashKeySerializer() { - return serializationContext.getHashKeySerializer(); - } - - /** - * Sets the hash key (or field) serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}. - * - * @param hashKeySerializer The hashKeySerializer to set. - */ - public void setHashKeySerializer(RedisSerializer hashKeySerializer) { - getMutableSerializationContext().setHashKeySerializer(hashKeySerializer); - } - - /** - * Returns the hashValueSerializer. - * - * @return Returns the hashValueSerializer - */ - public RedisSerializer getHashValueSerializer() { - return serializationContext.getHashValueSerializer(); - } - - /** - * Sets the hash value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}. - * - * @param hashValueSerializer The hashValueSerializer to set. - */ - public void setHashValueSerializer(RedisSerializer hashValueSerializer) { - getMutableSerializationContext().setHashValueSerializer(hashValueSerializer); - } - - /** - * Returns the stringSerializer. - * - * @return Returns the stringSerializer - */ - public RedisSerializer getStringSerializer() { - return serializationContext.getStringSerializer(); - } - - /** - * Sets the string value serializer to be used by this template (when the arguments or return types are always - * strings). Defaults to {@link StringRedisSerializer}. - * - * @param stringSerializer The stringValueSerializer to set. - * @see ValueOperations#get(Object, long, long) - */ - public void setStringSerializer(RedisSerializer stringSerializer) { - getMutableSerializationContext().setStringSerializer(stringSerializer); - } - - /** - * Set the {@link ClassLoader} to be used for the default {@link JdkSerializationRedisSerializer} in case no other - * {@link RedisSerializer} is explicitly set as the default one. - * - * @param classLoader can be {@literal null}. - * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader - */ - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - /** - * Initializes the properties and creates and sets an immutable {@link ReactiveSerializationContext}. Serializers - * cannot be changed after properties are initialized. - */ - @Override - public void afterPropertiesSet() { - - boolean defaultUsed = false; - - if (this.defaultSerializer == null) { - - this.defaultSerializer = new JdkSerializationRedisSerializer( - this.classLoader != null ? this.classLoader : this.getClass().getClassLoader()); - } - - if (this.enableDefaultSerializer) { - - if (this.serializationContext.getKeySerializer() == null) { - setKeySerializer(this.defaultSerializer); - defaultUsed = true; - } - - if (this.serializationContext.getValueSerializer() == null) { - setValueSerializer(this.defaultSerializer); - defaultUsed = true; - } - - if (this.serializationContext.getHashKeySerializer() == null) { - setHashKeySerializer(this.defaultSerializer); - defaultUsed = true; - } - - if (this.serializationContext.getHashValueSerializer() == null) { - setHashValueSerializer(this.defaultSerializer); - defaultUsed = true; - } - } - - if (this.enableDefaultSerializer && defaultUsed) { - Assert.notNull(this.defaultSerializer, "Default serializer is null and not all serializers initialized"); - } - - this.serializationContext = new ImmutableReactiveSerializationContext(serializationContext); - this.initialized = true; - } - /* (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue() */ @Override public ReactiveValueOperations opsForValue() { - - if (valueOps == null) { - valueOps = opsForValue(serializationContext); - } - - return valueOps; + return opsForValue(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override - public ReactiveValueOperations opsForValue( - ReactiveSerializationContext serializationContext) { + public ReactiveValueOperations opsForValue(RedisSerializationContext serializationContext) { return new DefaultReactiveValueOperations<>(this, serializationContext); } @@ -305,19 +116,14 @@ public class ReactiveRedisTemplate */ @Override public ReactiveListOperations opsForList() { - - if (listOps == null) { - listOps = opsForList(serializationContext); - } - - return listOps; + return opsForList(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForList(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForList(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override - public ReactiveListOperations opsForList(ReactiveSerializationContext serializationContext) { + public ReactiveListOperations opsForList(RedisSerializationContext serializationContext) { return new DefaultReactiveListOperations<>(this, serializationContext); } @@ -325,19 +131,14 @@ public class ReactiveRedisTemplate * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet() */ public ReactiveSetOperations opsForSet() { - - if (setOps == null) { - setOps = opsForSet(serializationContext); - } - - return setOps; + return opsForSet(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override - public ReactiveSetOperations opsForSet(ReactiveSerializationContext serializationContext) { + public ReactiveSetOperations opsForSet(RedisSerializationContext serializationContext) { return new DefaultReactiveSetOperations<>(this, serializationContext); } @@ -345,19 +146,14 @@ public class ReactiveRedisTemplate * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet() */ public ReactiveZSetOperations opsForZSet() { - - if (zSetOps == null) { - zSetOps = opsForZSet(serializationContext); - } - - return zSetOps; + return opsForZSet(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override - public ReactiveZSetOperations opsForZSet(ReactiveSerializationContext serializationContext) { + public ReactiveZSetOperations opsForZSet(RedisSerializationContext serializationContext) { return new DefaultReactiveZSetOperations<>(this, serializationContext); } @@ -366,20 +162,15 @@ public class ReactiveRedisTemplate */ @Override public ReactiveHyperLogLogOperations opsForHyperLogLog() { - - if (hyperLogLogOps == null) { - hyperLogLogOps = opsForHyperLogLog(serializationContext); - } - - return hyperLogLogOps; + return opsForHyperLogLog(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHyperLogLog(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHyperLogLog(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override public ReactiveHyperLogLogOperations opsForHyperLogLog( - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { return new DefaultReactiveHyperLogLogOperations<>(this, serializationContext); } @@ -392,11 +183,11 @@ public class ReactiveRedisTemplate } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHash(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHash(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override public ReactiveHashOperations opsForHash( - ReactiveSerializationContext serializationContext) { + RedisSerializationContext serializationContext) { return new DefaultReactiveHashOperations<>(this, serializationContext); } @@ -405,19 +196,14 @@ public class ReactiveRedisTemplate */ @Override public ReactiveGeoOperations opsForGeo() { - - if (geoOps == null) { - geoOps = opsForGeo(serializationContext); - } - - return geoOps; + return opsForGeo(serializationContext); } /* (non-Javadoc) - * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForGeo(org.springframework.data.redis.serializer.ReactiveSerializationContext) + * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForGeo(org.springframework.data.redis.serializer.RedisSerializationContext) */ @Override - public ReactiveGeoOperations opsForGeo(ReactiveSerializationContext serializationContext) { + public ReactiveGeoOperations opsForGeo(RedisSerializationContext serializationContext) { return new DefaultReactiveGeoOperations<>(this, serializationContext); } @@ -440,7 +226,6 @@ public class ReactiveRedisTemplate */ public Flux execute(ReactiveRedisCallback action, boolean exposeConnection) { - Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); Assert.notNull(action, "Callback object must not be null"); ReactiveRedisConnectionFactory factory = getConnectionFactory(); @@ -498,7 +283,6 @@ public class ReactiveRedisTemplate */ private Publisher doInConnection(ReactiveRedisCallback action, boolean exposeConnection) { - Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); Assert.notNull(action, "Callback object must not be null"); ReactiveRedisConnectionFactory factory = getConnectionFactory(); @@ -727,231 +511,15 @@ public class ReactiveRedisTemplate * @see org.springframework.data.redis.core.ReactiveRedisOperations#serialization() */ @Override - public ReactiveSerializationContext getSerializationContext() { + public RedisSerializationContext getSerializationContext() { return serializationContext; } - @SuppressWarnings("unchecked") - private MutableReactiveSerializationContext getMutableSerializationContext() { - - Assert.state(serializationContext instanceof MutableReactiveSerializationContext, - () -> String.format("Client configuration must be instance of MutableReactiveSerializationContext but is %s", - ClassUtils.getShortName(serializationContext.getClass()))); - - return (MutableReactiveSerializationContext) serializationContext; - } - private ByteBuffer rawKey(K key) { - return getSerializationContext().key().getWriter().write(key); + return getSerializationContext().getKeySerializationPair().getWriter().write(key); } private K readKey(ByteBuffer buffer) { - return getSerializationContext().key().getReader().read(buffer); - } - - /** - * @author Mark Paluch - */ - static abstract class ReactiveSerializationContextSupport implements ReactiveSerializationContext { - - @Override - public abstract SerializationTuple key(); - - @Override - public abstract SerializationTuple value(); - - @Override - public abstract SerializationTuple string(); - - @Override - public abstract SerializationTuple hashKey(); - - @Override - public abstract SerializationTuple hashValue(); - - public abstract RedisSerializer getKeySerializer(); - - public abstract RedisSerializer getValueSerializer(); - - public abstract RedisSerializer getHashKeySerializer(); - - public abstract RedisSerializer getHashValueSerializer(); - - public abstract RedisSerializer getStringSerializer(); - } - - /** - * @author Mark Paluch - */ - static class ImmutableReactiveSerializationContext extends ReactiveSerializationContextSupport { - - private RedisSerializer keySerializer; - private final SerializationTuple keyTuple; - - private RedisSerializer valueSerializer; - private final SerializationTuple valueTuple; - - private RedisSerializer hashKeySerializer; - private final SerializationTuple hashKeyTuple; - - private RedisSerializer hashValueSerializer; - private final SerializationTuple hashValueTuple; - - private RedisSerializer stringSerializer; - private final SerializationTuple stringTuple; - - public ImmutableReactiveSerializationContext(ReactiveSerializationContextSupport context) { - - keySerializer = context.getKeySerializer(); - keyTuple = context.key(); - valueSerializer = context.getValueSerializer(); - valueTuple = context.value(); - hashKeySerializer = context.getHashKeySerializer(); - hashKeyTuple = context.hashKey(); - hashValueSerializer = context.getHashValueSerializer(); - hashValueTuple = context.hashValue(); - stringSerializer = context.getStringSerializer(); - stringTuple = context.string(); - } - - @Override - public SerializationTuple key() { - return keyTuple; - } - - @Override - public SerializationTuple value() { - return valueTuple; - } - - @Override - public SerializationTuple string() { - return stringTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashKey() { - return (SerializationTuple) hashKeyTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashValue() { - return (SerializationTuple) hashValueTuple; - } - - public RedisSerializer getKeySerializer() { - return keySerializer; - } - - public RedisSerializer getValueSerializer() { - return valueSerializer; - } - - public RedisSerializer getHashKeySerializer() { - return hashKeySerializer; - } - - public RedisSerializer getHashValueSerializer() { - return hashValueSerializer; - } - - public RedisSerializer getStringSerializer() { - return stringSerializer; - } - } - - /** - * @author Mark Paluch - */ - static class MutableReactiveSerializationContext extends ReactiveSerializationContextSupport { - - private RedisSerializer keySerializer; - private SerializationTuple keyTuple = SerializationTuple.raw(); - - private RedisSerializer valueSerializer; - private SerializationTuple valueTuple = SerializationTuple.raw(); - - private RedisSerializer hashKeySerializer; - private SerializationTuple hashKeyTuple = SerializationTuple.raw(); - - private RedisSerializer hashValueSerializer; - private SerializationTuple hashValueTuple = SerializationTuple.raw(); - - private RedisSerializer stringSerializer = new StringRedisSerializer(); - private SerializationTuple stringTuple = SerializationTuple.fromSerializer(stringSerializer); - - @Override - public SerializationTuple key() { - return keyTuple; - } - - @Override - public SerializationTuple value() { - return valueTuple; - } - - @Override - public SerializationTuple string() { - return stringTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashKey() { - return (SerializationTuple) hashKeyTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashValue() { - return (SerializationTuple) hashValueTuple; - } - - public RedisSerializer getKeySerializer() { - return keySerializer; - } - - public void setKeySerializer(RedisSerializer keySerializer) { - this.keySerializer = keySerializer; - this.keyTuple = SerializationTuple.fromSerializer(keySerializer); - } - - public RedisSerializer getValueSerializer() { - return valueSerializer; - } - - public void setValueSerializer(RedisSerializer valueSerializer) { - this.valueSerializer = valueSerializer; - this.valueTuple = SerializationTuple.fromSerializer(valueSerializer); - } - - public RedisSerializer getHashKeySerializer() { - return hashKeySerializer; - } - - public void setHashKeySerializer(RedisSerializer hashKeySerializer) { - this.hashKeySerializer = hashKeySerializer; - this.hashKeyTuple = SerializationTuple.fromSerializer(hashKeySerializer); - } - - public RedisSerializer getHashValueSerializer() { - return hashValueSerializer; - } - - public void setHashValueSerializer(RedisSerializer hashValueSerializer) { - this.hashValueSerializer = hashValueSerializer; - this.hashValueTuple = SerializationTuple.fromSerializer(hashValueSerializer); - } - - public RedisSerializer getStringSerializer() { - return stringSerializer; - } - - public void setStringSerializer(RedisSerializer stringSerializer) { - this.stringSerializer = stringSerializer; - this.stringTuple = SerializationTuple.fromSerializer(stringSerializer); - } + return getSerializationContext().getKeySerializationPair().getReader().read(buffer); } } diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveZSetOperations.java b/src/main/java/org/springframework/data/redis/core/ReactiveZSetOperations.java index 148c13ee1..fa26085e8 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveZSetOperations.java @@ -54,17 +54,6 @@ public interface ReactiveZSetOperations { */ Mono addAll(K key, Collection> tuples); - /** - * Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} if it already exists. - * - * @param key must not be {@literal null}. - * @param tuples must not be {@literal null}. - * @return - * @see Redis Documentation: ZADD - */ - // TODO - // Mono add(K key, Set> tuples); - /** * Remove {@code values} from sorted set. Return number of removed elements. * diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultReactiveSerializationContextBuilder.java b/src/main/java/org/springframework/data/redis/serializer/DefaultReactiveSerializationContextBuilder.java deleted file mode 100644 index 81c8932e6..000000000 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultReactiveSerializationContextBuilder.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2017 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 - * - * http://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 org.springframework.data.redis.serializer.ReactiveSerializationContext.ReactiveSerializationContextBuilder; -import org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple; -import org.springframework.util.Assert; - -/** - * Default implementation of {@link ReactiveSerializationContextBuilder}. - * - * @author Mark Paluch - * @since 2.0 - */ -public class DefaultReactiveSerializationContextBuilder implements ReactiveSerializationContextBuilder { - - private SerializationTuple keyTuple; - - private SerializationTuple valueTuple; - - private SerializationTuple hashKeyTuple; - - private SerializationTuple hashValueTuple; - - private SerializationTuple stringTuple = SerializationTuple.fromSerializer(new StringRedisSerializer()); - - @Override - public ReactiveSerializationContextBuilder key(SerializationTuple tuple) { - - Assert.notNull(tuple, "SerializationTuple must not be null!"); - - this.keyTuple = tuple; - - return this; - } - - @Override - public ReactiveSerializationContextBuilder key(RedisElementReader reader, RedisElementWriter writer) { - return key(SerializationTuple.just(reader, writer)); - } - - @Override - public ReactiveSerializationContextBuilder key(RedisSerializer serializer) { - return key(SerializationTuple.fromSerializer(serializer)); - } - - @Override - public ReactiveSerializationContextBuilder value(SerializationTuple tuple) { - - Assert.notNull(tuple, "SerializationTuple must not be null!"); - - this.valueTuple = tuple; - - return this; - } - - @Override - public ReactiveSerializationContextBuilder value(RedisElementReader reader, RedisElementWriter writer) { - return value(SerializationTuple.just(reader, writer)); - } - - @Override - public ReactiveSerializationContextBuilder value(RedisSerializer serializer) { - return value(SerializationTuple.fromSerializer(serializer)); - } - - @Override - public ReactiveSerializationContextBuilder hashKey(SerializationTuple tuple) { - - Assert.notNull(tuple, "SerializationTuple must not be null!"); - - this.hashKeyTuple = tuple; - - return this; - } - - @Override - public ReactiveSerializationContextBuilder hashKey(RedisElementReader reader, RedisElementWriter writer) { - return hashKey(SerializationTuple.just(reader, writer)); - } - - @Override - public ReactiveSerializationContextBuilder hashKey(RedisSerializer serializer) { - return hashKey(SerializationTuple.fromSerializer(serializer)); - } - - @Override - public ReactiveSerializationContextBuilder hashValue(SerializationTuple tuple) { - - Assert.notNull(tuple, "SerializationTuple must not be null!"); - - this.hashValueTuple = tuple; - - return this; - } - - @Override - public ReactiveSerializationContextBuilder hashValue(RedisElementReader reader, - RedisElementWriter writer) { - return hashValue(SerializationTuple.just(reader, writer)); - } - - @Override - public ReactiveSerializationContextBuilder hashValue(RedisSerializer serializer) { - return hashValue(SerializationTuple.fromSerializer(serializer)); - } - - @Override - public ReactiveSerializationContextBuilder string(SerializationTuple tuple) { - - Assert.notNull(tuple, "SerializationTuple must not be null!"); - - this.hashValueTuple = tuple; - - return this; - } - - @Override - public ReactiveSerializationContextBuilder string(RedisElementReader reader, - RedisElementWriter writer) { - return string(SerializationTuple.just(reader, writer)); - } - - @Override - public ReactiveSerializationContextBuilder string(RedisSerializer serializer) { - return string(SerializationTuple.fromSerializer(serializer)); - } - - @Override - public ReactiveSerializationContext build() { - - Assert.notNull(keyTuple, "Key SerializationTuple must not be null!"); - Assert.notNull(valueTuple, "Value SerializationTuple must not be null!"); - Assert.notNull(hashKeyTuple, "HashKey SerializationTuple must not be null!"); - Assert.notNull(hashValueTuple, "ValueKey SerializationTuple must not be null!"); - - return new DefaultReactiveSerializationContext(keyTuple, valueTuple, hashKeyTuple, hashValueTuple, - stringTuple); - } - - static class DefaultReactiveSerializationContext implements ReactiveSerializationContext { - - private final SerializationTuple keyTuple; - - private final SerializationTuple valueTuple; - - private final SerializationTuple hashKeyTuple; - - private final SerializationTuple hashValueTuple; - - private final SerializationTuple stringTuple; - - public DefaultReactiveSerializationContext(SerializationTuple keyTuple, SerializationTuple valueTuple, - SerializationTuple hashKeyTuple, SerializationTuple hashValueTuple, - SerializationTuple stringTuple) { - - this.keyTuple = keyTuple; - this.valueTuple = valueTuple; - this.hashKeyTuple = hashKeyTuple; - this.hashValueTuple = hashValueTuple; - this.stringTuple = stringTuple; - } - - @Override - public SerializationTuple key() { - return keyTuple; - } - - @Override - public SerializationTuple value() { - return valueTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashKey() { - return (SerializationTuple) hashKeyTuple; - } - - @Override - @SuppressWarnings("unchecked") - public SerializationTuple hashValue() { - return (SerializationTuple) hashValueTuple; - } - - @Override - public SerializationTuple string() { - return stringTuple; - } - } -} diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java index c75879a88..59439f285 100644 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; * Default implementation of {@link RedisElementReader}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ @RequiredArgsConstructor @@ -41,7 +42,7 @@ class DefaultRedisElementReader implements RedisElementReader { return (T) buffer; } - byte[] bytes = new byte[buffer.remaining()]; + byte[] bytes = new byte[buffer.slice().remaining()]; buffer.get(bytes); return serializer.deserialize(bytes); diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java new file mode 100644 index 000000000..3a53c9acf --- /dev/null +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java @@ -0,0 +1,177 @@ +/* + * Copyright 2017 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 + * + * http://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 org.springframework.util.Assert; + +/** + * Default implementation of {@link RedisSerializationContext}. + * + * @author Mark Paluch + * @author Christoph Strobl + * @since 2.0 + */ +class DefaultRedisSerializationContext implements RedisSerializationContext { + + private final SerializationPair keyTuple; + private final SerializationPair valueTuple; + private final SerializationPair hashKeyTuple; + private final SerializationPair hashValueTuple; + private final SerializationPair stringTuple; + + private DefaultRedisSerializationContext(SerializationPair keyTuple, SerializationPair valueTuple, + SerializationPair hashKeyTuple, SerializationPair hashValueTuple, SerializationPair stringTuple) { + + this.keyTuple = keyTuple; + this.valueTuple = valueTuple; + this.hashKeyTuple = hashKeyTuple; + this.hashValueTuple = hashValueTuple; + this.stringTuple = stringTuple; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext#getKeySerializationPair() + */ + @Override + public SerializationPair getKeySerializationPair() { + return keyTuple; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext#getValueSerializationPair() + */ + @Override + public SerializationPair getValueSerializationPair() { + return valueTuple; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext#getHashKeySerializationPair() + */ + @Override + @SuppressWarnings("unchecked") + public SerializationPair getHashKeySerializationPair() { + return (SerializationPair) hashKeyTuple; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext#getHashValueSerializationPair() + */ + @Override + @SuppressWarnings("unchecked") + public SerializationPair getHashValueSerializationPair() { + return (SerializationPair) hashValueTuple; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext#getStringSerializationPair() + */ + @Override + public SerializationPair getStringSerializationPair() { + return stringTuple; + } + + /** + * Default implementation of {@link RedisSerializationContextBuilder}. + * + * @author Mark Paluch + * @author Christoph Strobl + * @since 2.0 + */ + static class DefaultRedisSerializationContextBuilder implements RedisSerializationContextBuilder { + + private SerializationPair keyTuple; + private SerializationPair valueTuple; + private SerializationPair hashKeyTuple; + private SerializationPair hashValueTuple; + private SerializationPair stringTuple = SerializationPair.fromSerializer(new StringRedisSerializer()); + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#key(SerializationPair) + */ + @Override + public RedisSerializationContextBuilder key(SerializationPair tuple) { + + Assert.notNull(tuple, "SerializationPair must not be null!"); + + this.keyTuple = tuple; + return this; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#value(SerializationPair) + */ + @Override + public RedisSerializationContextBuilder value(SerializationPair tuple) { + + Assert.notNull(tuple, "SerializationPair must not be null!"); + + this.valueTuple = tuple; + return this; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#hashKey(SerializationPair) + */ + @Override + public RedisSerializationContextBuilder hashKey(SerializationPair tuple) { + + Assert.notNull(tuple, "SerializationPair must not be null!"); + + this.hashKeyTuple = tuple; + return this; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#hashValue(SerializationPair) + */ + @Override + public RedisSerializationContextBuilder hashValue(SerializationPair tuple) { + + Assert.notNull(tuple, "SerializationPair must not be null!"); + + this.hashValueTuple = tuple; + return this; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#string(SerializationPair) + */ + @Override + public RedisSerializationContextBuilder string(SerializationPair tuple) { + + Assert.notNull(tuple, "SerializationPair must not be null!"); + + this.hashValueTuple = tuple; + return this; + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContextBuilder#build() + */ + @Override + public RedisSerializationContext build() { + + Assert.notNull(keyTuple, "Key SerializationPair must not be null!"); + Assert.notNull(valueTuple, "Value SerializationPair must not be null!"); + Assert.notNull(hashKeyTuple, "HashKey SerializationPair must not be null!"); + Assert.notNull(hashValueTuple, "ValueKey SerializationPair must not be null!"); + + return new DefaultRedisSerializationContext(keyTuple, valueTuple, hashKeyTuple, hashValueTuple, + stringTuple); + } + } +} diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultSerializationTuple.java b/src/main/java/org/springframework/data/redis/serializer/DefaultSerializationPair.java similarity index 65% rename from src/main/java/org/springframework/data/redis/serializer/DefaultSerializationTuple.java rename to src/main/java/org/springframework/data/redis/serializer/DefaultSerializationPair.java index 23c6e5cdd..80a56970c 100644 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultSerializationTuple.java +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultSerializationPair.java @@ -15,34 +15,26 @@ */ package org.springframework.data.redis.serializer; -import org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple; +import lombok.Getter; +import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; /** - * Default implementation of {@link SerializationTuple}. + * Default implementation of {@link SerializationPair}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ -class DefaultSerializationTuple implements SerializationTuple { +@Getter +class DefaultSerializationPair implements SerializationPair { private final RedisElementReader reader; - private final RedisElementWriter writer; @SuppressWarnings("unchecked") - protected DefaultSerializationTuple(RedisElementReader reader, RedisElementWriter writer) { + protected DefaultSerializationPair(RedisElementReader reader, RedisElementWriter writer) { this.reader = (RedisElementReader) reader; this.writer = (RedisElementWriter) writer; } - - @Override - public RedisElementReader getReader() { - return reader; - } - - @Override - public RedisElementWriter getWriter() { - return writer; - } } diff --git a/src/main/java/org/springframework/data/redis/serializer/ReactiveSerializationContext.java b/src/main/java/org/springframework/data/redis/serializer/ReactiveSerializationContext.java deleted file mode 100644 index 67e964c10..000000000 --- a/src/main/java/org/springframework/data/redis/serializer/ReactiveSerializationContext.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright 2017 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 - * - * http://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 java.nio.ByteBuffer; - -import org.springframework.util.Assert; - -/** - * Serialization context for reactive use. - *

- * This context provides {@link SerializationTuple}s for key, value, hash-key (field), hash-value and {@link String} - * serialization and deserialization. - * - * @author Mark Paluch - * @since 2.0 - * @see RedisElementWriter - * @see RedisElementReader - */ -public interface ReactiveSerializationContext { - - /** - * Creates a new {@link ReactiveSerializationContextBuilder}. - * - * @param expected key type. - * @param expected value type. - * @return a new {@link ReactiveSerializationContextBuilder}. - */ - static ReactiveSerializationContextBuilder builder() { - return new DefaultReactiveSerializationContextBuilder<>(); - } - - /** - * @return {@link SerializationTuple} for key-typed serialization and deserialization. - */ - SerializationTuple key(); - - /** - * @return {@link SerializationTuple} for value-typed serialization and deserialization. - */ - SerializationTuple value(); - - /** - * @return {@link SerializationTuple} for hash-key-typed serialization and deserialization. - */ - SerializationTuple hashKey(); - - /** - * @return {@link SerializationTuple} for hash-value-typed serialization and deserialization. - */ - SerializationTuple hashValue(); - - /** - * @return {@link SerializationTuple} for {@link String}-typed serialization and deserialization. - */ - SerializationTuple string(); - - /** - * Typed serialization tuple. - */ - interface SerializationTuple { - - /** - * Creates a {@link SerializationTuple} adapter given {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return a {@link SerializationTuple} adapter for {@link RedisSerializer}. - */ - static SerializationTuple fromSerializer(RedisSerializer serializer) { - - Assert.notNull(serializer, "RedisSerializer must not be null!"); - - return new RedisSerializerTupleAdapter(serializer); - } - - /** - * Creates a {@link SerializationTuple} adapter given {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return a {@link SerializationTuple} encapsulating {@link RedisElementReader} and {@link RedisElementWriter}. - */ - static SerializationTuple just(RedisElementReader reader, - RedisElementWriter writer) { - - Assert.notNull(reader, "RedisElementReader must not be null!"); - Assert.notNull(writer, "RedisElementWriter must not be null!"); - - return new DefaultSerializationTuple<>(reader, writer); - } - - /** - * Creates a pass-thru {@link SerializationTuple} to pass-thru {@link ByteBuffer} objects. - * - * @return a pass-thru {@link SerializationTuple}. - */ - static SerializationTuple raw() { - return RedisSerializerTupleAdapter.raw(); - } - - /** - * @return the {@link RedisElementReader}. - */ - RedisElementReader getReader(); - - /** - * Deserialize a {@link ByteBuffer} into the according type. - * - * @param buffer must not be {@literal null}. - * @return the deserialized value. - */ - default T read(ByteBuffer buffer) { - return getReader().read(buffer); - } - - /** - * @return the {@link RedisElementWriter}. - */ - RedisElementWriter getWriter(); - - /** - * Serialize a {@code element} to its {@link ByteBuffer} representation. - * - * @param element - * @return the {@link ByteBuffer} representing {@code element} in its binary form. - */ - default ByteBuffer write(T element) { - return getWriter().write(element); - } - } - - /** - * Builder for {@link ReactiveSerializationContext}. - */ - interface ReactiveSerializationContextBuilder { - - /** - * Set the key {@link SerializationTuple}. - * - * @param tuple must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder key(SerializationTuple tuple); - - /** - * Set the key {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder key(RedisElementReader reader, RedisElementWriter writer); - - /** - * Set the key {@link SerializationTuple} given a {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder key(RedisSerializer serializer); - - /** - * Set the value {@link SerializationTuple}. - * - * @param tuple must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder value(SerializationTuple tuple); - - /** - * Set the value {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder value(RedisElementReader reader, RedisElementWriter writer); - - /** - * Set the value {@link SerializationTuple} given a {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder value(RedisSerializer serializer); - - /** - * Set the hash key {@link SerializationTuple}. - * - * @param tuple must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashKey(SerializationTuple tuple); - - /** - * Set the hash key {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashKey(RedisElementReader reader, - RedisElementWriter writer); - - /** - * Set the hash key {@link SerializationTuple} given a {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashKey(RedisSerializer serializer); - - /** - * Set the hash value {@link SerializationTuple}. - * - * @param tuple must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashValue(SerializationTuple tuple); - - /** - * Set the hash value {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashValue(RedisElementReader reader, - RedisElementWriter writer); - - /** - * Set the hash value {@link SerializationTuple} given a {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder hashValue(RedisSerializer serializer); - - /** - * Set the string {@link SerializationTuple}. - * - * @param tuple must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder string(SerializationTuple tuple); - - /** - * Set the string {@link RedisElementReader} and {@link RedisElementWriter}. - * - * @param reader must not be {@literal null}. - * @param writer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder string(RedisElementReader reader, - RedisElementWriter writer); - - /** - * Set the string {@link SerializationTuple} given a {@link RedisSerializer}. - * - * @param serializer must not be {@literal null}. - * @return {@literal this} builder. - */ - ReactiveSerializationContextBuilder string(RedisSerializer serializer); - - /** - * Builds a {@link ReactiveSerializationContext}. - * - * @return the {@link ReactiveSerializationContext}. - */ - ReactiveSerializationContext build(); - } -} diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java new file mode 100644 index 000000000..aac24fb0e --- /dev/null +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java @@ -0,0 +1,406 @@ +/* + * Copyright 2017 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 + * + * http://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 java.nio.ByteBuffer; + +import org.springframework.util.Assert; + +/** + * Serialization context for reactive use. + *

+ * This context provides {@link SerializationPair}s for key, value, hash-key (field), hash-value and {@link String} + * serialization and deserialization. + * + * @author Mark Paluch + * @author Christoph Strobl + * @since 2.0 + * @see RedisElementWriter + * @see RedisElementReader + */ +public interface RedisSerializationContext { + + /** + * Creates a new {@link RedisSerializationContextBuilder}. + * + * @param expected key type. + * @param expected value type. + * @return a new {@link RedisSerializationContextBuilder}. + */ + @SuppressWarnings("unchecked") + static RedisSerializationContextBuilder newSerializationContext() { + return new DefaultRedisSerializationContext.DefaultRedisSerializationContextBuilder(); + } + + /** + * Creates a new {@link RedisSerializationContextBuilder} using a given default {@link RedisSerializer}. + * + * @param defaultSerializer must not be {@literal null}. + * @param expected key type. + * @param expected value type. + * @return a new {@link RedisSerializationContextBuilder}. + */ + static RedisSerializationContextBuilder newSerializationContext(RedisSerializer defaultSerializer) { + + Assert.notNull(defaultSerializer, "DefaultSerializer must not be null!"); + + return newSerializationContext(SerializationPair.fromSerializer(defaultSerializer)); + } + + /** + * Creates a new {@link RedisSerializationContextBuilder} using a given default {@link SerializationPair}. + * + * @param serializationPair must not be {@literal null}. + * @param expected key type. + * @param expected value type. + * @return a new {@link RedisSerializationContextBuilder}. + */ + @SuppressWarnings("unchecked") + static RedisSerializationContextBuilder newSerializationContext(SerializationPair serializationPair) { + + Assert.notNull(serializationPair, "SerializationPair must not be null!"); + + return new DefaultRedisSerializationContext.DefaultRedisSerializationContextBuilder() // + .key(serializationPair).value(serializationPair) // + .hashKey(serializationPair).hashValue(serializationPair); + } + + /** + * Creates a new {@link RedisSerializationContext} using a {@link SerializationPair#raw()} serialization pair. + * + * @return + */ + static RedisSerializationContext raw() { + return just(SerializationPair.raw()); + } + + /** + * Creates a new {@link RedisSerializationContext} using a {@link StringRedisSerializer}. + * + * @return + */ + static RedisSerializationContext string() { + return fromSerializer(new StringRedisSerializer()); + } + + /** + * Creates a new {@link RedisSerializationContext} using the given {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @param + * @return + */ + static RedisSerializationContext fromSerializer(RedisSerializer serializer) { + return just(SerializationPair.fromSerializer(serializer)); + } + + /** + * Creates a new {@link RedisSerializationContext} using the given {@link SerializationPair}. + * + * @param serializationPair + * @param + * @return + */ + static RedisSerializationContext just(SerializationPair serializationPair) { + return RedisSerializationContext.newSerializationContext(serializationPair).build(); + } + + /** + * @return {@link SerializationPair} for key-typed serialization and deserialization. + */ + SerializationPair getKeySerializationPair(); + + /** + * @return {@link SerializationPair} for value-typed serialization and deserialization. + */ + SerializationPair getValueSerializationPair(); + + /** + * @return {@link SerializationPair} for hash-key-typed serialization and deserialization. + */ + SerializationPair getHashKeySerializationPair(); + + /** + * @return {@link SerializationPair} for hash-value-typed serialization and deserialization. + */ + SerializationPair getHashValueSerializationPair(); + + /** + * @return {@link SerializationPair} for {@link String}-typed serialization and deserialization. + */ + SerializationPair getStringSerializationPair(); + + /** + * Typed serialization tuple. + * + * @author Mark Paluch + * @author Christoph Strobl + */ + interface SerializationPair { + + /** + * Creates a {@link SerializationPair} adapter given {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return a {@link SerializationPair} adapter for {@link RedisSerializer}. + */ + static SerializationPair fromSerializer(RedisSerializer serializer) { + + Assert.notNull(serializer, "RedisSerializer must not be null!"); + + return new RedisSerializerToSerializationPairAdapter(serializer); + } + + /** + * Creates a {@link SerializationPair} adapter given {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return a {@link SerializationPair} encapsulating {@link RedisElementReader} and {@link RedisElementWriter}. + */ + static SerializationPair just(RedisElementReader reader, + RedisElementWriter writer) { + + Assert.notNull(reader, "RedisElementReader must not be null!"); + Assert.notNull(writer, "RedisElementWriter must not be null!"); + + return new DefaultSerializationPair<>(reader, writer); + } + + /** + * Creates a pass through {@link SerializationPair} to pass-thru {@link ByteBuffer} objects. + * + * @return a pass through {@link SerializationPair}. + */ + static SerializationPair raw() { + return RedisSerializerToSerializationPairAdapter.raw(); + } + + /** + * @return the {@link RedisElementReader}. + */ + RedisElementReader getReader(); + + /** + * Deserialize a {@link ByteBuffer} into the according type. + * + * @param buffer must not be {@literal null}. + * @return the deserialized value. + */ + default T read(ByteBuffer buffer) { + return getReader().read(buffer); + } + + /** + * @return the {@link RedisElementWriter}. + */ + RedisElementWriter getWriter(); + + /** + * Serialize a {@code element} to its {@link ByteBuffer} representation. + * + * @param element + * @return the {@link ByteBuffer} representing {@code element} in its binary form. + */ + default ByteBuffer write(T element) { + return getWriter().write(element); + } + } + + /** + * Builder for {@link RedisSerializationContext}. + * + * @author Mark Paluch + * @author Christoph Strobl + */ + interface RedisSerializationContextBuilder { + + /** + * Set the key {@link SerializationPair}. + * + * @param pair must not be {@literal null}. + * @return {@literal this} builder. + */ + RedisSerializationContextBuilder key(SerializationPair pair); + + /** + * Set the key {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder key(RedisElementReader reader, RedisElementWriter writer) { + + key(SerializationPair.just(reader, writer)); + return this; + } + + /** + * Set the key {@link SerializationPair} given a {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder key(RedisSerializer serializer) { + + key(SerializationPair.fromSerializer(serializer)); + return this; + } + + /** + * Set the value {@link SerializationPair}. + * + * @param pair must not be {@literal null}. + * @return {@literal this} builder. + */ + RedisSerializationContextBuilder value(SerializationPair pair); + + /** + * Set the value {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder value(RedisElementReader reader, RedisElementWriter writer) { + + value(SerializationPair.just(reader, writer)); + return this; + } + + /** + * Set the value {@link SerializationPair} given a {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder value(RedisSerializer serializer) { + + value(SerializationPair.fromSerializer(serializer)); + return this; + } + + /** + * Set the hash key {@link SerializationPair}. + * + * @param pair must not be {@literal null}. + * @return {@literal this} builder. + */ + RedisSerializationContextBuilder hashKey(SerializationPair pair); + + /** + * Set the hash key {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder hashKey(RedisElementReader reader, + RedisElementWriter writer) { + + hashKey(SerializationPair.just(reader, writer)); + return this; + } + + /** + * Set the hash key {@link SerializationPair} given a {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder hashKey(RedisSerializer serializer) { + + hashKey(SerializationPair.fromSerializer(serializer)); + return this; + } + + /** + * Set the hash value {@link SerializationPair}. + * + * @param pair must not be {@literal null}. + * @return {@literal this} builder. + */ + RedisSerializationContextBuilder hashValue(SerializationPair pair); + + /** + * Set the hash value {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder hashValue(RedisElementReader reader, + RedisElementWriter writer) { + + hashValue(SerializationPair.just(reader, writer)); + return this; + } + + /** + * Set the hash value {@link SerializationPair} given a {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder hashValue(RedisSerializer serializer) { + + hashValue(SerializationPair.fromSerializer(serializer)); + return this; + } + + /** + * Set the string {@link SerializationPair}. + * + * @param pair must not be {@literal null}. + * @return {@literal this} builder. + */ + RedisSerializationContextBuilder string(SerializationPair pair); + + /** + * Set the string {@link RedisElementReader} and {@link RedisElementWriter}. + * + * @param reader must not be {@literal null}. + * @param writer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder string(RedisElementReader reader, + RedisElementWriter writer) { + + string(SerializationPair.just(reader, writer)); + return this; + } + + /** + * Set the string {@link SerializationPair} given a {@link RedisSerializer}. + * + * @param serializer must not be {@literal null}. + * @return {@literal this} builder. + */ + default RedisSerializationContextBuilder string(RedisSerializer serializer) { + + string(SerializationPair.fromSerializer(serializer)); + return this; + } + + /** + * Builds a {@link RedisSerializationContext}. + * + * @return the {@link RedisSerializationContext}. + */ + RedisSerializationContext build(); + } +} diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializerToSerializationPairAdapter.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializerToSerializationPairAdapter.java new file mode 100644 index 000000000..79e77c156 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializerToSerializationPairAdapter.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017 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 + * + * http://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 org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; +import org.springframework.util.Assert; + +/** + * Adapter to delegate serialization/deserialization to {@link RedisSerializer}. + * + * @author Mark Paluch + * @author Christoph Strobl + * @since 2.0 + */ +class RedisSerializerToSerializationPairAdapter implements SerializationPair { + + private final static RedisSerializerToSerializationPairAdapter RAW = new RedisSerializerToSerializationPairAdapter<>( + null); + + private final DefaultSerializationPair pair; + + protected RedisSerializerToSerializationPairAdapter(RedisSerializer serializer) { + pair = new DefaultSerializationPair(new DefaultRedisElementReader<>(serializer), + new DefaultRedisElementWriter<>(serializer)); + } + + @SuppressWarnings("unchecked") + public static SerializationPair raw() { + return (SerializationPair) RAW; + } + + /** + * Create a {@link SerializationPair} from given {@link RedisSerializer}. + * + * @param redisSerializer must not be {@literal null}. + * @param + * @return + */ + public static SerializationPair from(RedisSerializer redisSerializer) { + + Assert.notNull(redisSerializer, "RedisSerializer must not be null!"); + + return new RedisSerializerToSerializationPairAdapter<>(redisSerializer); + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair#reader() + */ + @Override + public RedisElementReader getReader() { + return pair.getReader(); + } + + /* (non-Javadoc) + * @see org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair#writer() + */ + @Override + public RedisElementWriter getWriter() { + return pair.getWriter(); + } +} diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializerTupleAdapter.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializerTupleAdapter.java deleted file mode 100644 index 1e34ec2a1..000000000 --- a/src/main/java/org/springframework/data/redis/serializer/RedisSerializerTupleAdapter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017 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 - * - * http://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 org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple; - -/** - * Adapter to delegate serialization/deserialization to {@link RedisSerializer}. - * - * @author Mark Paluch - * @since 2.0 - */ -class RedisSerializerTupleAdapter implements SerializationTuple { - - private final static RedisSerializerTupleAdapter RAW = new RedisSerializerTupleAdapter<>(null); - - private final RedisElementReader reader; - private final RedisElementWriter writer; - - protected RedisSerializerTupleAdapter(RedisSerializer serializer) { - - reader = new DefaultRedisElementReader<>(serializer); - writer = new DefaultRedisElementWriter<>(serializer); - } - - @SuppressWarnings("unchecked") - public static SerializationTuple raw() { - return (SerializationTuple) RAW; - } - - public static SerializationTuple from(RedisSerializer redisSerializer) { - return new RedisSerializerTupleAdapter<>(redisSerializer); - } - - /* (non-Javadoc) - * @see org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple#reader() - */ - @Override - public RedisElementReader getReader() { - return reader; - } - - /* (non-Javadoc) - * @see org.springframework.data.redis.serializer.ReactiveSerializationContext.SerializationTuple#writer() - */ - @Override - public RedisElementWriter getWriter() { - return writer; - } -} diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveGeoOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveGeoOperationsIntegrationTests.java index 561b0d0b0..7614ed0f4 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveGeoOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveGeoOperationsIntegrationTests.java @@ -44,6 +44,7 @@ import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; +import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.test.util.MinimumRedisVersionRule; import org.springframework.test.annotation.IfProfileValue; @@ -51,6 +52,7 @@ import org.springframework.test.annotation.IfProfileValue; * Integration tests for {@link DefaultReactiveGeoOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @IfProfileValue(name = "redisVersion", value = "3.2.0+") @@ -71,7 +73,7 @@ public class DefaultReactiveGeoOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -88,7 +90,7 @@ public class DefaultReactiveGeoOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveGeoOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.geoOperations = redisTemplate.opsForGeo(); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java index 5f633ff7a..992436135 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHashOperationsIntegrationTests.java @@ -39,12 +39,14 @@ import org.springframework.data.redis.StringObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Integration tests for {@link DefaultReactiveHashOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -68,16 +70,13 @@ public class DefaultReactiveHashOperationsIntegrationTests { lettuceConnectionFactory.setHostName(SettingsUtils.getHost()); lettuceConnectionFactory.afterPropertiesSet(); - ReactiveRedisTemplate stringTemplate = new ReactiveRedisTemplate<>(); - stringTemplate.setConnectionFactory(lettuceConnectionFactory); - stringTemplate.setEnableDefaultSerializer(true); - stringTemplate.setDefaultSerializer(new StringRedisSerializer()); - stringTemplate.afterPropertiesSet(); + RedisSerializationContext serializationContext = RedisSerializationContext + .fromSerializer(new StringRedisSerializer()); + ReactiveRedisTemplate stringTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + serializationContext); - ReactiveRedisTemplate rawTemplate = new ReactiveRedisTemplate<>(); - rawTemplate.setConnectionFactory(lettuceConnectionFactory); - rawTemplate.setEnableDefaultSerializer(false); - rawTemplate.afterPropertiesSet(); + ReactiveRedisTemplate rawTemplate = new ReactiveRedisTemplate(lettuceConnectionFactory, + RedisSerializationContext.raw()); return Arrays.asList(new Object[][] { { stringTemplate, stringFactory, stringFactory, stringFactory, "String" }, { rawTemplate, rawFactory, rawFactory, rawFactory, "raw" } }); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperationsIntegrationTests.java index c277934c3..d0c8af8ca 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveHyperLogLogOperationsIntegrationTests.java @@ -29,11 +29,13 @@ import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.RedisSerializer; /** * Integration tests for {@link DefaultReactiveHyperLogLogOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -45,7 +47,7 @@ public class DefaultReactiveHyperLogLogOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -62,7 +64,7 @@ public class DefaultReactiveHyperLogLogOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveHyperLogLogOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.hyperLogLogOperations = redisTemplate.opsForHyperLogLog(); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveListOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveListOperationsIntegrationTests.java index a15e62c9b..b2162886a 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveListOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveListOperationsIntegrationTests.java @@ -34,11 +34,13 @@ import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.RedisSerializer; /** * Integration tests for {@link DefaultReactiveListOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -50,7 +52,7 @@ public class DefaultReactiveListOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -67,7 +69,7 @@ public class DefaultReactiveListOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveListOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.listOperations = redisTemplate.opsForList(); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveSetOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveSetOperationsIntegrationTests.java index 50d88774a..c577fe428 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveSetOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveSetOperationsIntegrationTests.java @@ -35,11 +35,13 @@ import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.RedisSerializer; /** * Integration tests for {@link DefaultReactiveSetOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -51,7 +53,7 @@ public class DefaultReactiveSetOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -68,7 +70,7 @@ public class DefaultReactiveSetOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveSetOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.setOperations = redisTemplate.opsForSet(); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java index 847d2d646..b633dec1a 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveValueOperationsIntegrationTests.java @@ -37,12 +37,14 @@ import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Integration tests for {@link DefaultReactiveValueOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -54,7 +56,9 @@ public class DefaultReactiveValueOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + private final RedisSerializer serializer; + + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -71,12 +75,13 @@ public class DefaultReactiveValueOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveValueOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.valueOperations = redisTemplate.opsForValue(); this.keyFactory = keyFactory; this.valueFactory = valueFactory; + this.serializer = serializer; ConnectionFactoryTracker.add(redisTemplate.getConnectionFactory()); } @@ -219,7 +224,7 @@ public class DefaultReactiveValueOperationsIntegrationTests { V value2 = valueFactory.instance(); V absentValue = null; - if (redisTemplate.getValueSerializer() instanceof StringRedisSerializer) { + if (serializer instanceof StringRedisSerializer) { absentValue = (V) ""; } if (value1 instanceof ByteBuffer) { @@ -239,7 +244,7 @@ public class DefaultReactiveValueOperationsIntegrationTests { @Test // DATAREDIS-602 public void append() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V value = valueFactory.instance(); @@ -254,7 +259,7 @@ public class DefaultReactiveValueOperationsIntegrationTests { @Test // DATAREDIS-602 public void getRange() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V value = valueFactory.instance(); @@ -269,7 +274,7 @@ public class DefaultReactiveValueOperationsIntegrationTests { @Test // DATAREDIS-602 public void setRange() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V value = valueFactory.instance(); @@ -289,7 +294,7 @@ public class DefaultReactiveValueOperationsIntegrationTests { @Test // DATAREDIS-602 public void size() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V value = valueFactory.instance(); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultReactiveZSetOperationsIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/DefaultReactiveZSetOperationsIntegrationTests.java index 6309ccb45..b196f622c 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultReactiveZSetOperationsIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultReactiveZSetOperationsIntegrationTests.java @@ -37,12 +37,14 @@ import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisZSetCommands.Limit; +import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Integration tests for {@link DefaultReactiveZSetOperations}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) @SuppressWarnings("unchecked") @@ -54,7 +56,9 @@ public class DefaultReactiveZSetOperationsIntegrationTests { private final ObjectFactory keyFactory; private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + private final RedisSerializer serializer; + + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -71,12 +75,13 @@ public class DefaultReactiveZSetOperationsIntegrationTests { * @param label parameterized test label, no further use besides that. */ public DefaultReactiveZSetOperationsIntegrationTests(ReactiveRedisTemplate redisTemplate, - ObjectFactory keyFactory, ObjectFactory valueFactory, String label) { + ObjectFactory keyFactory, ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.zSetOperations = redisTemplate.opsForZSet(); this.keyFactory = keyFactory; this.valueFactory = valueFactory; + this.serializer = serializer; ConnectionFactoryTracker.add(redisTemplate.getConnectionFactory()); } @@ -524,7 +529,7 @@ public class DefaultReactiveZSetOperationsIntegrationTests { @Test // DATAREDIS-602 public void rangeByLex() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V a = (V) "a"; @@ -542,7 +547,7 @@ public class DefaultReactiveZSetOperationsIntegrationTests { @Test // DATAREDIS-602 public void rangeByLexWithLimit() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V a = (V) "a"; @@ -565,7 +570,7 @@ public class DefaultReactiveZSetOperationsIntegrationTests { @Test // DATAREDIS-602 public void reverseRangeByLex() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V a = (V) "a"; @@ -582,7 +587,7 @@ public class DefaultReactiveZSetOperationsIntegrationTests { @Test // DATAREDIS-602 public void reverseRangeByLexLimit() { - assumeTrue(redisTemplate.getValueSerializer() instanceof StringRedisSerializer); + assumeTrue(serializer instanceof StringRedisSerializer); K key = keyFactory.instance(); V a = (V) "a"; diff --git a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java index f0ee78d88..5fd5ca77c 100644 --- a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java +++ b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java @@ -18,9 +18,12 @@ package org.springframework.data.redis.core; import static org.springframework.data.redis.connection.ClusterTestVariables.*; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; +import org.junit.runners.model.Statement; import org.springframework.data.redis.ByteBufferObjectFactory; import org.springframework.data.redis.DoubleObjectFactory; import org.springframework.data.redis.LongObjectFactory; @@ -36,14 +39,18 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.GenericToStringSerializer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.OxmSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.data.redis.test.util.RedisClusterRule; import org.springframework.oxm.xstream.XStreamMarshaller; /** * Parameters for testing implementations of {@link ReactiveRedisTemplate} * * @author Mark Paluch + * @author Christoph Strobl */ abstract public class ReactiveOperationsTestParams { @@ -69,85 +76,94 @@ abstract public class ReactiveOperationsTestParams { lettuceConnectionFactory.setHostName(SettingsUtils.getHost()); lettuceConnectionFactory.afterPropertiesSet(); - RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); - clusterConfiguration.addClusterNode(new RedisClusterNode(CLUSTER_HOST, MASTER_NODE_1_PORT)); + JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(); + ReactiveRedisTemplate objectTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + RedisSerializationContext.fromSerializer(jdkSerializationRedisSerializer)); - LettuceConnectionFactory lettuceClusterConnectionFactory = new LettuceConnectionFactory(clusterConfiguration); - lettuceClusterConnectionFactory.setPort(SettingsUtils.getPort()); - lettuceClusterConnectionFactory.setHostName(SettingsUtils.getHost()); - lettuceClusterConnectionFactory.afterPropertiesSet(); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + ReactiveRedisTemplate stringTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + RedisSerializationContext.fromSerializer(stringRedisSerializer)); - ReactiveRedisTemplate objectTemplate = new ReactiveRedisTemplate<>(); - objectTemplate.setConnectionFactory(lettuceConnectionFactory); - objectTemplate.afterPropertiesSet(); + GenericToStringSerializer longToStringSerializer = new GenericToStringSerializer(Long.class); + ReactiveRedisTemplate longTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + RedisSerializationContext. newSerializationContext(jdkSerializationRedisSerializer) + .key(stringRedisSerializer).value(longToStringSerializer).build()); - ReactiveRedisTemplate clusterStringTemplate = new ReactiveRedisTemplate<>(); - clusterStringTemplate.setConnectionFactory(lettuceClusterConnectionFactory); - clusterStringTemplate.setDefaultSerializer(new StringRedisSerializer()); - clusterStringTemplate.setEnableDefaultSerializer(true); - clusterStringTemplate.afterPropertiesSet(); + GenericToStringSerializer doubleToStringSerializer = new GenericToStringSerializer(Double.class); + ReactiveRedisTemplate doubleTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + RedisSerializationContext. newSerializationContext(jdkSerializationRedisSerializer) + .key(stringRedisSerializer).value(doubleToStringSerializer).build()); - ReactiveRedisTemplate stringTemplate = new ReactiveRedisTemplate<>(); - stringTemplate.setDefaultSerializer(new StringRedisSerializer()); - stringTemplate.setEnableDefaultSerializer(true); - stringTemplate.setConnectionFactory(lettuceConnectionFactory); - stringTemplate.afterPropertiesSet(); + ReactiveRedisTemplate rawTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, + RedisSerializationContext.raw()); - ReactiveRedisTemplate longTemplate = new ReactiveRedisTemplate<>(); - longTemplate.setKeySerializer(new StringRedisSerializer()); - longTemplate.setValueSerializer(new GenericToStringSerializer<>(Long.class)); - longTemplate.setConnectionFactory(lettuceConnectionFactory); - longTemplate.afterPropertiesSet(); + ReactiveRedisTemplate personTemplate = new ReactiveRedisTemplate(lettuceConnectionFactory, + RedisSerializationContext.fromSerializer(jdkSerializationRedisSerializer)); - ReactiveRedisTemplate doubleTemplate = new ReactiveRedisTemplate<>(); - doubleTemplate.setKeySerializer(new StringRedisSerializer()); - doubleTemplate.setValueSerializer(new GenericToStringSerializer<>(Double.class)); - doubleTemplate.setConnectionFactory(lettuceConnectionFactory); - doubleTemplate.afterPropertiesSet(); + OxmSerializer oxmSerializer = new OxmSerializer(xstream, xstream); + ReactiveRedisTemplate xstreamStringTemplate = new ReactiveRedisTemplate(lettuceConnectionFactory, + RedisSerializationContext.fromSerializer(oxmSerializer)); - ReactiveRedisTemplate rawTemplate = new ReactiveRedisTemplate<>(); - rawTemplate.setEnableDefaultSerializer(false); - rawTemplate.setConnectionFactory(lettuceConnectionFactory); - rawTemplate.afterPropertiesSet(); - - ReactiveRedisTemplate personTemplate = new ReactiveRedisTemplate<>(); - personTemplate.setConnectionFactory(lettuceConnectionFactory); - personTemplate.afterPropertiesSet(); - - OxmSerializer serializer = new OxmSerializer(xstream, xstream); - ReactiveRedisTemplate xstreamStringTemplate = new ReactiveRedisTemplate<>(); - xstreamStringTemplate.setConnectionFactory(lettuceConnectionFactory); - xstreamStringTemplate.setDefaultSerializer(serializer); - xstreamStringTemplate.afterPropertiesSet(); - - ReactiveRedisTemplate xstreamPersonTemplate = new ReactiveRedisTemplate<>(); - xstreamPersonTemplate.setConnectionFactory(lettuceConnectionFactory); - xstreamPersonTemplate.setValueSerializer(serializer); - xstreamPersonTemplate.afterPropertiesSet(); + ReactiveRedisTemplate xstreamPersonTemplate = new ReactiveRedisTemplate(lettuceConnectionFactory, + RedisSerializationContext.fromSerializer(oxmSerializer)); Jackson2JsonRedisSerializer jackson2JsonSerializer = new Jackson2JsonRedisSerializer<>(Person.class); - ReactiveRedisTemplate jackson2JsonPersonTemplate = new ReactiveRedisTemplate<>(); - jackson2JsonPersonTemplate.setConnectionFactory(lettuceConnectionFactory); - jackson2JsonPersonTemplate.setValueSerializer(jackson2JsonSerializer); - jackson2JsonPersonTemplate.afterPropertiesSet(); + ReactiveRedisTemplate jackson2JsonPersonTemplate = new ReactiveRedisTemplate( + lettuceConnectionFactory, RedisSerializationContext.fromSerializer(jackson2JsonSerializer)); GenericJackson2JsonRedisSerializer genericJackson2JsonSerializer = new GenericJackson2JsonRedisSerializer(); - ReactiveRedisTemplate genericJackson2JsonPersonTemplate = new ReactiveRedisTemplate<>(); - genericJackson2JsonPersonTemplate.setConnectionFactory(lettuceConnectionFactory); - genericJackson2JsonPersonTemplate.setValueSerializer(genericJackson2JsonSerializer); - genericJackson2JsonPersonTemplate.afterPropertiesSet(); + ReactiveRedisTemplate genericJackson2JsonPersonTemplate = new ReactiveRedisTemplate( + lettuceConnectionFactory, RedisSerializationContext.fromSerializer(genericJackson2JsonSerializer)); - return Arrays.asList(new Object[][] { // - { stringTemplate, stringFactory, stringFactory , "String"}, // - { clusterStringTemplate, clusterKeyStringFactory, stringFactory, "Cluster String" }, // - { objectTemplate, personFactory, personFactory , "Person/JDK"}, // - { longTemplate, stringFactory, longFactory , "Long"}, // - { doubleTemplate, stringFactory, doubleFactory , "Double"}, // - { rawTemplate, rawFactory, rawFactory , "raw"}, // - { personTemplate, stringFactory, personFactory , "String/Person/JDK"}, // - { xstreamStringTemplate, stringFactory, stringFactory , "String/OXM"}, // - { xstreamPersonTemplate, stringFactory, personFactory, "String/Person/OXM"}, // - { jackson2JsonPersonTemplate, stringFactory, personFactory, "Jackson2"}, // - { genericJackson2JsonPersonTemplate, stringFactory, personFactory, "Generic Jackson 2" } }); + List list = Arrays.asList(new Object[][] { // + { stringTemplate, stringFactory, stringFactory, stringRedisSerializer, "String" }, // + { objectTemplate, personFactory, personFactory, jdkSerializationRedisSerializer, "Person/JDK" }, // + { longTemplate, stringFactory, longFactory, longToStringSerializer, "Long" }, // + { doubleTemplate, stringFactory, doubleFactory, doubleToStringSerializer, "Double" }, // + { rawTemplate, rawFactory, rawFactory, null, "raw" }, // + { personTemplate, stringFactory, personFactory, jdkSerializationRedisSerializer, "String/Person/JDK" }, // + { xstreamStringTemplate, stringFactory, stringFactory, oxmSerializer, "String/OXM" }, // + { xstreamPersonTemplate, stringFactory, personFactory, oxmSerializer, "String/Person/OXM" }, // + { jackson2JsonPersonTemplate, stringFactory, personFactory, jackson2JsonSerializer, "Jackson2" }, // + { genericJackson2JsonPersonTemplate, stringFactory, personFactory, genericJackson2JsonSerializer, + "Generic Jackson 2" } }); + + if (clusterAvailable()) { + + RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); + clusterConfiguration.addClusterNode(new RedisClusterNode(CLUSTER_HOST, MASTER_NODE_1_PORT)); + + ReactiveRedisTemplate clusterStringTemplate = null; + + LettuceConnectionFactory lettuceClusterConnectionFactory = new LettuceConnectionFactory(clusterConfiguration); + lettuceClusterConnectionFactory.setPort(SettingsUtils.getPort()); + lettuceClusterConnectionFactory.setHostName(SettingsUtils.getHost()); + lettuceClusterConnectionFactory.afterPropertiesSet(); + + clusterStringTemplate = new ReactiveRedisTemplate<>(lettuceClusterConnectionFactory, + RedisSerializationContext.string()); + + list = new ArrayList<>(list); + list.add(new Object[] { clusterStringTemplate, clusterKeyStringFactory, stringFactory, stringRedisSerializer, + "Cluster String" }); + } + + return list; } + + private static boolean clusterAvailable() { + + try { + new RedisClusterRule().apply(new Statement() { + @Override + public void evaluate() throws Throwable { + + } + }, null).evaluate(); + } catch (Throwable throwable) { + return false; + } + return true; + } + } diff --git a/src/test/java/org/springframework/data/redis/core/ReactiveRedisTemplateIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/ReactiveRedisTemplateIntegrationTests.java index 593b3c538..7accbeee8 100644 --- a/src/test/java/org/springframework/data/redis/core/ReactiveRedisTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/ReactiveRedisTemplateIntegrationTests.java @@ -40,13 +40,15 @@ import org.springframework.data.redis.connection.ReactiveRedisClusterConnection; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.ReactiveSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Integration tests for {@link ReactiveRedisTemplate}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(Parameterized.class) public class ReactiveRedisTemplateIntegrationTests { @@ -57,7 +59,7 @@ public class ReactiveRedisTemplateIntegrationTests { private final ObjectFactory valueFactory; - @Parameters(name = "{3}") + @Parameters(name = "{4}") public static Collection testParams() { return ReactiveOperationsTestParams.testParams(); } @@ -74,7 +76,7 @@ public class ReactiveRedisTemplateIntegrationTests { * @param label parameterized test label, no further use besides that. */ public ReactiveRedisTemplateIntegrationTests(ReactiveRedisTemplate redisTemplate, ObjectFactory keyFactory, - ObjectFactory valueFactory, String label) { + ObjectFactory valueFactory, RedisSerializer serializer, String label) { this.redisTemplate = redisTemplate; this.keyFactory = keyFactory; @@ -269,7 +271,7 @@ public class ReactiveRedisTemplateIntegrationTests { Person value = new PersonObjectFactory().instance(); JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(); - ReactiveSerializationContext objectSerializers = ReactiveSerializationContext.builder() + RedisSerializationContext objectSerializers = RedisSerializationContext.newSerializationContext() .key(jdkSerializer) // .value(jdkSerializer) // .hashKey(jdkSerializer) // @@ -286,18 +288,17 @@ public class ReactiveRedisTemplateIntegrationTests { @Test // DATAREDIS-602 public void shouldApplyCustomSerializationContextToHash() { - ReactiveSerializationContext serializationContext = redisTemplate.getSerializationContext(); + RedisSerializationContext serializationContext = redisTemplate.getSerializationContext(); K key = keyFactory.instance(); String hashField = "foo"; Person hashValue = new PersonObjectFactory().instance(); - JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(); - ReactiveSerializationContext objectSerializers = ReactiveSerializationContext. builder() - .key(serializationContext.key()) // - .value(serializationContext.value()) // + RedisSerializationContext objectSerializers = RedisSerializationContext. newSerializationContext() + .key(serializationContext.getKeySerializationPair()) // + .value(serializationContext.getValueSerializationPair()) // .hashKey(new StringRedisSerializer()) // - .hashValue(jdkSerializer) // + .hashValue(new JdkSerializationRedisSerializer()) // .build(); ReactiveHashOperations hashOperations = redisTemplate.opsForHash(objectSerializers); diff --git a/src/test/java/org/springframework/data/redis/repository/cdi/PersonRepository.java b/src/test/java/org/springframework/data/redis/repository/cdi/PersonRepository.java index 287d66c2a..a222b76b2 100644 --- a/src/test/java/org/springframework/data/redis/repository/cdi/PersonRepository.java +++ b/src/test/java/org/springframework/data/redis/repository/cdi/PersonRepository.java @@ -29,5 +29,4 @@ public interface PersonRepository extends CrudRepository, Person List findAll(); List findByName(String name); - } diff --git a/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementReaderUnitTests.java b/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementReaderUnitTests.java new file mode 100644 index 000000000..3d4b4458f --- /dev/null +++ b/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementReaderUnitTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 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 + * + * http://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.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +/** + * Unit tests for {@link DefaultRedisElementReader}. + * + * @author Mark Paluch + */ +public class DefaultRedisElementReaderUnitTests { + + @Test // DATAREDIS-602 + public void shouldDecodeByteBufferCorrectly() { + + String input = "123ü?™"; + byte[] bytes = input.getBytes(StandardCharsets.UTF_8); + + DefaultRedisElementReader reader = new DefaultRedisElementReader<>( + new StringRedisSerializer(StandardCharsets.UTF_8)); + + String result = reader.read(ByteBuffer.wrap(bytes)); + + assertThat(result, is(equalTo(input))); + } + + @Test // DATAREDIS-602 + public void shouldPassThroughByteBufferForAbsentSerializer() { + + ByteBuffer input = ByteBuffer.allocate(1); + + DefaultRedisElementReader reader = new DefaultRedisElementReader<>(null); + + Object result = reader.read(input); + + assertThat(result, is(equalTo(input))); + } +} diff --git a/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementWriterUnitTests.java b/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementWriterUnitTests.java new file mode 100644 index 000000000..2ad31cc6c --- /dev/null +++ b/src/test/java/org/springframework/data/redis/serializer/DefaultRedisElementWriterUnitTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2017 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 + * + * http://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.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +/** + * Unit tests for {@link DefaultRedisElementWriter}. + * + * @author Mark Paluch + */ +public class DefaultRedisElementWriterUnitTests { + + @Test // DATAREDIS-602 + public void shouldSerializeInputCorrectly() { + + String input = "123ü?™"; + byte[] bytes = input.getBytes(StandardCharsets.UTF_8); + + DefaultRedisElementWriter writer = new DefaultRedisElementWriter<>( + new StringRedisSerializer(StandardCharsets.UTF_8)); + + ByteBuffer result = writer.write(input); + + assertThat(result.array(), is(equalTo(bytes))); + } + + @Test // DATAREDIS-602 + public void shouldWrapByteArrayForAbsentSerializer() { + + DefaultRedisElementWriter writer = new DefaultRedisElementWriter<>(null); + + byte[] input = { 1, 2, 3 }; + ByteBuffer result = writer.write(input); + + assertThat(result.array(), is(equalTo(input))); + } + + @Test // DATAREDIS-602 + public void shouldPassThroughByteBufferForAbsentSerializer() { + + DefaultRedisElementWriter writer = new DefaultRedisElementWriter<>(null); + + byte[] input = { 1, 2, 3 }; + ByteBuffer result = writer.write(ByteBuffer.wrap(input)); + + assertThat(result.array(), is(equalTo(input))); + } + + @Test(expected = IllegalStateException.class) // DATAREDIS-602 + public void shouldFailForUnsupportedTypeWithAbsentSerializer() { + + DefaultRedisElementWriter writer = new DefaultRedisElementWriter<>(null); + + writer.write(new Object()); + } +} diff --git a/src/test/java/org/springframework/data/redis/serializer/ReactiveSerializationContextUnitTests.java b/src/test/java/org/springframework/data/redis/serializer/RedisSerializationContextUnitTests.java similarity index 58% rename from src/test/java/org/springframework/data/redis/serializer/ReactiveSerializationContextUnitTests.java rename to src/test/java/org/springframework/data/redis/serializer/RedisSerializationContextUnitTests.java index 3d69d7e0a..77959adbc 100644 --- a/src/test/java/org/springframework/data/redis/serializer/ReactiveSerializationContextUnitTests.java +++ b/src/test/java/org/springframework/data/redis/serializer/RedisSerializationContextUnitTests.java @@ -22,16 +22,17 @@ import java.nio.ByteBuffer; import org.junit.Test; /** - * Unit tests for {@link ReactiveSerializationContext}. + * Unit tests for {@link RedisSerializationContext}. * * @author Mark Paluch + * @author Christoph Strobl */ -public class ReactiveSerializationContextUnitTests { +public class RedisSerializationContextUnitTests { @Test(expected = IllegalArgumentException.class) // DATAREDIS-602 public void shouldRejectBuildIfKeySerializerIsNotSet() { - ReactiveSerializationContext. builder() // + RedisSerializationContext. newSerializationContext() // .value(new StringRedisSerializer()) // .hashKey(new StringRedisSerializer()) // .hashValue(new StringRedisSerializer()) // @@ -41,7 +42,7 @@ public class ReactiveSerializationContextUnitTests { @Test(expected = IllegalArgumentException.class) // DATAREDIS-602 public void shouldRejectBuildIfValueSerializerIsNotSet() { - ReactiveSerializationContext. builder() // + RedisSerializationContext. newSerializationContext() // .key(new StringRedisSerializer()) // .hashKey(new StringRedisSerializer()) // .hashValue(new StringRedisSerializer()) // @@ -51,7 +52,7 @@ public class ReactiveSerializationContextUnitTests { @Test(expected = IllegalArgumentException.class) // DATAREDIS-602 public void shouldRejectBuildIfHashKeySerializerIsNotSet() { - ReactiveSerializationContext. builder() // + RedisSerializationContext. newSerializationContext() // .key(new StringRedisSerializer()) // .value(new StringRedisSerializer()) // .hashValue(new StringRedisSerializer()) // @@ -61,31 +62,40 @@ public class ReactiveSerializationContextUnitTests { @Test(expected = IllegalArgumentException.class) // DATAREDIS-602 public void shouldRejectBuildIfHashValueSerializerIsNotSet() { - ReactiveSerializationContext. builder() // + RedisSerializationContext. newSerializationContext() // .key(new StringRedisSerializer()) // .value(new StringRedisSerializer()) // .hashKey(new StringRedisSerializer()) // .build(); } + @Test // DATAREDIS-602 + public void shouldUseDefaultIfSet() { + + RedisSerializationContext. newSerializationContext(new StringRedisSerializer()) + .key(new GenericToStringSerializer(Long.class))// + .build(); + } + @Test // DATAREDIS-602 public void shouldBuildSerializationContext() { - ReactiveSerializationContext serializationContext = createSerializationContext(); + RedisSerializationContext serializationContext = createSerializationContext(); - assertThat(serializationContext.key()).isNotNull(); - assertThat(serializationContext.value()).isNotNull(); - assertThat(serializationContext.hashKey()).isNotNull(); - assertThat(serializationContext.hashValue()).isNotNull(); - assertThat(serializationContext.string()).isNotNull(); + assertThat(serializationContext.getKeySerializationPair()).isNotNull(); + assertThat(serializationContext.getValueSerializationPair()).isNotNull(); + assertThat(serializationContext.getHashKeySerializationPair()).isNotNull(); + assertThat(serializationContext.getHashValueSerializationPair()).isNotNull(); + assertThat(serializationContext.getStringSerializationPair()).isNotNull(); } @Test // DATAREDIS-602 public void shouldEncodeAndDecodeKey() { - ReactiveSerializationContext serializationContext = createSerializationContext(); + RedisSerializationContext serializationContext = createSerializationContext(); - String deserialized = serializationContext.key().read(serializationContext.key().write("foo")); + String deserialized = serializationContext.getKeySerializationPair() + .read(serializationContext.getKeySerializationPair().write("foo")); assertThat(deserialized).isEqualTo("foo"); } @@ -93,16 +103,17 @@ public class ReactiveSerializationContextUnitTests { @Test // DATAREDIS-602 public void shouldEncodeAndDecodeValue() { - ReactiveSerializationContext serializationContext = createSerializationContext(); + RedisSerializationContext serializationContext = createSerializationContext(); - long deserialized = serializationContext.value().read(serializationContext.value().write(42L)); + long deserialized = serializationContext.getValueSerializationPair() + .read(serializationContext.getValueSerializationPair().write(42L)); assertThat(deserialized).isEqualTo(42); } - private ReactiveSerializationContext createSerializationContext() { + private RedisSerializationContext createSerializationContext() { - return ReactiveSerializationContext. builder() // + return RedisSerializationContext. newSerializationContext() // .key(new StringRedisSerializer()) // .value(ByteBuffer::getLong, value -> (ByteBuffer) ByteBuffer.allocate(8).putLong(value).flip()) // .hashKey(new StringRedisSerializer()) //