diff --git a/src/main/java/org/springframework/data/redis/ExceptionTranslationStrategy.java b/src/main/java/org/springframework/data/redis/ExceptionTranslationStrategy.java index 807829fb5..7ccbf02a3 100644 --- a/src/main/java/org/springframework/data/redis/ExceptionTranslationStrategy.java +++ b/src/main/java/org/springframework/data/redis/ExceptionTranslationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-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. @@ -16,6 +16,7 @@ package org.springframework.data.redis; import org.springframework.dao.DataAccessException; +import org.springframework.lang.Nullable; /** * Potentially translates an {@link Exception} into appropriate {@link DataAccessException}. @@ -28,10 +29,11 @@ public interface ExceptionTranslationStrategy { /** * Potentially translate the given {@link Exception} into {@link DataAccessException}. - * - * @param e - * @return + * + * @param e must not be {@literal null}. + * @return can be {@literal null} if given {@link Exception} cannot be translated. */ + @Nullable DataAccessException translate(Exception e); } diff --git a/src/main/java/org/springframework/data/redis/VersionParser.java b/src/main/java/org/springframework/data/redis/VersionParser.java index f06c02683..ae0663555 100644 --- a/src/main/java/org/springframework/data/redis/VersionParser.java +++ b/src/main/java/org/springframework/data/redis/VersionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-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. @@ -18,6 +18,8 @@ package org.springframework.data.redis; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.lang.Nullable; + /** * Central class for reading version string (eg. {@literal 1.3.1}) into {@link Version}. * @@ -31,10 +33,11 @@ public class VersionParser { /** * Parse version string {@literal eg. 1.1.1} to {@link Version}. * - * @param version - * @return + * @param version can be {@literal null}. + * @return never {@literal null}. */ - public static Version parseVersion(String version) { + public static Version parseVersion(@Nullable String version) { + if (version == null) { return Version.UNKNOWN; } @@ -47,6 +50,7 @@ public class VersionParser { return new Version(Integer.parseInt(major), minor != null ? Integer.parseInt(minor) : 0, patch != null ? Integer.parseInt(patch) : 0); } + return Version.UNKNOWN; } diff --git a/src/main/java/org/springframework/data/redis/cache/DefaultRedisCacheWriter.java b/src/main/java/org/springframework/data/redis/cache/DefaultRedisCacheWriter.java index 13867093b..713a9ef48 100644 --- a/src/main/java/org/springframework/data/redis/cache/DefaultRedisCacheWriter.java +++ b/src/main/java/org/springframework/data/redis/cache/DefaultRedisCacheWriter.java @@ -17,6 +17,8 @@ package org.springframework.data.redis.cache; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.Collections; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; @@ -26,6 +28,7 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -70,17 +73,16 @@ class DefaultRedisCacheWriter implements RedisCacheWriter { this.sleepTime = sleepTime; } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.cache.RedisCacheWriter#put(java.lang.String, byte[], byte[], java.time.Duration) */ @Override - public void put(String name, byte[] key, byte[] value, Duration ttl) { + public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); - Assert.notNull(ttl, "Ttl must not be null!"); execute(name, connection -> { @@ -94,7 +96,7 @@ class DefaultRedisCacheWriter implements RedisCacheWriter { }); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.cache.RedisCacheWriter#get(java.lang.String, byte[]) */ @@ -107,17 +109,16 @@ class DefaultRedisCacheWriter implements RedisCacheWriter { return execute(name, connection -> connection.get(key)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.cache.RedisCacheWriter#putIfAbsent(java.lang.String, byte[], byte[], java.time.Duration) */ @Override - public byte[] putIfAbsent(String name, byte[] key, byte[] value, Duration ttl) { + public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); - Assert.notNull(ttl, "Ttl must not be null!"); return execute(name, connection -> { @@ -178,7 +179,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter { wasLocked = true; } - byte[][] keys = connection.keys(pattern).toArray(new byte[0][]); + byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet()) + .toArray(new byte[0][]); if (keys.length > 0) { connection.del(keys); @@ -275,7 +277,7 @@ class DefaultRedisCacheWriter implements RedisCacheWriter { } } - private static boolean shouldExpireWithin(Duration ttl) { + private static boolean shouldExpireWithin(@Nullable Duration ttl) { return ttl != null && !ttl.isZero() && !ttl.isNegative(); } diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCache.java b/src/main/java/org/springframework/data/redis/cache/RedisCache.java index ba3183175..c0fc359eb 100644 --- a/src/main/java/org/springframework/data/redis/cache/RedisCache.java +++ b/src/main/java/org/springframework/data/redis/cache/RedisCache.java @@ -26,6 +26,7 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.util.ByteUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; @@ -129,7 +130,7 @@ public class RedisCache extends AbstractValueAdaptingCache { * @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object) */ @Override - public void put(Object key, Object value) { + public void put(Object key, @Nullable Object value) { Object cacheValue = preProcessCacheValue(value); @@ -148,7 +149,7 @@ public class RedisCache extends AbstractValueAdaptingCache { * @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object, java.lang.Object) */ @Override - public ValueWrapper putIfAbsent(Object key, Object value) { + public ValueWrapper putIfAbsent(Object key, @Nullable Object value) { Object cacheValue = preProcessCacheValue(value); @@ -202,7 +203,8 @@ public class RedisCache extends AbstractValueAdaptingCache { * @param value can be {@literal null}. * @return preprocessed value. Can be {@literal null}. */ - protected Object preProcessCacheValue(Object value) { + @Nullable + protected Object preProcessCacheValue(@Nullable Object value) { if (value != null) { return value; @@ -242,6 +244,7 @@ public class RedisCache extends AbstractValueAdaptingCache { * @param value must not be {@literal null}. * @return can be {@literal null}. */ + @Nullable protected Object deserializeCacheValue(byte[] value) { if (isAllowNullValues() && ObjectUtils.nullSafeEquals(value, BINARY_NULL_VALUE)) { diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java b/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java index aa347bcee..ff10b5692 100644 --- a/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java +++ b/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -43,7 +44,7 @@ public class RedisCacheConfiguration { private final Duration ttl; private final boolean cacheNullValues; - private final String keyPrefix; + private final @Nullable String keyPrefix; private final boolean usePrefix; private final SerializationPair keySerializationPair; @@ -52,7 +53,7 @@ public class RedisCacheConfiguration { private final ConversionService conversionService; @SuppressWarnings("unchecked") - private RedisCacheConfiguration(Duration ttl, Boolean cacheNullValues, Boolean usePrefix, String keyPrefix, + private RedisCacheConfiguration(Duration ttl, Boolean cacheNullValues, Boolean usePrefix, @Nullable String keyPrefix, SerializationPair keySerializationPair, SerializationPair valueSerializationPair, ConversionService conversionService) { diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCacheManager.java b/src/main/java/org/springframework/data/redis/cache/RedisCacheManager.java index dc778cc09..d6b10749c 100644 --- a/src/main/java/org/springframework/data/redis/cache/RedisCacheManager.java +++ b/src/main/java/org/springframework/data/redis/cache/RedisCacheManager.java @@ -26,6 +26,7 @@ import java.util.Set; import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -205,7 +206,7 @@ public class RedisCacheManager extends AbstractTransactionSupportingCacheManager * @param cacheConfig can be {@literal null}. * @return never {@literal null}. */ - protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { + protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) { return new RedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig); } diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCacheWriter.java b/src/main/java/org/springframework/data/redis/cache/RedisCacheWriter.java index 7f1527f0e..5846a9c3a 100644 --- a/src/main/java/org/springframework/data/redis/cache/RedisCacheWriter.java +++ b/src/main/java/org/springframework/data/redis/cache/RedisCacheWriter.java @@ -18,6 +18,7 @@ package org.springframework.data.redis.cache; import java.time.Duration; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -66,7 +67,7 @@ public interface RedisCacheWriter { * @param value The value stored for the key. Must not be {@literal null}. * @param ttl Optional expiration time. Can be {@literal null}. */ - void put(String name, byte[] key, byte[] value, Duration ttl); + void put(String name, byte[] key, byte[] value, @Nullable Duration ttl); /** * Get the binary value representation from Redis stored for the given key. @@ -75,7 +76,7 @@ public interface RedisCacheWriter { * @param key must not be {@literal null}. * @return {@literal null} if key does not exist. */ - + @Nullable byte[] get(String name, byte[] key); /** @@ -87,7 +88,8 @@ public interface RedisCacheWriter { * @param ttl Optional expiration time. Can be {@literal null}. * @return {@literal null} if the value has been written, the value stored for the key if it already exists. */ - byte[] putIfAbsent(String name, byte[] key, byte[] value, Duration ttl); + @Nullable + byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl); /** * Remove the given key from Redis. diff --git a/src/main/java/org/springframework/data/redis/cache/package-info.java b/src/main/java/org/springframework/data/redis/cache/package-info.java index 14230b11d..c79b7ed9e 100644 --- a/src/main/java/org/springframework/data/redis/cache/package-info.java +++ b/src/main/java/org/springframework/data/redis/cache/package-info.java @@ -1,5 +1,6 @@ /** - * Package providing a Redis implementation for Spring cache abstraction. + * Package providing a Redis implementation for Spring + * cache abstraction. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.cache; - diff --git a/src/main/java/org/springframework/data/redis/config/RedisCollectionParser.java b/src/main/java/org/springframework/data/redis/config/RedisCollectionParser.java index 083148569..417df2c02 100644 --- a/src/main/java/org/springframework/data/redis/config/RedisCollectionParser.java +++ b/src/main/java/org/springframework/data/redis/config/RedisCollectionParser.java @@ -33,6 +33,7 @@ class RedisCollectionParser extends AbstractSimpleBeanDefinitionParser { } protected void postProcess(BeanDefinitionBuilder beanDefinition, Element element) { + String template = element.getAttribute("template"); if (StringUtils.hasText(template)) { beanDefinition.addPropertyReference("template", template); diff --git a/src/main/java/org/springframework/data/redis/config/package-info.java b/src/main/java/org/springframework/data/redis/config/package-info.java new file mode 100644 index 000000000..0c0b3156c --- /dev/null +++ b/src/main/java/org/springframework/data/redis/config/package-info.java @@ -0,0 +1,5 @@ +/** + * Namespace and configuration. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.config; diff --git a/src/main/java/org/springframework/data/redis/connection/AbstractRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/AbstractRedisConnection.java index d8ea1ade3..95d5ac492 100644 --- a/src/main/java/org/springframework/data/redis/connection/AbstractRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/AbstractRedisConnection.java @@ -22,6 +22,8 @@ import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.data.redis.RedisSystemException; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * @author Christoph Strobl @@ -30,7 +32,7 @@ import org.springframework.data.redis.RedisSystemException; */ public abstract class AbstractRedisConnection implements DefaultedRedisConnection { - private RedisSentinelConfiguration sentinelConfiguration; + private @Nullable RedisSentinelConfiguration sentinelConfiguration; private ConcurrentHashMap connectionCache = new ConcurrentHashMap<>(); /* @@ -63,6 +65,8 @@ public abstract class AbstractRedisConnection implements DefaultedRedisConnectio private RedisNode selectActiveSentinel() { + Assert.state(hasRedisSentinelConfigured(), "Sentinel configuration missing!"); + for (RedisNode node : this.sentinelConfiguration.getSentinels()) { if (isActive(node)) { return node; diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java index 194c831ef..a53ba715c 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java @@ -29,6 +29,7 @@ import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.TooManyClusterRedirectionsException; import org.springframework.data.redis.connection.util.ByteArraySet; import org.springframework.data.redis.connection.util.ByteArrayWrapper; +import org.springframework.lang.Nullable; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -73,10 +74,10 @@ public class ClusterCommandExecutor implements DisposableBean { * @param topologyProvider must not be {@literal null}. * @param resourceProvider must not be {@literal null}. * @param exceptionTranslation must not be {@literal null}. - * @param executor can be {@literal null}. + * @param executor can be {@literal null}. Defaulted to {@link ThreadPoolTaskExecutor}. */ public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterNodeResourceProvider resourceProvider, - ExceptionTranslationStrategy exceptionTranslation, AsyncTaskExecutor executor) { + ExceptionTranslationStrategy exceptionTranslation, @Nullable AsyncTaskExecutor executor) { this(topologyProvider, resourceProvider, exceptionTranslation); this.executor = executor; @@ -94,7 +95,7 @@ public class ClusterCommandExecutor implements DisposableBean { * Run {@link ClusterCommandCallback} on a random node. * * @param cmd must not be {@literal null}. - * @return + * @return never {@literal null}. */ public NodeResult executeCommandOnArbitraryNode(ClusterCommandCallback cmd) { @@ -325,6 +326,7 @@ public class ClusterCommandExecutor implements DisposableBean { return this.topologyProvider.getTopology(); } + @Nullable private DataAccessException convertToDataAccessExeption(Exception e) { return exceptionTranslationStrategy.translate(e); } @@ -455,27 +457,27 @@ public class ClusterCommandExecutor implements DisposableBean { public static class NodeResult { private RedisClusterNode node; - private T value; + private @Nullable T value; private ByteArrayWrapper key; /** * Create new {@link NodeResult}. * - * @param node - * @param value + * @param node must not be {@literal null}. + * @param value can be {@literal null}. */ - public NodeResult(RedisClusterNode node, T value) { + public NodeResult(RedisClusterNode node, @Nullable T value) { this(node, value, new byte[] {}); } /** * Create new {@link NodeResult}. * - * @param node - * @param value - * @parm key + * @param node must not be {@literal null}. + * @param value can be {@literal null}. + * @param key must not be {@literal null}. */ - public NodeResult(RedisClusterNode node, T value, byte[] key) { + public NodeResult(RedisClusterNode node, @Nullable T value, byte[] key) { this.node = node; this.value = value; @@ -488,6 +490,7 @@ public class ClusterCommandExecutor implements DisposableBean { * * @return can be {@literal null}. */ + @Nullable public T getValue() { return value; } @@ -557,9 +560,10 @@ public class ClusterCommandExecutor implements DisposableBean { /** * @param returnValue can be {@literal null}. - * @return + * @return can be {@litearl null}. */ - public T getFirstNonNullNotEmptyOrDefault(T returnValue) { + @Nullable + public T getFirstNonNullNotEmptyOrDefault(@Nullable T returnValue) { for (NodeResult nodeResult : nodeResults) { if (nodeResult.getValue() != null) { diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterInfo.java b/src/main/java/org/springframework/data/redis/connection/ClusterInfo.java index 354719b52..7dbff90e8 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterInfo.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-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. @@ -18,6 +18,7 @@ package org.springframework.data.redis.connection; import java.util.Properties; import org.springframework.data.redis.core.types.RedisClientInfo.INFO; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -32,8 +33,8 @@ public class ClusterInfo { public static enum Info { STATE("cluster_state"), SLOTS_ASSIGNED("cluster_slots_assigned"), SLOTS_OK("cluster_slots_ok"), SLOTS_PFAIL( "cluster_slots_pfail"), SLOTS_FAIL("cluster_slots_fail"), KNOWN_NODES("cluster_known_nodes"), SIZE( - "cluster_size"), CURRENT_EPOCH("cluster_current_epoch"), MY_EPOCH("cluster_my_epoch"), MESSAGES_SENT( - "cluster_stats_messages_sent"), MESSAGES_RECEIVED("cluster_stats_messages_received"); + "cluster_size"), CURRENT_EPOCH("cluster_current_epoch"), MY_EPOCH("cluster_my_epoch"), MESSAGES_SENT( + "cluster_stats_messages_sent"), MESSAGES_RECEIVED("cluster_stats_messages_received"); String key; @@ -57,80 +58,90 @@ public class ClusterInfo { /** * @see Info#STATE - * @return + * @return {@literal null} if no entry found for requested {@link Info#STATE}. */ + @Nullable public String getState() { return get(Info.STATE); } /** * @see Info#SLOTS_ASSIGNED - * @return + * @return {@literal null} if no entry found for requested {@link Info#SLOTS_ASSIGNED}. */ + @Nullable public Long getSlotsAssigned() { return getLongValueOf(Info.SLOTS_ASSIGNED); } /** * @see Info#SLOTS_OK - * @return + * @return {@literal null} if no entry found for requested {@link Info#SLOTS_OK}. */ + @Nullable public Long getSlotsOk() { return getLongValueOf(Info.SLOTS_OK); } /** * @see Info#SLOTS_PFAIL - * @return + * @return {@literal null} if no entry found for requested {@link Info#SLOTS_PFAIL}. */ + @Nullable public Long getSlotsPfail() { return getLongValueOf(Info.SLOTS_PFAIL); } /** * @see Info#SLOTS_FAIL - * @return + * @return {@literal null} if no entry found for requested {@link Info#SLOTS_FAIL}. */ + @Nullable public Long getSlotsFail() { return getLongValueOf(Info.SLOTS_FAIL); } /** * @see Info#KNOWN_NODES - * @return + * @return {@literal null} if no entry found for requested {@link Info#KNOWN_NODES}. */ + @Nullable public Long getKnownNodes() { return getLongValueOf(Info.KNOWN_NODES); } /** * @see Info#SIZE - * @return + * @return {@literal null} if no entry found for requested {@link Info#SIZE}. */ + @Nullable public Long getClusterSize() { return getLongValueOf(Info.SIZE); } /** * @see Info#CURRENT_EPOCH - * @return + * @return {@literal null} if no entry found for requested {@link Info#CURRENT_EPOCH}. */ + @Nullable public Long getCurrentEpoch() { return getLongValueOf(Info.CURRENT_EPOCH); } /** * @see Info#MESSAGES_SENT - * @return + * @return {@literal null} if no entry found for requested {@link Info#MESSAGES_SENT}. */ + @Nullable public Long getMessagesSent() { return getLongValueOf(Info.MESSAGES_SENT); } /** * @see Info#MESSAGES_RECEIVED - * @return + * @return {@literal null} if no entry found for requested {@link Info#MESSAGES_RECEIVED}. */ + @Nullable public Long getMessagesReceived() { return getLongValueOf(Info.MESSAGES_RECEIVED); } @@ -139,6 +150,7 @@ public class ClusterInfo { * @param info must not be null * @return {@literal null} if no entry found for requested {@link INFO}. */ + @Nullable public String get(Info info) { Assert.notNull(info, "Cannot retrieve cluster information for 'null'."); @@ -149,12 +161,14 @@ public class ClusterInfo { * @param key must not be {@literal null} or {@literal empty}. * @return {@literal null} if no entry found for requested {@code key}. */ + @Nullable public String get(String key) { Assert.hasText(key, "Cannot get cluster information for 'empty' / 'null' key."); return this.clusterProperties.getProperty(key); } + @Nullable private Long getLongValueOf(Info info) { String value = get(info); diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterNodeResourceProvider.java b/src/main/java/org/springframework/data/redis/connection/ClusterNodeResourceProvider.java index 379b74b9d..ce5e9a796 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterNodeResourceProvider.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterNodeResourceProvider.java @@ -28,7 +28,8 @@ public interface ClusterNodeResourceProvider { * Get the client resource for the given node. * * @param node must not be {@literal null}. - * @return + * @return never {@literal null}. + * @throws org.springframework.dao.DataAccessResourceFailureException if node is not known to the cluster. */ S getResourceForSpecificNode(RedisClusterNode node); diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java b/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java index be689a997..7366138c7 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java @@ -20,6 +20,7 @@ import java.util.LinkedHashSet; import java.util.Set; import org.springframework.data.redis.ClusterStateFailureException; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -39,7 +40,7 @@ public class ClusterTopology { * * @param nodes can be {@literal null}. */ - public ClusterTopology(Set nodes) { + public ClusterTopology(@Nullable Set nodes) { this.nodes = nodes != null ? nodes : Collections.emptySet(); } @@ -153,7 +154,7 @@ public class ClusterTopology { public RedisClusterNode lookup(String host, int port) { for (RedisClusterNode node : nodes) { - if (host.equals(node.getHost()) && port == node.getPort()) { + if (host.equals(node.getHost()) && (node.getPort() != null && port == node.getPort())) { return node; } } @@ -199,7 +200,7 @@ public class ClusterTopology { return node; } - if (StringUtils.hasText(node.getHost())) { + if (StringUtils.hasText(node.getHost()) && node.getPort() != null) { return lookup(node.getHost(), node.getPort()); } diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterTopologyProvider.java b/src/main/java/org/springframework/data/redis/connection/ClusterTopologyProvider.java index b3fb569d4..74279ed45 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterTopologyProvider.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterTopologyProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-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. @@ -17,7 +17,7 @@ package org.springframework.data.redis.connection; /** * {@link ClusterTopologyProvider} manages the current cluster topology and makes sure to refresh cluster information. - * + * * @author Christoph Strobl * @since 1.7 */ @@ -25,7 +25,7 @@ public interface ClusterTopologyProvider { /** * Get the current known {@link ClusterTopology}. - * + * * @return never {@null}. */ ClusterTopology getTopology(); diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java b/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java index 946728c5f..1e3d731db 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -15,31 +15,44 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + /** * Default message implementation. * * @author Costin Leau + * @author Christoph Strobl */ public class DefaultMessage implements Message { private final byte[] channel; private final byte[] body; - private String toString; + private @Nullable String toString; public DefaultMessage(byte[] channel, byte[] body) { + + Assert.notNull(channel, "Channel must not be null!"); + Assert.notNull(body, "Body must not be null!"); + this.body = body; this.channel = channel; } + /** + * @return + */ public byte[] getChannel() { - return (channel != null ? channel.clone() : null); + return channel.clone(); } public byte[] getBody() { - return (body != null ? body.clone() : null); + return body.clone(); } + @Override public String toString() { + if (toString == null) { toString = new String(body); } diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 93abfec78..6cefa04d0 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -48,6 +48,7 @@ import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -3242,8 +3243,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco @Override public Cursor> hScan(String key, ScanOptions options) { - return new ConvertingCursor<>( - this.delegate.hScan(this.serialize(key), options), + return new ConvertingCursor<>(this.delegate.hScan(this.serialize(key), options), source -> new Entry() { @Override @@ -3278,8 +3278,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco */ @Override public Cursor zScan(String key, ScanOptions options) { - return new ConvertingCursor<>(delegate.zScan(this.serialize(key), options), - new TupleConverter()); + return new ConvertingCursor<>(delegate.zScan(this.serialize(key), options), new TupleConverter()); } /* @@ -3440,7 +3439,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option) { delegate.migrate(key, target, dbIndex, option); } @@ -3449,7 +3448,7 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, long timeout) { delegate.migrate(key, target, dbIndex, option, timeout); } @@ -3467,10 +3466,13 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco private T convertAndReturn(Object value, Converter converter) { if (isFutureConversion()) { + addResultConverter(converter); + return null; } - return ObjectUtils.nullSafeEquals(converter, identityConverter) ? (T) value : (T) converter.convert(value); + + return value == null ? null : ObjectUtils.nullSafeEquals(converter, identityConverter) ? (T) value : (T) converter.convert(value); } private void addResultConverter(Converter converter) { @@ -3497,7 +3499,9 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco } List convertedResults = new ArrayList<>(results.size()); for (Object result : results) { - convertedResults.add(converters.remove().convert(result)); + + Converter converter = converters.remove(); + convertedResults.add(result == null ? null : converter.convert(result)); } return convertedResults; } diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultTuple.java b/src/main/java/org/springframework/data/redis/connection/DefaultTuple.java index de2fd984f..bf52849f2 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultTuple.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultTuple.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -21,8 +21,9 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; /** * Default implementation for {@link Tuple} interface. - * + * * @author Costin Leau + * @author Christoph Strobl */ public class DefaultTuple implements Tuple { @@ -36,14 +37,23 @@ public class DefaultTuple implements Tuple { * @param score */ public DefaultTuple(byte[] value, Double score) { + this.score = score; this.value = value; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisZSetCommands.Tuple#getScore() + */ public Double getScore() { return score; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisZSetCommands.Tuple#getValue() + */ public byte[] getValue() { return value; } diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java index 60b89aa8f..8de0c63d3 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java @@ -31,6 +31,7 @@ import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.lang.Nullable; /** * {@link DefaultedRedisConnection} provides method delegates to {@code Redis*Command} interfaces accessible via @@ -1184,14 +1185,14 @@ public interface DefaultedRedisConnection extends RedisConnection { /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ @Override @Deprecated - default void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + default void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option) { serverCommands().migrate(key, target, dbIndex, option); } /** @deprecated in favor of {@link RedisConnection#serverCommands()}. */ @Override @Deprecated - default void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + default void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, long timeout) { serverCommands().migrate(key, target, dbIndex, option, timeout); } diff --git a/src/main/java/org/springframework/data/redis/connection/FutureResult.java b/src/main/java/org/springframework/data/redis/connection/FutureResult.java index 431ae5b28..704b5fa52 100644 --- a/src/main/java/org/springframework/data/redis/connection/FutureResult.java +++ b/src/main/java/org/springframework/data/redis/connection/FutureResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -16,11 +16,13 @@ package org.springframework.data.redis.connection; import org.springframework.core.convert.converter.Converter; +import org.springframework.lang.Nullable; /** * The result of an asynchronous operation * * @author Jennifer Hickey + * @author Christoph Strobl * @param The data type of the object that holds the future result (usually of type Future) */ abstract public class FutureResult { @@ -29,7 +31,8 @@ abstract public class FutureResult { protected boolean status = false; - @SuppressWarnings("rawtypes") protected Converter converter; + @SuppressWarnings("rawtypes") // + protected @Nullable Converter converter; public FutureResult(T resultHolder) { this.resultHolder = resultHolder; @@ -48,18 +51,22 @@ abstract public class FutureResult { /** * Converts the given result if a converter is specified, else returns the result * - * @param result The result to convert - * @return The converted result + * @param result The result to convert. Can be {@literal null}. + * @return The converted result or {@literal null}. */ @SuppressWarnings("unchecked") - public Object convert(Object result) { - if (converter != null) { - return converter.convert(result); + @Nullable + public Object convert(@Nullable Object result) { + + if (result == null) { + return null; } - return result; + + return (converter != null) ? converter.convert(result) : result; } @SuppressWarnings("rawtypes") + @Nullable public Converter getConverter() { return converter; } @@ -81,7 +88,8 @@ abstract public class FutureResult { } /** - * @return The result of the operation + * @return The result of the operation. Can be {@literal null}. */ + @Nullable abstract public Object get(); } diff --git a/src/main/java/org/springframework/data/redis/connection/Message.java b/src/main/java/org/springframework/data/redis/connection/Message.java index 1547fb1f6..bfea26a58 100644 --- a/src/main/java/org/springframework/data/redis/connection/Message.java +++ b/src/main/java/org/springframework/data/redis/connection/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -17,24 +17,27 @@ package org.springframework.data.redis.connection; import java.io.Serializable; +import org.springframework.lang.Nullable; + /** * Class encapsulating a Redis message body and its properties. - * + * * @author Costin Leau + * @author Christoph Strobl */ public interface Message extends Serializable { /** * Returns the body (or the payload) of the message. - * - * @return message body + * + * @return message body. Never {@literal null}. */ byte[] getBody(); /** * Returns the channel associated with the message. - * - * @return message channel. + * + * @return message channel. Never {@literal null}. */ byte[] getChannel(); } diff --git a/src/main/java/org/springframework/data/redis/connection/MessageListener.java b/src/main/java/org/springframework/data/redis/connection/MessageListener.java index b51729340..41811f850 100644 --- a/src/main/java/org/springframework/data/redis/connection/MessageListener.java +++ b/src/main/java/org/springframework/data/redis/connection/MessageListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -15,18 +15,21 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * Listener of messages published in Redis. - * + * * @author Costin Leau + * @author Christoph Strobl */ public interface MessageListener { /** * Callback for processing received objects through Redis. - * - * @param message message - * @param pattern pattern matching the channel (if specified) - can be null + * + * @param message message must not be {@literal null}. + * @param pattern pattern matching the channel (if specified) - can be {@literal null}. */ - void onMessage(Message message, byte[] pattern); + void onMessage(Message message, @Nullable byte[] pattern); } diff --git a/src/main/java/org/springframework/data/redis/connection/NamedNode.java b/src/main/java/org/springframework/data/redis/connection/NamedNode.java index e5c0be670..c4f069c6b 100644 --- a/src/main/java/org/springframework/data/redis/connection/NamedNode.java +++ b/src/main/java/org/springframework/data/redis/connection/NamedNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-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. @@ -15,11 +15,17 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * @author Christoph Strobl * @since 1.4 */ public interface NamedNode { + /** + * @return the node name. Can be {@literal null}. + */ + @Nullable String getName(); } diff --git a/src/main/java/org/springframework/data/redis/connection/PoolException.java b/src/main/java/org/springframework/data/redis/connection/PoolException.java index a8abd7168..acc09f724 100644 --- a/src/main/java/org/springframework/data/redis/connection/PoolException.java +++ b/src/main/java/org/springframework/data/redis/connection/PoolException.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -16,27 +16,30 @@ package org.springframework.data.redis.connection; import org.springframework.core.NestedRuntimeException; +import org.springframework.lang.Nullable; /** * Exception thrown when there are issues with a resource pool * * @author Jennifer Hickey + * @author Christoph Strobl */ @SuppressWarnings("serial") public class PoolException extends NestedRuntimeException { + /** * Constructs a new PoolException instance. - * + * * @param msg * @param cause */ - public PoolException(String msg, Throwable cause) { + public PoolException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } /** * Constructs a new PoolException instance. - * + * * @param msg */ public PoolException(String msg) { diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java index ce897c46b..4aafb1fb3 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java @@ -41,6 +41,7 @@ import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs; import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.Flag; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -62,7 +63,7 @@ public interface ReactiveGeoCommands { private final List> geoLocations; - private GeoAddCommand(ByteBuffer key, List> geoLocations) { + private GeoAddCommand(@Nullable ByteBuffer key, List> geoLocations) { super(key); @@ -184,7 +185,8 @@ public interface ReactiveGeoCommands { private final ByteBuffer to; private final Metric metric; - private GeoDistCommand(ByteBuffer key, ByteBuffer from, ByteBuffer to, Metric metric) { + private GeoDistCommand(@Nullable ByteBuffer key, @Nullable ByteBuffer from, @Nullable ByteBuffer to, + Metric metric) { super(key); @@ -274,21 +276,23 @@ public interface ReactiveGeoCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getFrom() { return from; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getTo() { return to; } /** - * @return + * @return never {@literal null}. */ public Optional getMetric() { return Optional.ofNullable(metric); @@ -305,7 +309,7 @@ public interface ReactiveGeoCommands { * @see Redis Documentation: GEODIST */ default Mono geoDist(ByteBuffer key, ByteBuffer from, ByteBuffer to) { - return geoDist(key, from, to, null); + return geoDist(key, from, to, DistanceUnit.METERS); } /** @@ -314,7 +318,7 @@ public interface ReactiveGeoCommands { * @param key must not be {@literal null}. * @param from must not be {@literal null}. * @param to must not be {@literal null}. - * @param metric can be {@literal null} and defaults to {@link DistanceUnit#METERS}. + * @param metric must not be {@literal null}. * @return * @see Redis Documentation: GEODIST */ @@ -323,6 +327,7 @@ public interface ReactiveGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(from, "From must not be null!"); Assert.notNull(to, "To must not be null!"); + Assert.notNull(metric, "Metric must not be null!"); return geoDist(Mono.just(GeoDistCommand.units(metric).between(from).and(to).forKey(key))) // .next() // @@ -348,7 +353,7 @@ public interface ReactiveGeoCommands { private final List members; - private GeoHashCommand(ByteBuffer key, List members) { + private GeoHashCommand(@Nullable ByteBuffer key, List members) { super(key); @@ -395,7 +400,7 @@ public interface ReactiveGeoCommands { } /** - * @return + * @return never {@literal null}. */ public List getMembers() { return members; @@ -455,7 +460,7 @@ public interface ReactiveGeoCommands { private final List members; - private GeoPosCommand(ByteBuffer key, List members) { + private GeoPosCommand(@Nullable ByteBuffer key, List members) { super(key); @@ -502,7 +507,7 @@ public interface ReactiveGeoCommands { } /** - * @return + * @return never {@literal null}. */ public List getMembers() { return members; @@ -559,19 +564,19 @@ public interface ReactiveGeoCommands { class GeoRadiusCommand extends KeyCommand { private final Distance distance; - private final Point point; + private final @Nullable Point point; private final GeoRadiusCommandArgs args; - private final ByteBuffer store; - private final ByteBuffer storeDist; + private final @Nullable ByteBuffer store; + private final @Nullable ByteBuffer storeDist; - private GeoRadiusCommand(ByteBuffer key, Point point, Distance distance, GeoRadiusCommandArgs args, - ByteBuffer store, ByteBuffer storeDist) { + private GeoRadiusCommand(@Nullable ByteBuffer key, @Nullable Point point, Distance distance, + GeoRadiusCommandArgs args, @Nullable ByteBuffer store, @Nullable ByteBuffer storeDist) { super(key); this.distance = distance; this.point = point; - this.args = args == null ? GeoRadiusCommandArgs.newGeoRadiusArgs() : args; + this.args = args; this.store = store; this.storeDist = storeDist; } @@ -586,7 +591,7 @@ public interface ReactiveGeoCommands { Assert.notNull(distance, "Distance must not be null!"); - return new GeoRadiusCommand(null, null, distance, null, null, null); + return new GeoRadiusCommand(null, null, distance, GeoRadiusCommandArgs.newGeoRadiusArgs(), null, null); } /** @@ -694,11 +699,14 @@ public interface ReactiveGeoCommands { * Applies command {@link GeoRadiusCommandArgs}. Constructs a new command instance with all previously configured * properties. * - * @param args can be {@literal null}. + * @param args must not be {@literal null}. * @return a new {@link GeoRadiusCommand} with {@link GeoRadiusCommandArgs} applied. */ public GeoRadiusCommand withArgs(GeoRadiusCommandArgs args) { - return new GeoRadiusCommand(getKey(), point, distance, args, store, storeDist); + + Assert.notNull(args, "Args must not be null!"); + return new GeoRadiusCommand(getKey(), point, distance, + args == null ? GeoRadiusCommandArgs.newGeoRadiusArgs() : args, store, storeDist); } /** @@ -766,74 +774,79 @@ public interface ReactiveGeoCommands { /** * NOTE: STORE option is not compatible with WITHDIST, WITHHASH and WITHCOORDS options. * - * @param key - * @return + * @param key must not be {@literal null}. + * @return new instance of {@link GeoRadiusCommand}. */ public GeoRadiusCommand storeAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); return new GeoRadiusCommand(getKey(), point, distance, args, key, storeDist); } /** * NOTE: STOREDIST option is not compatible with WITHDIST, WITHHASH and WITHCOORDS options. * - * @param key - * @return + * @param key must not be {@literal null}. + * @return new instance of {@link GeoRadiusCommand}. */ - public GeoRadiusCommand storeDistAt(ByteBuffer key) { + public GeoRadiusCommand storeDistAt(@Nullable ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); return new GeoRadiusCommand(getKey(), point, distance, args, store, key); } /** - * @return + * @return never {@literal null}. */ public Optional getDirection() { return Optional.ofNullable(args.getSortDirection()); } /** - * @return + * @return never {@literal null}. */ public Distance getDistance() { return distance; } /** - * @return + * @return never {@literal null}. */ public Set getFlags() { return args.getFlags(); } /** - * @return + * @return never {@literal null}. */ public Optional getLimit() { return Optional.ofNullable(args.getLimit()); } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Point getPoint() { return point; } /** - * @return + * @return never {@literal null}. */ public Optional getStore() { return Optional.ofNullable(store); } /** - * @return + * @return never {@literal null}. */ public Optional getStoreDist() { return Optional.ofNullable(storeDist); } /** - * @return + * @return never {@literal null}. */ public Optional getArgs() { return Optional.ofNullable(args); @@ -858,7 +871,7 @@ public interface ReactiveGeoCommands { * @see Redis Documentation: GEORADIUS */ default Flux>> geoRadius(ByteBuffer key, Circle circle) { - return geoRadius(key, circle, null); + return geoRadius(key, circle, GeoRadiusCommandArgs.newGeoRadiusArgs()); } /** @@ -866,7 +879,7 @@ public interface ReactiveGeoCommands { * * @param key must not be {@literal null}. * @param circle must not be {@literal null}. - * @param geoRadiusArgs can be {@literal null}. + * @param geoRadiusArgs must not be {@literal null}. * @return * @see Redis Documentation: GEORADIUS */ @@ -875,6 +888,7 @@ public interface ReactiveGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(circle, "Circle must not be null!"); + Assert.notNull(geoRadiusArgs, "GeoRadiusArgs must not be null!"); return geoRadius(Mono.just(GeoRadiusCommand.within(circle).withArgs(geoRadiusArgs).forKey(key))) .flatMap(CommandResponse::getOutput); @@ -899,19 +913,19 @@ public interface ReactiveGeoCommands { class GeoRadiusByMemberCommand extends KeyCommand { private final Distance distance; - private final ByteBuffer member; + private final @Nullable ByteBuffer member; private final GeoRadiusCommandArgs args; - private final ByteBuffer store; - private final ByteBuffer storeDist; + private final @Nullable ByteBuffer store; + private final @Nullable ByteBuffer storeDist; - private GeoRadiusByMemberCommand(ByteBuffer key, ByteBuffer member, Distance distance, GeoRadiusCommandArgs args, - ByteBuffer store, ByteBuffer storeDist) { + private GeoRadiusByMemberCommand(@Nullable ByteBuffer key, @Nullable ByteBuffer member, Distance distance, + GeoRadiusCommandArgs args, @Nullable ByteBuffer store, @Nullable ByteBuffer storeDist) { super(key); this.distance = distance; this.member = member; - this.args = args == null ? GeoRadiusCommandArgs.newGeoRadiusArgs() : args; + this.args = args; this.store = store; this.storeDist = storeDist; } @@ -1020,11 +1034,12 @@ public interface ReactiveGeoCommands { * Applies command {@link GeoRadiusCommandArgs}. Constructs a new command instance with all previously configured * properties. * - * @param args can be {@literal null}. + * @param args must not be {@literal null}. * @return a new {@link GeoRadiusByMemberCommand} with {@link GeoRadiusCommandArgs} applied. */ public GeoRadiusByMemberCommand withArgs(GeoRadiusCommandArgs args) { + Assert.notNull(args, "Args must not be null!"); return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); } @@ -1084,80 +1099,87 @@ public interface ReactiveGeoCommands { * @return a new {@link GeoRadiusByMemberCommand} with {@literal key} applied. */ public GeoRadiusByMemberCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); return new GeoRadiusByMemberCommand(key, member, distance, args, store, storeDist); } /** * NOTE: STORE option is not compatible with WITHDIST, WITHHASH and WITHCOORDS options. * - * @param key - * @return + * @param key must not be {@literal null}. + * @return new instance of {@link GeoRadiusByMemberCommand}. */ public GeoRadiusByMemberCommand storeAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); return new GeoRadiusByMemberCommand(getKey(), member, distance, args, key, storeDist); } /** * NOTE: STOREDIST option is not compatible with WITHDIST, WITHHASH and WITHCOORDS options. * - * @param key - * @return + * @param key must not be {@literal null}. + * @return new instance of {@link GeoRadiusByMemberCommand}. */ public GeoRadiusByMemberCommand storeDistAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, key); } /** - * @return + * @return never {@literal null}. */ public Optional getDirection() { return Optional.ofNullable(args.getSortDirection()); } /** - * @return + * @return never {@literal null}. */ public Distance getDistance() { return distance; } /** - * @return + * @return never {@literal null}. */ public Set getFlags() { return args.getFlags(); } /** - * @return + * @return never {@literal null}. */ public Optional getLimit() { return Optional.ofNullable(args.getLimit()); } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getMember() { return member; } /** - * @return + * @return never {@literal null}. */ public Optional getStore() { return Optional.ofNullable(store); } /** - * @return + * @return never {@literal null}. */ public Optional getStoreDist() { return Optional.ofNullable(storeDist); } /** - * @return + * @return never {@literal null}. */ public Optional getArgs() { return Optional.ofNullable(args); @@ -1183,7 +1205,7 @@ public interface ReactiveGeoCommands { */ default Flux>> geoRadiusByMember(ByteBuffer key, ByteBuffer member, Distance distance) { - return geoRadiusByMember(key, member, distance, null); + return geoRadiusByMember(key, member, distance, GeoRadiusCommandArgs.newGeoRadiusArgs()); } /** @@ -1191,7 +1213,7 @@ public interface ReactiveGeoCommands { * * @param key must not be {@literal null}. * @param member must not be {@literal null}. - * @param geoRadiusArgs can be {@literal null}. + * @param geoRadiusArgs must not be {@literal null}. * @return * @see Redis Documentation: GEORADIUSBYMEMBER */ @@ -1201,6 +1223,7 @@ public interface ReactiveGeoCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(member, "Member must not be null!"); Assert.notNull(distance, "Distance must not be null!"); + Assert.notNull(geoRadiusArgs, "GeoRadiusArgs must not be null!"); return geoRadiusByMember( Mono.just(GeoRadiusByMemberCommand.within(distance).from(member).forKey(key).withArgs(geoRadiusArgs))) diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java index bac54a669..03979020d 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java @@ -33,6 +33,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Command import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -56,7 +57,7 @@ public interface ReactiveHashCommands { private final Map fieldValueMap; private final boolean upsert; - private HSetCommand(ByteBuffer key, Map keyValueMap, boolean upsert) { + private HSetCommand(@Nullable ByteBuffer key, Map keyValueMap, boolean upsert) { super(key); @@ -137,7 +138,7 @@ public interface ReactiveHashCommands { } /** - * @return + * @return never {@literal null}. */ public Map getFieldValueMap() { return fieldValueMap; @@ -217,7 +218,7 @@ public interface ReactiveHashCommands { private List fields; - private HGetCommand(ByteBuffer key, List fields) { + private HGetCommand(@Nullable ByteBuffer key, List fields) { super(key); @@ -264,7 +265,7 @@ public interface ReactiveHashCommands { } /** - * @return + * @return never {@literal null}. */ public List getFields() { return fields; @@ -318,7 +319,7 @@ public interface ReactiveHashCommands { private final ByteBuffer field; - private HExistsCommand(ByteBuffer key, ByteBuffer field) { + private HExistsCommand(@Nullable ByteBuffer key, ByteBuffer field) { super(key); @@ -352,7 +353,7 @@ public interface ReactiveHashCommands { } /** - * @return + * @return never {@literal null}. */ public ByteBuffer getField() { return field; @@ -392,7 +393,7 @@ public interface ReactiveHashCommands { private final List fields; - private HDelCommand(ByteBuffer key, List fields) { + private HDelCommand(@Nullable ByteBuffer key, List fields) { super(key); @@ -439,7 +440,7 @@ public interface ReactiveHashCommands { } /** - * @return + * @return never {@literal null}. */ public List getFields() { return fields; diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java index ab6bf52c2..306c15de8 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java @@ -29,6 +29,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Command import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -125,9 +126,9 @@ public interface ReactiveKeyCommands { */ class RenameCommand extends KeyCommand { - private ByteBuffer newName; + private @Nullable ByteBuffer newName; - private RenameCommand(ByteBuffer key, ByteBuffer newName) { + private RenameCommand(ByteBuffer key, @Nullable ByteBuffer newName) { super(key); @@ -161,8 +162,9 @@ public interface ReactiveKeyCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getNewName() { return newName; } @@ -271,9 +273,9 @@ public interface ReactiveKeyCommands { */ class ExpireCommand extends KeyCommand { - private Duration timeout; + private @Nullable Duration timeout; - private ExpireCommand(ByteBuffer key, Duration timeout) { + private ExpireCommand(ByteBuffer key, @Nullable Duration timeout) { super(key); @@ -307,8 +309,9 @@ public interface ReactiveKeyCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Duration getTimeout() { return timeout; } @@ -375,9 +378,9 @@ public interface ReactiveKeyCommands { */ class ExpireAtCommand extends KeyCommand { - private Instant expireAt; + private @Nullable Instant expireAt; - private ExpireAtCommand(ByteBuffer key, Instant expireAt) { + private ExpireAtCommand(ByteBuffer key, @Nullable Instant expireAt) { super(key); @@ -411,8 +414,9 @@ public interface ReactiveKeyCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Instant getExpireAt() { return expireAt; } @@ -547,9 +551,9 @@ public interface ReactiveKeyCommands { */ class MoveCommand extends KeyCommand { - private Integer database; + private @Nullable Integer database; - private MoveCommand(ByteBuffer key, Integer database) { + private MoveCommand(ByteBuffer key, @Nullable Integer database) { super(key); @@ -581,8 +585,9 @@ public interface ReactiveKeyCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Integer getDatabase() { return database; } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java index 5341969ae..64125b7a4 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java @@ -33,6 +33,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyComm import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.RangeCommand; import org.springframework.data.redis.connection.RedisListCommands.Position; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -65,7 +66,7 @@ public interface ReactiveListCommands { private boolean upsert; private Direction direction; - private PushCommand(ByteBuffer key, List values, Direction direction, boolean upsert) { + private PushCommand(@Nullable ByteBuffer key, List values, Direction direction, boolean upsert) { super(key); @@ -80,7 +81,7 @@ public interface ReactiveListCommands { * @return a new {@link PushCommand} for right push ({@literal RPUSH}). */ public static PushCommand right() { - return new PushCommand(null, null, Direction.RIGHT, true); + return new PushCommand(null, Collections.emptyList(), Direction.RIGHT, true); } /** @@ -89,7 +90,7 @@ public interface ReactiveListCommands { * @return a new {@link PushCommand} for left push ({@literal LPUSH}). */ public static PushCommand left() { - return new PushCommand(null, null, Direction.LEFT, true); + return new PushCommand(null, Collections.emptyList(), Direction.LEFT, true); } /** @@ -141,7 +142,7 @@ public interface ReactiveListCommands { } /** - * @return + * @return never {@literal null}. */ public List getValues() { return values; @@ -155,7 +156,7 @@ public interface ReactiveListCommands { } /** - * @return + * @return never {@literal null}. */ public Direction getDirection() { return direction; @@ -321,7 +322,7 @@ public interface ReactiveListCommands { private final Long index; - private LIndexCommand(ByteBuffer key, Long index) { + private LIndexCommand(@Nullable ByteBuffer key, Long index) { super(key); this.index = index; @@ -390,11 +391,12 @@ public interface ReactiveListCommands { */ class LInsertCommand extends KeyCommand { - private final Position position; - private final ByteBuffer pivot; + private final @Nullable Position position; + private final @Nullable ByteBuffer pivot; private final ByteBuffer value; - private LInsertCommand(ByteBuffer key, Position position, ByteBuffer pivot, ByteBuffer value) { + private LInsertCommand(@Nullable ByteBuffer key, @Nullable Position position, @Nullable ByteBuffer pivot, + ByteBuffer value) { super(key); @@ -456,22 +458,24 @@ public interface ReactiveListCommands { } /** - * @return + * @return never {@literal null}. */ public ByteBuffer getValue() { return value; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Position getPosition() { return position; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getPivot() { return pivot; } @@ -520,9 +524,9 @@ public interface ReactiveListCommands { class LSetCommand extends KeyCommand { private final Long index; - private final ByteBuffer value; + private final @Nullable ByteBuffer value; - private LSetCommand(ByteBuffer key, Long index, ByteBuffer value) { + private LSetCommand(@Nullable ByteBuffer key, Long index, @Nullable ByteBuffer value) { super(key); this.index = index; @@ -566,14 +570,15 @@ public interface ReactiveListCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getValue() { return value; } /** - * @return + * @return never {@literal null}. */ public Long getIndex() { return index; @@ -615,9 +620,9 @@ public interface ReactiveListCommands { class LRemCommand extends KeyCommand { private final Long count; - private final ByteBuffer value; + private final @Nullable ByteBuffer value; - private LRemCommand(ByteBuffer key, Long count, ByteBuffer value) { + private LRemCommand(@Nullable ByteBuffer key, Long count, @Nullable ByteBuffer value) { super(key); @@ -681,15 +686,16 @@ public interface ReactiveListCommands { } /** - * @return + * @return never {@literal null}. */ public Long getCount() { return count; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getValue() { return value; } @@ -751,7 +757,7 @@ public interface ReactiveListCommands { private final Direction direction; - private PopCommand(ByteBuffer key, Direction direction) { + private PopCommand(@Nullable ByteBuffer key, Direction direction) { super(key); @@ -790,7 +796,7 @@ public interface ReactiveListCommands { } /** - * @return + * @return never {@literal null}. */ public Direction getDirection() { return direction; @@ -859,7 +865,7 @@ public interface ReactiveListCommands { * @return a new {@link BPopCommand} for right push ({@literal BRPOP}). */ public static BPopCommand right() { - return new BPopCommand(null, Duration.ZERO, Direction.RIGHT); + return new BPopCommand(Collections.emptyList(), Duration.ZERO, Direction.RIGHT); } /** @@ -868,7 +874,7 @@ public interface ReactiveListCommands { * @return a new {@link BPopCommand} for right push ({@literal BLPOP}). */ public static BPopCommand left() { - return new BPopCommand(null, Duration.ZERO, Direction.LEFT); + return new BPopCommand(Collections.emptyList(), Duration.ZERO, Direction.LEFT); } /** @@ -959,7 +965,6 @@ public interface ReactiveListCommands { * @author Christoph Strobl */ class PopResponse extends CommandResponse { - public PopResponse(BPopCommand input, PopResult output) { super(input, output); } @@ -1019,9 +1024,9 @@ public interface ReactiveListCommands { */ class RPopLPushCommand extends KeyCommand { - private final ByteBuffer destination; + private final @Nullable ByteBuffer destination; - private RPopLPushCommand(ByteBuffer key, ByteBuffer destination) { + private RPopLPushCommand(ByteBuffer key, @Nullable ByteBuffer destination) { super(key); this.destination = destination; @@ -1055,8 +1060,9 @@ public interface ReactiveListCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getDestination() { return destination; } @@ -1098,10 +1104,10 @@ public interface ReactiveListCommands { */ class BRPopLPushCommand extends KeyCommand { - private final ByteBuffer destination; + private final @Nullable ByteBuffer destination; private final Duration timeout; - private BRPopLPushCommand(ByteBuffer key, ByteBuffer destination, Duration timeout) { + private BRPopLPushCommand(ByteBuffer key, @Nullable ByteBuffer destination, Duration timeout) { super(key); @@ -1119,7 +1125,7 @@ public interface ReactiveListCommands { Assert.notNull(sourceKey, "Source key must not be null!"); - return new BRPopLPushCommand(sourceKey, null, null); + return new BRPopLPushCommand(sourceKey, null, Duration.ZERO); } /** @@ -1150,14 +1156,15 @@ public interface ReactiveListCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getDestination() { return destination; } /** - * @return + * @return never {@literal null}. */ public Duration getTimeout() { return timeout; diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java index 17f2579f4..cd8cc1dd2 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -65,9 +66,10 @@ public interface ReactiveNumberCommands { */ class IncrByCommand extends KeyCommand { - private T value; + private @Nullable T value; + + private IncrByCommand(ByteBuffer key, @Nullable T value) { - private IncrByCommand(ByteBuffer key, T value) { super(key); this.value = value; } @@ -100,8 +102,9 @@ public interface ReactiveNumberCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public T getValue() { return value; } @@ -141,9 +144,9 @@ public interface ReactiveNumberCommands { */ class DecrByCommand extends KeyCommand { - private T value; + private @Nullable T value; - private DecrByCommand(ByteBuffer key, T value) { + private DecrByCommand(ByteBuffer key, @Nullable T value) { super(key); this.value = value; } @@ -176,8 +179,9 @@ public interface ReactiveNumberCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public T getValue() { return value; } @@ -239,9 +243,9 @@ public interface ReactiveNumberCommands { class HIncrByCommand extends KeyCommand { private final ByteBuffer field; - private final T value; + private final @Nullable T value; - private HIncrByCommand(ByteBuffer key, ByteBuffer field, T value) { + private HIncrByCommand(@Nullable ByteBuffer key, ByteBuffer field, @Nullable T value) { super(key); @@ -290,14 +294,15 @@ public interface ReactiveNumberCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public T getValue() { return value; } /** - * @return + * @return never {@literal null}. */ public ByteBuffer getField() { return field; diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java index 0bf775474..46de3d6d2 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java @@ -24,6 +24,7 @@ import java.util.List; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -148,6 +149,7 @@ public interface ReactiveRedisConnection extends Closeable { /** * @return the key related to this command. */ + @Nullable ByteBuffer getKey(); /** @@ -165,18 +167,19 @@ public interface ReactiveRedisConnection extends Closeable { */ class KeyCommand implements Command { - private ByteBuffer key; + private @Nullable ByteBuffer key; /** * Creates a new {@link KeyCommand} given a {@code key}. * - * @param key must not be {@literal null}. + * @param key can be {@literal null}. */ - public KeyCommand(ByteBuffer key) { + public KeyCommand(@Nullable ByteBuffer key) { this.key = key; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override @@ -196,12 +199,12 @@ public interface ReactiveRedisConnection extends Closeable { * Creates a new {@link RangeCommand} given a {@code key} and {@link Range}. * * @param key must not be {@literal null}. - * @param range may be {@literal null} if unbounded. + * @param range must not be {@literal null}. */ private RangeCommand(ByteBuffer key, Range range) { super(key); - this.range = range != null ? range : new Range<>(0L, Long.MAX_VALUE); + this.range = range; } /** @@ -211,7 +214,7 @@ public interface ReactiveRedisConnection extends Closeable { * @return a new {@link RangeCommand} for {@code key}. */ public static RangeCommand key(ByteBuffer key) { - return new RangeCommand(key, null); + return new RangeCommand(key, Range.unbounded()); } /** @@ -267,7 +270,7 @@ public interface ReactiveRedisConnection extends Closeable { class CommandResponse { private final I input; - private final O output; + private final @Nullable O output; /** * @return {@literal true} if the response is present. An absent {@link CommandResponse} maps to Redis @@ -293,7 +296,7 @@ public interface ReactiveRedisConnection extends Closeable { */ class ByteBufferResponse extends CommandResponse { - public ByteBufferResponse(I input, ByteBuffer output) { + public ByteBufferResponse(I input, @Nullable ByteBuffer output) { super(input, output); } } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java index 2b83fd3c3..f949889c3 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java @@ -32,6 +32,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Command import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -53,7 +54,7 @@ public interface ReactiveSetCommands { private List values; - private SAddCommand(ByteBuffer key, List values) { + private SAddCommand(@Nullable ByteBuffer key, List values) { super(key); @@ -157,7 +158,7 @@ public interface ReactiveSetCommands { private final List values; - private SRemCommand(ByteBuffer key, List values) { + private SRemCommand(@Nullable ByteBuffer key, List values) { super(key); @@ -204,7 +205,7 @@ public interface ReactiveSetCommands { } /** - * @return + * @return never {@literal null}. */ public List getValues() { return values; @@ -261,7 +262,7 @@ public interface ReactiveSetCommands { private final long count; - private SPopCommand(ByteBuffer key, long count) { + private SPopCommand(@Nullable ByteBuffer key, long count) { super(key); this.count = count; @@ -358,10 +359,10 @@ public interface ReactiveSetCommands { */ class SMoveCommand extends KeyCommand { - private final ByteBuffer destination; + private final @Nullable ByteBuffer destination; private final ByteBuffer value; - private SMoveCommand(ByteBuffer key, ByteBuffer destination, ByteBuffer value) { + private SMoveCommand(@Nullable ByteBuffer key, @Nullable ByteBuffer destination, ByteBuffer value) { super(key); this.destination = destination; @@ -409,14 +410,15 @@ public interface ReactiveSetCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getDestination() { return destination; } /** - * @return + * @return never {@literal null}. */ public ByteBuffer getValue() { return value; @@ -484,7 +486,7 @@ public interface ReactiveSetCommands { private final ByteBuffer value; - private SIsMemberCommand(ByteBuffer key, ByteBuffer value) { + private SIsMemberCommand(@Nullable ByteBuffer key, ByteBuffer value) { super(key); @@ -577,10 +579,12 @@ public interface ReactiveSetCommands { return new SInterCommand(new ArrayList<>(keys)); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override + @Nullable public ByteBuffer getKey() { return null; } @@ -626,7 +630,7 @@ public interface ReactiveSetCommands { private final List keys; - private SInterStoreCommand(ByteBuffer key, List keys) { + private SInterStoreCommand(@Nullable ByteBuffer key, List keys) { super(key); @@ -721,10 +725,12 @@ public interface ReactiveSetCommands { return new SUnionCommand(new ArrayList<>(keys)); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override + @Nullable public ByteBuffer getKey() { return null; } @@ -770,7 +776,7 @@ public interface ReactiveSetCommands { private final List keys; - private SUnionStoreCommand(ByteBuffer key, List keys) { + private SUnionStoreCommand(@Nullable ByteBuffer key, List keys) { super(key); @@ -865,10 +871,12 @@ public interface ReactiveSetCommands { return new SDiffCommand(new ArrayList<>(keys)); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override + @Nullable public ByteBuffer getKey() { return null; } @@ -914,7 +922,7 @@ public interface ReactiveSetCommands { private final List keys; - private SDiffStoreCommand(ByteBuffer key, List keys) { + private SDiffStoreCommand(@Nullable ByteBuffer key, List keys) { super(key); @@ -1013,9 +1021,9 @@ public interface ReactiveSetCommands { */ class SRandMembersCommand extends KeyCommand { - private final Long count; + private final @Nullable Long count; - private SRandMembersCommand(ByteBuffer key, Long count) { + private SRandMembersCommand(@Nullable ByteBuffer key, @Nullable Long count) { super(key); this.count = count; diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java index 0c1846eb4..ee680f816 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java @@ -21,6 +21,7 @@ import reactor.core.publisher.Mono; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -38,6 +39,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.RangeCo import org.springframework.data.redis.connection.RedisStringCommands.BitOperation; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -57,11 +59,12 @@ public interface ReactiveStringCommands { */ class SetCommand extends KeyCommand { - private ByteBuffer value; + private @Nullable ByteBuffer value; private Expiration expiration; private SetOption option; - private SetCommand(ByteBuffer key, ByteBuffer value, Expiration expiration, SetOption option) { + private SetCommand(ByteBuffer key, @Nullable ByteBuffer value, @Nullable Expiration expiration, + @Nullable SetOption option) { super(key); @@ -125,6 +128,7 @@ public interface ReactiveStringCommands { /** * @return */ + @Nullable public ByteBuffer getValue() { return value; } @@ -358,10 +362,12 @@ public interface ReactiveStringCommands { this.keyValuePairs = keyValuePairs; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override + @Nullable public ByteBuffer getKey() { return null; } @@ -443,9 +449,9 @@ public interface ReactiveStringCommands { */ class AppendCommand extends KeyCommand { - private ByteBuffer value; + private @Nullable ByteBuffer value; - private AppendCommand(ByteBuffer key, ByteBuffer value) { + private AppendCommand(ByteBuffer key, @Nullable ByteBuffer value) { super(key); this.value = value; @@ -479,8 +485,9 @@ public interface ReactiveStringCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getValue() { return value; } @@ -546,10 +553,10 @@ public interface ReactiveStringCommands { */ class SetRangeCommand extends KeyCommand { - private ByteBuffer value; - private Long offset; + private @Nullable ByteBuffer value; + private @Nullable Long offset; - private SetRangeCommand(ByteBuffer key, ByteBuffer value, Long offset) { + private SetRangeCommand(ByteBuffer key, @Nullable ByteBuffer value, @Nullable Long offset) { super(key); this.value = value; @@ -593,15 +600,17 @@ public interface ReactiveStringCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getValue() { return value; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Long getOffset() { return offset; } @@ -643,9 +652,9 @@ public interface ReactiveStringCommands { */ class GetBitCommand extends KeyCommand { - private Long offset; + private @Nullable Long offset; - private GetBitCommand(ByteBuffer key, Long offset) { + private GetBitCommand(ByteBuffer key, @Nullable Long offset) { super(key); @@ -676,8 +685,9 @@ public interface ReactiveStringCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Long getOffset() { return offset; } @@ -715,7 +725,7 @@ public interface ReactiveStringCommands { */ class SetBitCommand extends KeyCommand { - private Long offset; + private @Nullable Long offset; private boolean value; private SetBitCommand(ByteBuffer key, Long offset, boolean value) { @@ -760,14 +770,15 @@ public interface ReactiveStringCommands { } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Long getOffset() { return offset; } /** - * @return + * @return never {@literal null}. */ public boolean getValue() { return value; @@ -825,7 +836,7 @@ public interface ReactiveStringCommands { Assert.notNull(key, "Key must not be null!"); - return new BitCountCommand(key, null); + return new BitCountCommand(key, Range.unbounded()); } /** @@ -901,9 +912,9 @@ public interface ReactiveStringCommands { private List keys; private BitOperation bitOp; - private ByteBuffer destinationKey; + private @Nullable ByteBuffer destinationKey; - private BitOpCommand(List keys, BitOperation bitOp, ByteBuffer destinationKey) { + private BitOpCommand(List keys, BitOperation bitOp, @Nullable ByteBuffer destinationKey) { this.keys = keys; this.bitOp = bitOp; @@ -920,7 +931,7 @@ public interface ReactiveStringCommands { Assert.notNull(bitOp, "BitOperation must not be null!"); - return new BitOpCommand(null, bitOp, null); + return new BitOpCommand(Collections.emptyList(), bitOp, null); } /** @@ -952,22 +963,23 @@ public interface ReactiveStringCommands { } /** - * @return + * @return never {@literal null}. */ public BitOperation getBitOp() { return bitOp; } /** - * @return + * @return never {@literal null}. */ public List getKeys() { return keys; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public ByteBuffer getDestinationKey() { return destinationKey; } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java index ce2d7e5eb..ea8d68a19 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java @@ -35,6 +35,7 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate; import org.springframework.data.redis.connection.RedisZSetCommands.Limit; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.util.ByteUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -59,7 +60,8 @@ public interface ReactiveZSetCommands { private final boolean returnTotalChanged; private final boolean incr; - private ZAddCommand(ByteBuffer key, List tuples, boolean upsert, boolean returnTotalChanged, boolean incr) { + private ZAddCommand(@Nullable ByteBuffer key, List tuples, boolean upsert, boolean returnTotalChanged, + boolean incr) { super(key); @@ -232,7 +234,7 @@ public interface ReactiveZSetCommands { private final List values; - private ZRemCommand(ByteBuffer key, List values) { + private ZRemCommand(@Nullable ByteBuffer key, List values) { super(key); @@ -335,9 +337,9 @@ public interface ReactiveZSetCommands { class ZIncrByCommand extends KeyCommand { private final ByteBuffer value; - private final Number increment; + private final @Nullable Number increment; - private ZIncrByCommand(ByteBuffer key, ByteBuffer value, Number increment) { + private ZIncrByCommand(@Nullable ByteBuffer key, ByteBuffer value, @Nullable Number increment) { super(key); @@ -386,15 +388,16 @@ public interface ReactiveZSetCommands { } /** - * @return + * @return never {@literal null}. */ public ByteBuffer getValue() { return value; } /** - * @return + * @return can be {@literal null}. */ + @Nullable public Number getIncrement() { return increment; } @@ -441,7 +444,7 @@ public interface ReactiveZSetCommands { private final ByteBuffer value; private final Direction direction; - private ZRankCommand(ByteBuffer key, ByteBuffer value, Direction direction) { + private ZRankCommand(@Nullable ByteBuffer key, ByteBuffer value, Direction direction) { super(key); @@ -561,7 +564,7 @@ public interface ReactiveZSetCommands { private final boolean withScores; private final Direction direction; - private ZRangeCommand(ByteBuffer key, Range range, Direction direction, boolean withScores) { + private ZRangeCommand(@Nullable ByteBuffer key, Range range, Direction direction, boolean withScores) { super(key); @@ -730,10 +733,10 @@ public interface ReactiveZSetCommands { private final Range range; private final boolean withScores; private final Direction direction; - private final Limit limit; + private final @Nullable Limit limit; - private ZRangeByScoreCommand(ByteBuffer key, Range range, Direction direction, boolean withScores, - Limit limit) { + private ZRangeByScoreCommand(@Nullable ByteBuffer key, Range range, Direction direction, boolean withScores, + @Nullable Limit limit) { super(key); @@ -797,10 +800,12 @@ public interface ReactiveZSetCommands { /** * Applies the {@link Limit}. Constructs a new command instance with all previously configured properties. * - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return a new {@link ZRangeByScoreCommand} with {@link Limit} applied. */ public ZRangeByScoreCommand limitTo(Limit limit) { + + Assert.notNull(limit, "Limit must not be null!"); return new ZRangeByScoreCommand(getKey(), range, direction, withScores, limit); } @@ -856,7 +861,7 @@ public interface ReactiveZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return * @see Redis Documentation: ZRANGEBYSCORE */ @@ -864,6 +869,7 @@ public interface ReactiveZSetCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(range, "Range must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).from(key).limitTo(limit))) // .flatMap(CommandResponse::getOutput) // @@ -892,7 +898,7 @@ public interface ReactiveZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return * @see Redis Documentation: ZRANGEBYSCORE */ @@ -900,6 +906,7 @@ public interface ReactiveZSetCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(range, "Range must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).withScores().from(key).limitTo(limit))) .flatMap(CommandResponse::getOutput); @@ -927,7 +934,7 @@ public interface ReactiveZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return * @see Redis Documentation: ZREVRANGEBYSCORE */ @@ -935,6 +942,7 @@ public interface ReactiveZSetCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(range, "Range must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).from(key).limitTo(limit))) // .flatMap(CommandResponse::getOutput) // @@ -963,7 +971,7 @@ public interface ReactiveZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return * @see Redis Documentation: ZREVRANGEBYSCORE */ @@ -971,6 +979,7 @@ public interface ReactiveZSetCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(range, "Range must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); return zRangeByScore( Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).withScores().from(key).limitTo(limit))) @@ -997,7 +1006,7 @@ public interface ReactiveZSetCommands { private final Range range; - private ZCountCommand(ByteBuffer key, Range range) { + private ZCountCommand(@Nullable ByteBuffer key, Range range) { super(key); this.range = range; @@ -1099,7 +1108,7 @@ public interface ReactiveZSetCommands { private final ByteBuffer value; - private ZScoreCommand(ByteBuffer key, ByteBuffer value) { + private ZScoreCommand(@Nullable ByteBuffer key, ByteBuffer value) { super(key); this.value = value; @@ -1250,7 +1259,7 @@ public interface ReactiveZSetCommands { private final Range range; - private ZRemRangeByScoreCommand(ByteBuffer key, Range range) { + private ZRemRangeByScoreCommand(@Nullable ByteBuffer key, Range range) { super(key); this.range = range; @@ -1323,9 +1332,10 @@ public interface ReactiveZSetCommands { private final List sourceKeys; private final List weights; - private final Aggregate aggregateFunction; + private final @Nullable Aggregate aggregateFunction; - private ZUnionStoreCommand(ByteBuffer key, List sourceKeys, List weights, Aggregate aggregate) { + private ZUnionStoreCommand(@Nullable ByteBuffer key, List sourceKeys, List weights, + @Nullable Aggregate aggregate) { super(key); this.sourceKeys = sourceKeys; @@ -1343,7 +1353,7 @@ public interface ReactiveZSetCommands { Assert.notNull(keys, "Keys must not be null!"); - return new ZUnionStoreCommand(null, new ArrayList<>(keys), null, null); + return new ZUnionStoreCommand(null, new ArrayList<>(keys), Collections.emptyList(), null); } /** @@ -1363,7 +1373,8 @@ public interface ReactiveZSetCommands { * @param aggregateFunction can be {@literal null}. * @return a new {@link ZUnionStoreCommand} with {@link Aggregate} applied. */ - public ZUnionStoreCommand aggregateUsing(Aggregate aggregateFunction) { + public ZUnionStoreCommand aggregateUsing(@Nullable Aggregate aggregateFunction) { + return new ZUnionStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } @@ -1382,21 +1393,21 @@ public interface ReactiveZSetCommands { } /** - * @return + * @return never {@literal null}. */ public List getSourceKeys() { return sourceKeys; } /** - * @return + * @return never {@literal null}. */ public List getWeights() { - return weights == null ? Collections.emptyList() : weights; + return weights; } /** - * @return + * @return never {@literal null}. */ public Optional getAggregateFunction() { return Optional.ofNullable(aggregateFunction); @@ -1412,7 +1423,7 @@ public interface ReactiveZSetCommands { * @see Redis Documentation: ZUNIONSTORE */ default Mono zUnionStore(ByteBuffer destinationKey, List sets) { - return zUnionStore(destinationKey, sets, null); + return zUnionStore(destinationKey, sets, Collections.emptyList()); } /** @@ -1421,7 +1432,7 @@ public interface ReactiveZSetCommands { * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. - * @param weights can be {@literal null}. + * @param weights must not be {@literal null}. * @return * @see Redis Documentation: ZUNIONSTORE */ @@ -1441,7 +1452,7 @@ public interface ReactiveZSetCommands { * @see Redis Documentation: ZUNIONSTORE */ default Mono zUnionStore(ByteBuffer destinationKey, List sets, List weights, - Aggregate aggregateFunction) { + @Nullable Aggregate aggregateFunction) { Assert.notNull(destinationKey, "DestinationKey must not be null!"); Assert.notNull(sets, "Sets must not be null!"); @@ -1471,9 +1482,10 @@ public interface ReactiveZSetCommands { private final List sourceKeys; private final List weights; - private final Aggregate aggregateFunction; + private final @Nullable Aggregate aggregateFunction; - private ZInterStoreCommand(ByteBuffer key, List sourceKeys, List weights, Aggregate aggregate) { + private ZInterStoreCommand(ByteBuffer key, List sourceKeys, List weights, + @Nullable Aggregate aggregate) { super(key); this.sourceKeys = sourceKeys; @@ -1491,7 +1503,7 @@ public interface ReactiveZSetCommands { Assert.notNull(keys, "Keys must not be null!"); - return new ZInterStoreCommand(null, new ArrayList<>(keys), null, null); + return new ZInterStoreCommand(null, new ArrayList<>(keys), Collections.emptyList(), null); } /** @@ -1512,7 +1524,8 @@ public interface ReactiveZSetCommands { * @param aggregateFunction can be {@literal null}. * @return a new {@link ZInterStoreCommand} with {@link Aggregate} applied. */ - public ZInterStoreCommand aggregateUsing(Aggregate aggregateFunction) { + public ZInterStoreCommand aggregateUsing(@Nullable Aggregate aggregateFunction) { + return new ZInterStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } @@ -1531,21 +1544,21 @@ public interface ReactiveZSetCommands { } /** - * @return + * @return never {@literal null}. */ public List getSourceKeys() { return sourceKeys; } /** - * @return + * @return never {@literal null}. */ public List getWeights() { - return weights == null ? Collections.emptyList() : weights; + return weights; } /** - * @return + * @return never {@literal null}.ø */ public Optional getAggregateFunction() { return Optional.ofNullable(aggregateFunction); @@ -1561,7 +1574,7 @@ public interface ReactiveZSetCommands { * @see Redis Documentation: ZINTERSTORE */ default Mono zInterStore(ByteBuffer destinationKey, List sets) { - return zInterStore(destinationKey, sets, null); + return zInterStore(destinationKey, sets, Collections.emptyList()); } /** @@ -1570,7 +1583,7 @@ public interface ReactiveZSetCommands { * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. - * @param weights can be {@literal null}. + * @param weights must not be {@literal null}. * @return * @see Redis Documentation: ZINTERSTORE */ @@ -1584,13 +1597,13 @@ public interface ReactiveZSetCommands { * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. - * @param weights can be {@literal null}. + * @param weights must not be {@literal null}. * @param aggregateFunction can be {@literal null}. * @return * @see Redis Documentation: ZINTERSTORE */ default Mono zInterStore(ByteBuffer destinationKey, List sets, List weights, - Aggregate aggregateFunction) { + @Nullable Aggregate aggregateFunction) { Assert.notNull(destinationKey, "DestinationKey must not be null!"); Assert.notNull(sets, "Sets must not be null!"); @@ -1623,7 +1636,7 @@ public interface ReactiveZSetCommands { private final Direction direction; private final Limit limit; - private ZRangeByLexCommand(ByteBuffer key, Range range, Direction direction, Limit limit) { + private ZRangeByLexCommand(@Nullable ByteBuffer key, Range range, Direction direction, Limit limit) { super(key); this.range = range; @@ -1642,7 +1655,7 @@ public interface ReactiveZSetCommands { Assert.notNull(range, "Range must not be null!"); - return new ZRangeByLexCommand(null, range, Direction.ASC, null); + return new ZRangeByLexCommand(null, range, Direction.ASC, Limit.unlimited()); } /** @@ -1656,7 +1669,7 @@ public interface ReactiveZSetCommands { Assert.notNull(range, "Range must not be null!"); - return new ZRangeByLexCommand(null, range, Direction.DESC, null); + return new ZRangeByLexCommand(null, range, Direction.DESC, Limit.unlimited()); } /** @@ -1675,10 +1688,12 @@ public interface ReactiveZSetCommands { /** * Applies the {@link Limit}. Constructs a new command instance with all previously configured properties. * - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return a new {@link ZRangeByLexCommand} with {@link Limit} applied. */ public ZRangeByLexCommand limitTo(Limit limit) { + + Assert.notNull(limit, "Limit must not be null!"); return new ZRangeByLexCommand(getKey(), range, direction, limit); } @@ -1713,7 +1728,7 @@ public interface ReactiveZSetCommands { * @see Redis Documentation: ZRANGEBYLEX */ default Flux zRangeByLex(ByteBuffer key, Range range) { - return zRangeByLex(key, range, null); + return zRangeByLex(key, range, Limit.unlimited()); } /** @@ -1744,7 +1759,7 @@ public interface ReactiveZSetCommands { * @see Redis Documentation: ZREVRANGEBYLEX */ default Flux zRevRangeByLex(ByteBuffer key, Range range) { - return zRevRangeByLex(key, range, null); + return zRevRangeByLex(key, range, Limit.unlimited()); } /** @@ -1753,7 +1768,7 @@ public interface ReactiveZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param limit must not be {@literal null}. * @return * @see Redis Documentation: ZREVRANGEBYLEX */ @@ -1761,6 +1776,7 @@ public interface ReactiveZSetCommands { Assert.notNull(key, "Key must not be null!"); Assert.notNull(range, "Range must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); return zRangeByLex(Mono.just(ZRangeByLexCommand.reverseStringsWithin(range).from(key).limitTo(limit))) .flatMap(CommandResponse::getOutput); diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterCommands.java index 061068f5f..826ed7868 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterCommands.java @@ -179,7 +179,7 @@ public interface RedisClusterCommands { */ void clusterReplicate(RedisClusterNode master, RedisClusterNode slave); - public enum AddSlots { + enum AddSlots { MIGRATING, IMPORTING, STABLE, NODE } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java index 8736d22a4..2783bd02e 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java @@ -27,6 +27,7 @@ import java.util.Set; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.NumberUtils; import org.springframework.util.StringUtils; @@ -46,7 +47,7 @@ public class RedisClusterConfiguration { private static final String REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY = "spring.redis.cluster.max-redirects"; private Set clusterNodes; - private Integer maxRedirects; + private @Nullable Integer maxRedirects; private RedisPassword password = RedisPassword.none(); /** @@ -213,7 +214,6 @@ public class RedisClusterConfiguration { /** * @param clusterHostAndPorts must not be {@literal null} or empty. * @param redirects the max number of redirects to follow. - * @param password can be {@literal null} or empty. * @return cluster config map with properties. */ private static Map asMap(Collection clusterHostAndPorts, int redirects) { diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java index 765268fe3..7af3f274e 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-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. @@ -17,6 +17,8 @@ package org.springframework.data.redis.connection; import java.util.Set; +import org.springframework.lang.Nullable; + /** * {@link RedisClusterConnection} allows sending commands to dedicated nodes within the cluster. A * {@link RedisClusterNode} can be obtained from {@link #clusterGetNodes()} or it can be constructed using either @@ -31,24 +33,27 @@ public interface RedisClusterConnection extends RedisConnection, RedisClusterCom /** * @param node must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see RedisConnectionCommands#ping() */ + @Nullable String ping(RedisClusterNode node); /** * @param node must not be {@literal null}. * @param pattern must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see RedisKeyCommands#keys(byte[]) */ + @Nullable Set keys(RedisClusterNode node, byte[] pattern); /** * @param node must not be {@literal null}. - * @return + * @return {@literal null} when no keys stored at node or when used in pipeline / transaction. * @see RedisKeyCommands#randomKey() */ + @Nullable byte[] randomKey(RedisClusterNode node); /** diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java index f66abb30c..789aef656 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -33,11 +34,13 @@ import org.springframework.util.CollectionUtils; public class RedisClusterNode extends RedisNode { private SlotRange slotRange; - private LinkState linkState; + private @Nullable LinkState linkState; private Set flags; protected RedisClusterNode() { + super(); + flags = Collections.emptySet(); } /** @@ -47,7 +50,7 @@ public class RedisClusterNode extends RedisNode { * @param port */ public RedisClusterNode(String host, int port) { - this(host, port, new SlotRange(Collections. emptySet())); + this(host, port, SlotRange.empty()); } /** @@ -57,7 +60,7 @@ public class RedisClusterNode extends RedisNode { */ public RedisClusterNode(String id) { - this(new SlotRange(Collections. emptySet())); + this(SlotRange.empty()); Assert.notNull(id, "Id must not be null!"); this.id = id; } @@ -67,23 +70,34 @@ public class RedisClusterNode extends RedisNode { * * @param host must not be {@literal null}. * @param port - * @param slotRange can be {@literal null}. + * @param slotRange must not be {@literal null}. */ public RedisClusterNode(String host, int port, SlotRange slotRange) { super(host, port); - this.slotRange = slotRange != null ? slotRange : new SlotRange(Collections. emptySet()); + + Assert.notNull(slotRange, "SlotRange must not be null!"); + this.slotRange = slotRange; } /** * Creates new {@link RedisClusterNode} with given {@link SlotRange}. * - * @param slotRange can be {@literal null}. + * @param slotRange must not be {@literal null}. */ public RedisClusterNode(SlotRange slotRange) { super(); - this.slotRange = slotRange != null ? slotRange : new SlotRange(Collections. emptySet()); + + Assert.notNull(slotRange, "SlotRange must not be null!"); + + this.slotRange = slotRange; + } + + { + if (flags == null) { + flags = Collections.emptySet(); + } } /** @@ -104,8 +118,9 @@ public class RedisClusterNode extends RedisNode { } /** - * @return + * @return can be {@literal null} */ + @Nullable public LinkState getLinkState() { return linkState; } @@ -121,7 +136,7 @@ public class RedisClusterNode extends RedisNode { * @return never {@literal null}. */ public Set getFlags() { - return flags == null ? Collections. emptySet() : flags; + return flags == null ? Collections.emptySet() : flags; } /** @@ -177,8 +192,7 @@ public class RedisClusterNode extends RedisNode { } public SlotRange(Collection range) { - this.range = CollectionUtils.isEmpty(range) ? Collections. emptySet() - : new LinkedHashSet<>(range); + this.range = CollectionUtils.isEmpty(range) ? Collections.emptySet() : new LinkedHashSet<>(range); } @Override @@ -212,13 +226,17 @@ public class RedisClusterNode extends RedisNode { return slots; } + + public static SlotRange empty() { + return new SlotRange(Collections.emptySet()); + } } /** * @author Christoph Strobl * @since 1.7 */ - public static enum LinkState { + public enum LinkState { CONNECTED, DISCONNECTED } @@ -251,12 +269,12 @@ public class RedisClusterNode extends RedisNode { */ public static class RedisClusterNodeBuilder extends RedisNodeBuilder { - Set flags; - LinkState linkState; + @Nullable Set flags; + @Nullable LinkState linkState; SlotRange slotRange; public RedisClusterNodeBuilder() { - + this.slotRange = SlotRange.empty(); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/RedisCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisCommands.java index f0b3020e4..071b9f671 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-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. @@ -16,6 +16,8 @@ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * Interface for the commands supported by Redis. * @@ -30,10 +32,11 @@ public interface RedisCommands extends RedisKeyCommands, RedisStringCommands, Re * 'Native' or 'raw' execution of the given command along-side the given arguments. The command is executed as is, * with as little 'interpretation' as possible - it is up to the caller to take care of any processing of arguments or * the result. - * - * @param command Command to execute - * @param args Possible command arguments (may be null) - * @return execution result. + * + * @param command Command to execute. must not be {@literal null}. + * @param args Possible command arguments (may be empty). + * @return execution result. Can be {@literal null}. */ + @Nullable Object execute(String command, byte[]... args); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisConnectionCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisConnectionCommands.java index d96fd2632..5d112872a 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisConnectionCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisConnectionCommands.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * Connection-specific commands supported by Redis. * @@ -36,16 +38,18 @@ public interface RedisConnectionCommands { * Returns {@code message} via server roundtrip. * * @param message the message to echo. - * @return + * @return the message or {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ECHO */ + @Nullable byte[] echo(byte[] message); /** * Test connection. * - * @return Server response message - usually {@literal PONG}. + * @return Server response message - usually {@literal PONG}. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PING */ + @Nullable String ping(); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisGeoCommands.java index 99e7de7bd..fd5333cd1 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisGeoCommands.java @@ -29,6 +29,7 @@ import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metric; import org.springframework.data.geo.Point; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -47,9 +48,10 @@ public interface RedisGeoCommands { * @param key must not be {@literal null}. * @param point must not be {@literal null}. * @param member must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD */ + @Nullable Long geoAdd(byte[] key, Point point, byte[] member); /** @@ -57,9 +59,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param location must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD */ + @Nullable default Long geoAdd(byte[] key, GeoLocation location) { Assert.notNull(key, "Key must not be null!"); @@ -73,9 +76,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param memberCoordinateMap must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD */ + @Nullable Long geoAdd(byte[] key, Map memberCoordinateMap); /** @@ -83,9 +87,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param locations must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD */ + @Nullable Long geoAdd(byte[] key, Iterable> locations); /** @@ -94,9 +99,10 @@ public interface RedisGeoCommands { * @param key must not be {@literal null}. * @param member1 must not be {@literal null}. * @param member2 must not be {@literal null}. - * @return can be {@literal null}. + * @return can be {@literal null}. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEODIST */ + @Nullable Distance geoDist(byte[] key, byte[] member1, byte[] member2); /** @@ -106,9 +112,10 @@ public interface RedisGeoCommands { * @param member1 must not be {@literal null}. * @param member2 must not be {@literal null}. * @param metric must not be {@literal null}. - * @return can be {@literal null}. + * @return can be {@literal null}. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEODIST */ + @Nullable Distance geoDist(byte[] key, byte[] member1, byte[] member2, Metric metric); /** @@ -116,9 +123,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return empty list when key or members do not exists. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOHASH */ + @Nullable List geoHash(byte[] key, byte[]... members); /** @@ -126,9 +134,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return empty {@link List} when key of members do not exist. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOPOS */ + @Nullable List geoPos(byte[] key, byte[]... members); /** @@ -136,9 +145,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param within must not be {@literal null}. - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> geoRadius(byte[] key, Circle within); /** @@ -147,9 +157,10 @@ public interface RedisGeoCommands { * @param key must not be {@literal null}. * @param within must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> geoRadius(byte[] key, Circle within, GeoRadiusCommandArgs args); /** @@ -159,9 +170,10 @@ public interface RedisGeoCommands { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param radius - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable default GeoResults> geoRadiusByMember(byte[] key, byte[] member, double radius) { return geoRadiusByMember(key, member, new Distance(radius, DistanceUnit.METERS)); } @@ -173,9 +185,10 @@ public interface RedisGeoCommands { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param radius must not be {@literal null}. - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction.. * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> geoRadiusByMember(byte[] key, byte[] member, Distance radius); /** @@ -186,9 +199,10 @@ public interface RedisGeoCommands { * @param member must not be {@literal null}. * @param radius must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> geoRadiusByMember(byte[] key, byte[] member, Distance radius, GeoRadiusCommandArgs args); @@ -197,9 +211,10 @@ public interface RedisGeoCommands { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return Number of elements removed. + * @return Number of elements removed. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREM */ + @Nullable Long geoRemove(byte[] key, byte[]... members); /** @@ -212,8 +227,8 @@ public interface RedisGeoCommands { class GeoRadiusCommandArgs implements Cloneable { Set flags = new LinkedHashSet<>(2, 1); - Long limit; - Direction sortDirection; + @Nullable Long limit; + @Nullable Direction sortDirection; private GeoRadiusCommandArgs() {} @@ -293,6 +308,7 @@ public interface RedisGeoCommands { /** * @return can be {@literal null}. */ + @Nullable public Long getLimit() { return limit; } @@ -300,6 +316,7 @@ public interface RedisGeoCommands { /** * @return can be {@literal null}. */ + @Nullable public Direction getSortDirection() { return sortDirection; } @@ -316,7 +333,7 @@ public interface RedisGeoCommands { return limit != null; } - public static enum Flag { + public enum Flag { WITHCOORD, WITHDIST } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisHashCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisHashCommands.java index 4e533f233..d4bb421b6 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisHashCommands.java @@ -21,6 +21,7 @@ import java.util.Set; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; +import org.springframework.lang.Nullable; /** * Hash-specific commands supported by Redis. @@ -36,10 +37,11 @@ public interface RedisHashCommands { * * @param key must not be {@literal null}. * @param field must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HSET */ + @Nullable Boolean hSet(byte[] key, byte[] field, byte[] value); /** @@ -47,10 +49,11 @@ public interface RedisHashCommands { * * @param key must not be {@literal null}. * @param field must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HSETNX */ + @Nullable Boolean hSetNX(byte[] key, byte[] field, byte[] value); /** @@ -58,19 +61,21 @@ public interface RedisHashCommands { * * @param key must not be {@literal null}. * @param field must not be {@literal null}. - * @return + * @return {@literal null} when key or field do not exists or when used in pipeline / transaction. * @see Redis Documentation: HGET */ + @Nullable byte[] hGet(byte[] key, byte[] field); /** * Get values for given {@code fields} from hash at {@code key}. * * @param key must not be {@literal null}. - * @param fields must not be {@literal null}. - * @return + * @param fields must not be {@literal empty}. + * @return empty {@link List} if key or fields do not exists. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HMGET */ + @Nullable List hMGet(byte[] key, byte[]... fields); /** @@ -88,20 +93,22 @@ public interface RedisHashCommands { * @param key must not be {@literal null}. * @param field must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HINCRBY */ + @Nullable Long hIncrBy(byte[] key, byte[] field, long delta); /** * Increment {@code value} of a hash {@code field} by the given {@code delta}. * * @param key must not be {@literal null}. - * @param field + * @param field must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HINCRBYFLOAT */ + @Nullable Double hIncrBy(byte[] key, byte[] field, double delta); /** @@ -109,55 +116,61 @@ public interface RedisHashCommands { * * @param key must not be {@literal null}. * @param field must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HEXISTS */ + @Nullable Boolean hExists(byte[] key, byte[] field); /** * Delete given hash {@code fields}. * * @param key must not be {@literal null}. - * @param fields must not be {@literal null}. - * @return + * @param fields must not be {@literal empty}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HDEL */ + @Nullable Long hDel(byte[] key, byte[]... fields); /** * Get size of hash at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HLEN */ + @Nullable Long hLen(byte[] key); /** * Get key set (fields) of hash at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HKEYS? */ + @Nullable Set hKeys(byte[] key); /** * Get entry set (values) of hash at {@code field}. * * @param key must not be {@literal null}. - * @return + * @return empty {@link List} if key does not exist. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HVALS */ + @Nullable List hVals(byte[] key); /** * Get entire hash stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return empty {@link Map} if key does not exist or {@literal null} when used in pipeline / transaction. * @see Redis Documentation: HGETALL */ + @Nullable Map hGetAll(byte[] key); /** diff --git a/src/main/java/org/springframework/data/redis/connection/RedisHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisHyperLogLogCommands.java index d05c83047..36999c1c3 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisHyperLogLogCommands.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * {@literal HyperLogLog} specific commands supported by Redis. * @@ -29,18 +31,20 @@ public interface RedisHyperLogLogCommands { * * @param key must not be {@literal null}. * @param values must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PFADD */ + @Nullable Long pfAdd(byte[] key, byte[]... values); /** * Return the approximated cardinality of the structures observed by the HyperLogLog at {@literal key(s)}. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PFCOUNT */ + @Nullable Long pfCount(byte[]... keys); /** diff --git a/src/main/java/org/springframework/data/redis/connection/RedisKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisKeyCommands.java index 1f372479d..809edee5a 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisKeyCommands.java @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; +import org.springframework.lang.Nullable; /** * Key-specific commands supported by Redis. @@ -35,43 +36,47 @@ public interface RedisKeyCommands { * Determine if given {@code key} exists. * * @param key must not be {@literal null}. - * @return + * @return {@literal true} if key exists. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: EXISTS */ + @Nullable Boolean exists(byte[] key); /** * Delete given {@code keys}. * * @param keys must not be {@literal null}. - * @return The number of keys that were removed. + * @return The number of keys that were removed. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: DEL */ + @Nullable Long del(byte[]... keys); /** * Determine the type stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: TYPE */ + @Nullable DataType type(byte[] key); /** * Find all keys matching the given {@code pattern}. * * @param pattern must not be {@literal null}. - * @return + * @return empty {@link Set} if no match found. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: KEYS */ + @Nullable Set keys(byte[] pattern); /** * Use a {@link Cursor} to iterate over keys. * * @param options must not be {@literal null}. - * @return + * @return never {@literal null}. * @since 1.4 * @see Redis Documentation: SCAN */ @@ -80,9 +85,10 @@ public interface RedisKeyCommands { /** * Return a random key from the keyspace. * - * @return + * @return {@literal null} if no keys available or when used in pipeline or transaction. * @see Redis Documentation: RANDOMKEY */ + @Nullable byte[] randomKey(); /** @@ -99,9 +105,10 @@ public interface RedisKeyCommands { * * @param oldName must not be {@literal null}. * @param newName must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RENAMENX */ + @Nullable Boolean renameNX(byte[] oldName, byte[] newName); /** @@ -109,9 +116,10 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param seconds - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: EXPIRE */ + @Nullable Boolean expire(byte[] key, long seconds); /** @@ -119,9 +127,10 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param millis - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PEXPIRE */ + @Nullable Boolean pExpire(byte[] key, long millis); /** @@ -129,9 +138,10 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param unixTime - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: EXPIREAT */ + @Nullable Boolean expireAt(byte[] key, long unixTime); /** @@ -139,18 +149,20 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param unixTimeInMillis - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PEXPIREAT */ + @Nullable Boolean pExpireAt(byte[] key, long unixTimeInMillis); /** * Remove the expiration from given {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PERSIST */ + @Nullable Boolean persist(byte[] key); /** @@ -158,18 +170,20 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param dbIndex - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: MOVE */ + @Nullable Boolean move(byte[] key, int dbIndex); /** * Get the time to live for {@code key} in seconds. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: TTL */ + @Nullable Long ttl(byte[] key); /** @@ -177,19 +191,21 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param timeUnit must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.8 * @see Redis Documentation: TTL */ + @Nullable Long ttl(byte[] key, TimeUnit timeUnit); /** * Get the precise time to live for {@code key} in milliseconds. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PTTL */ + @Nullable Long pTtl(byte[] key); /** @@ -197,10 +213,11 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param timeUnit must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.8 * @see Redis Documentation: PTTL */ + @Nullable Long pTtl(byte[] key, TimeUnit timeUnit); /** @@ -208,9 +225,10 @@ public interface RedisKeyCommands { * * @param key must not be {@literal null}. * @param params must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable List sort(byte[] key, SortParameters params); /** @@ -219,18 +237,20 @@ public interface RedisKeyCommands { * @param key must not be {@literal null}. * @param params must not be {@literal null}. * @param storeKey must not be {@literal null}. - * @return number of values. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable Long sort(byte[] key, SortParameters params, byte[] storeKey); /** * Retrieve serialized version of the value stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} if key does not exist or when used in pipeline / transaction. * @see Redis Documentation: DUMP */ + @Nullable byte[] dump(byte[] key); /** diff --git a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java index 0f4c6fe1c..fbbe7d297 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java @@ -17,6 +17,8 @@ package org.springframework.data.redis.connection; import java.util.List; +import org.springframework.lang.Nullable; + /** * List-specific commands supported by Redis. * @@ -29,7 +31,7 @@ public interface RedisListCommands { /** * List insertion position. */ - public enum Position { + enum Position { BEFORE, AFTER } @@ -37,49 +39,54 @@ public interface RedisListCommands { * Append {@code values} to {@code key}. * * @param key must not be {@literal null}. - * @param values - * @return + * @param values must not be empty. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSH */ + @Nullable Long rPush(byte[] key, byte[]... values); /** * Prepend {@code values} to {@code key}. * * @param key must not be {@literal null}. - * @param values - * @return + * @param values must not be empty. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSH */ + @Nullable Long lPush(byte[] key, byte[]... values); /** * Append {@code values} to {@code key} only if the list exists. * * @param key must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSHX */ + @Nullable Long rPushX(byte[] key, byte[] value); /** * Prepend {@code values} to {@code key} only if the list exists. * * @param key must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSHX */ + @Nullable Long lPushX(byte[] key, byte[] value); /** * Get the size of list stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LLEN */ + @Nullable Long lLen(byte[] key); /** @@ -88,9 +95,11 @@ public interface RedisListCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return empty {@link List} if key does not exists or range does not contain values. {@literal null} when used in + * pipeline / transaction. * @see Redis Documentation: LRANGE */ + @Nullable List lRange(byte[] key, long start, long end); /** @@ -107,10 +116,11 @@ public interface RedisListCommands { * Get element at {@code index} form list at {@code key}. * * @param key must not be {@literal null}. - * @param index - * @return + * @param index zero based index value. Use negative number to designate elements starting at the tail. + * @return {@literal null} when index is out of range or when used in pipeline / transaction. * @see Redis Documentation: LINDEX */ + @Nullable byte[] lIndex(byte[] key, long index); /** @@ -118,11 +128,12 @@ public interface RedisListCommands { * * @param key must not be {@literal null}. * @param where must not be {@literal null}. - * @param pivot - * @param value - * @return + * @param pivot must not be {@literal null}. + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LINSERT */ + @Nullable Long lInsert(byte[] key, Position where, byte[] pivot, byte[] value); /** @@ -141,51 +152,58 @@ public interface RedisListCommands { * @param key must not be {@literal null}. * @param count * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LREM */ + @Nullable Long lRem(byte[] key, long count, byte[] value); /** * Removes and returns first element in list stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when key does not exist or used in pipeline / transaction. * @see Redis Documentation: LPOP */ + @Nullable byte[] lPop(byte[] key); /** * Removes and returns last element in list stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when key does not exist or used in pipeline / transaction. * @see Redis Documentation: RPOP */ + @Nullable byte[] rPop(byte[] key); /** * Removes and returns first element from lists stored at {@code keys}.
* Blocks connection until element available or {@code timeout} reached. * - * @param timeout + * @param timeout seconds to block. * @param keys must not be {@literal null}. - * @return + * @return empty {@link List} when no element could be popped and the timeout was reached. {@literal null} when used + * in pipeline / transaction. * @see Redis Documentation: BLPOP * @see #lPop(byte[]) */ + @Nullable List bLPop(int timeout, byte[]... keys); /** * Removes and returns last element from lists stored at {@code keys}.
* Blocks connection until element available or {@code timeout} reached. * - * @param timeout + * @param timeout seconds to block. * @param keys must not be {@literal null}. - * @return + * @return empty {@link List} when no element could be popped and the timeout was reached. {@literal null} when used + * in pipeline / transaction. * @see Redis Documentation: BRPOP * @see #rPop(byte[]) */ + @Nullable List bRPop(int timeout, byte[]... keys); /** @@ -193,22 +211,23 @@ public interface RedisListCommands { * * @param srcKey must not be {@literal null}. * @param dstKey must not be {@literal null}. - * @return + * @return can be {@literal null}. * @see Redis Documentation: RPOPLPUSH */ + @Nullable byte[] rPopLPush(byte[] srcKey, byte[] dstKey); /** - * Remove the last element from list at {@code srcKey}, append it to {@code dstKey} and return its value. - *
+ * Remove the last element from list at {@code srcKey}, append it to {@code dstKey} and return its value.
* Blocks connection until element available or {@code timeout} reached. * - * @param timeout + * @param timeout seconds to block. * @param srcKey must not be {@literal null}. * @param dstKey must not be {@literal null}. - * @return + * @return can be {@literal null}. * @see Redis Documentation: BRPOPLPUSH * @see #rPopLPush(byte[], byte[]) */ + @Nullable byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisNode.java b/src/main/java/org/springframework/data/redis/connection/RedisNode.java index b4f47b941..9883008d4 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisNode.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisNode.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -26,12 +27,12 @@ import org.springframework.util.ObjectUtils; */ public class RedisNode implements NamedNode { - String id; - String name; - String host; + @Nullable String id; + @Nullable String name; + @Nullable String host; int port; - NodeType type; - String masterId; + @Nullable NodeType type; + @Nullable String masterId; /** * Creates a new {@link RedisNode} with the given {@code host}, {@code port}. @@ -49,10 +50,18 @@ public class RedisNode implements NamedNode { protected RedisNode() {} + /** + * @return can be {@literal null}. + */ + @Nullable public String getHost() { return host; } + /** + * @return can be {@literal null}. + */ + @Nullable public Integer getPort() { return port; } @@ -62,6 +71,7 @@ public class RedisNode implements NamedNode { } @Override + @Nullable public String getName() { return this.name; } @@ -71,23 +81,24 @@ public class RedisNode implements NamedNode { } /** - * @return + * @return can be {@literal null}. * @since 1.7 */ + @Nullable public String getMasterId() { return masterId; } /** - * @return + * @return can be {@literal null}. * @since 1.7 */ + @Nullable public String getId() { return id; } /** - * * @param id * @since 1.7 */ @@ -96,9 +107,10 @@ public class RedisNode implements NamedNode { } /** - * @return + * @return can be {@literal null}. * @since 1.7 */ + @Nullable public NodeType getType() { return type; } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisPipelineException.java b/src/main/java/org/springframework/data/redis/connection/RedisPipelineException.java index 324b79e83..357437b94 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisPipelineException.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisPipelineException.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.lang.Nullable; /** * Exception thrown when executing/closing a pipeline that contains one or multiple invalid/incorrect statements. The @@ -41,7 +42,7 @@ public class RedisPipelineException extends InvalidDataAccessResourceUsageExcept * @param cause the cause * @param pipelineResult the pipeline result */ - public RedisPipelineException(String msg, Throwable cause, List pipelineResult) { + public RedisPipelineException(@Nullable String msg, @Nullable Throwable cause, List pipelineResult) { super(msg, cause); results = Collections.unmodifiableList(pipelineResult); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisPubSubCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisPubSubCommands.java index a435c754b..440e1f742 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisPubSubCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisPubSubCommands.java @@ -15,34 +15,38 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * PubSub-specific Redis commands. * * @author Costin Leau * @author Mark Paluch + * @author Christoph Strobl */ public interface RedisPubSubCommands { /** * Indicates whether the current connection is subscribed (to at least one channel) or not. - * + * * @return true if the connection is subscribed, false otherwise */ boolean isSubscribed(); /** * Returns the current subscription for this connection or null if the connection is not subscribed. - * - * @return the current subscription, null if none is available + * + * @return the current subscription, {@literal null} if none is available. */ + @Nullable Subscription getSubscription(); /** * Publishes the given message to the given channel. - * - * @param channel the channel to publish to, must not be {@literal null}. - * @param message message to publish - * @return the number of clients that received the message + * + * @param channel the channel to publish to. Must not be {@literal null}. + * @param message message to publish. Must not be {@literal null}. + * @return the number of clients that received the message. * @see Redis Documentation: PUBLISH */ Long publish(byte[] channel, byte[] message); @@ -52,7 +56,7 @@ public interface RedisPubSubCommands { * subscribe to other channels or unsubscribe. No other commands are accepted until the connection is unsubscribed. *

* Note that this operation is blocking and the current thread starts waiting for new messages immediately. - * + * * @param listener message listener, must not be {@literal null}. * @param channels channel names, must not be {@literal null}. * @see Redis Documentation: SUBSCRIBE @@ -65,7 +69,7 @@ public interface RedisPubSubCommands { * connection is unsubscribed. *

* Note that this operation is blocking and the current thread starts waiting for new messages immediately. - * + * * @param listener message listener, must not be {@literal null}. * @param patterns channel name patterns, must not be {@literal null}. * @see Redis Documentation: PSUBSCRIBE diff --git a/src/main/java/org/springframework/data/redis/connection/RedisScriptingCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisScriptingCommands.java index 48614c58a..0cf0f6407 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisScriptingCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisScriptingCommands.java @@ -17,9 +17,11 @@ package org.springframework.data.redis.connection; import java.util.List; +import org.springframework.lang.Nullable; + /** * Scripting commands. - * + * * @author Costin Leau * @author Christoph Strobl * @author David Liu @@ -46,18 +48,21 @@ public interface RedisScriptingCommands { * Execute the script by calling {@link #evalSha(byte[], ReturnType, int, byte[]...)}. * * @param script must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SCRIPT LOAD */ + @Nullable String scriptLoad(byte[] script); /** * Check if given {@code scriptShas} exist in script cache. * * @param scriptShas - * @return one entry per given scriptSha in returned list. + * @return one entry per given scriptSha in returned {@link List} or {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: SCRIPT EXISTS */ + @Nullable List scriptExists(String... scriptShas); /** @@ -67,9 +72,10 @@ public interface RedisScriptingCommands { * @param returnType must not be {@literal null}. * @param numKeys * @param keysAndArgs must not be {@literal null}. - * @return + * @return script result. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: EVAL */ + @Nullable T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs); /** @@ -79,9 +85,10 @@ public interface RedisScriptingCommands { * @param returnType must not be {@literal null}. * @param numKeys * @param keysAndArgs must not be {@literal null}. - * @return + * @return script result. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: EVALSHA */ + @Nullable T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs); /** @@ -91,9 +98,10 @@ public interface RedisScriptingCommands { * @param returnType must not be {@literal null}. * @param numKeys * @param keysAndArgs must not be {@literal null}. - * @return + * @return script result. {@literal null} when used in pipeline / transaction. * @since 1.5 * @see Redis Documentation: EVALSHA */ + @Nullable T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisSentinelCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisSentinelCommands.java index 7e8009002..ab6a6d00d 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisSentinelCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisSentinelCommands.java @@ -36,7 +36,7 @@ public interface RedisSentinelCommands { /** * Get a {@link Collection} of monitored masters and their state. - * + * * @return Collection of {@link RedisServer}s. Never {@literal null}. */ Collection masters(); diff --git a/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java b/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java index c792174a3..1def208f6 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java @@ -27,6 +27,7 @@ import java.util.Set; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -45,7 +46,7 @@ public class RedisSentinelConfiguration { private static final String REDIS_SENTINEL_MASTER_CONFIG_PROPERTY = "spring.redis.sentinel.master"; private static final String REDIS_SENTINEL_NODES_CONFIG_PROPERTY = "spring.redis.sentinel.nodes"; - private NamedNode master; + private @Nullable NamedNode master; private Set sentinels; private int database; private RedisPassword password = RedisPassword.none(); @@ -162,8 +163,9 @@ public class RedisSentinelConfiguration { /** * Get the {@literal Sentinel} master node. * - * @return get the master node. + * @return get the master node or {@literal null} if not set. */ + @Nullable public NamedNode getMaster() { return master; } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java index d5a3d9af7..3ffe77120 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Properties; import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.lang.Nullable; /** * Server-specific commands supported by Redis. @@ -30,14 +31,14 @@ import org.springframework.data.redis.core.types.RedisClientInfo; */ public interface RedisServerCommands { - public enum ShutdownOption { + enum ShutdownOption { SAVE, NOSAVE; } /** * @since 1.7 */ - public enum MigrateOption { + enum MigrateOption { COPY, REPLACE } @@ -70,9 +71,10 @@ public interface RedisServerCommands { /** * Get time of last {@link #bgSave()} operation in seconds. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LASTSAVE */ + @Nullable Long lastSave(); /** @@ -85,9 +87,10 @@ public interface RedisServerCommands { /** * Get the total number of available keys in currently selected database. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: DBSIZE */ + @Nullable Long dbSize(); /** @@ -113,17 +116,19 @@ public interface RedisServerCommands { * *

* - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: INFO */ + @Nullable Properties info(); /** * Load server information for given {@code selection}. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: INFO */ + @Nullable Properties info(String section); /** @@ -145,16 +150,17 @@ public interface RedisServerCommands { * Load configuration parameters for given {@code pattern} from server. * * @param pattern must not be {@literal null}. - * @return never {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: CONFIG GET */ + @Nullable Properties getConfig(String pattern); /** * Set server configuration for {@code param} to {@code value}. * - * @param param - * @param value + * @param param must not be {@literal null}. + * @param value must not be {@literal null}. * @see Redis Documentation: CONFIG SET */ void setConfig(String param, String value); @@ -170,10 +176,11 @@ public interface RedisServerCommands { /** * Request server timestamp using {@code TIME} command. * - * @return current server time in milliseconds. + * @return current server time in milliseconds or {@literal null} when used in pipeline / transaction. * @since 1.1 * @see Redis Documentation: TIME */ + @Nullable Long time(); /** @@ -199,18 +206,20 @@ public interface RedisServerCommands { * Returns the name of the current connection. * * @see Redis Documentation: CLIENT GETNAME - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.3 */ + @Nullable String getClientName(); /** * Request information and statistics about connected clients. * - * @return {@link List} of {@link RedisClientInfo} objects. + * @return {@link List} of {@link RedisClientInfo} objects or {@literal null} when used in pipeline / transaction. * @since 1.3 * @see Redis Documentation: CLIENT LIST */ + @Nullable List getClientList(); /** @@ -242,7 +251,7 @@ public interface RedisServerCommands { * @since 1.7 * @see Redis Documentation: MIGRATE */ - void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option); + void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option); /** * Atomically transfer a key from a source Redis instance to a destination Redis instance. On success the key is @@ -256,5 +265,5 @@ public interface RedisServerCommands { * @since 1.7 * @see Redis Documentation: MIGRATE */ - void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout); + void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, long timeout); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisSetCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisSetCommands.java index 461946d1f..28ffdfc6d 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisSetCommands.java @@ -20,6 +20,7 @@ import java.util.Set; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; +import org.springframework.lang.Nullable; /** * Set-specific commands supported by Redis. @@ -34,29 +35,32 @@ public interface RedisSetCommands { * Add given {@code values} to set at {@code key}. * * @param key must not be {@literal null}. - * @param values - * @return + * @param values must not be empty. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SADD */ + @Nullable Long sAdd(byte[] key, byte[]... values); /** * Remove given {@code values} from set at {@code key} and return the number of removed elements. * * @param key must not be {@literal null}. - * @param values - * @return + * @param values must not be empty. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SREM */ + @Nullable Long sRem(byte[] key, byte[]... values); /** * Remove and return a random member from set at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when key does not exist or used in pipeline / transaction. * @see Redis Documentation: SPOP */ + @Nullable byte[] sPop(byte[] key); /** @@ -64,10 +68,11 @@ public interface RedisSetCommands { * * @param key must not be {@literal null}. * @param count number of random members to pop from the set. - * @return empty {@link List} if set does not exist. Never {@literal null}. + * @return empty {@link List} if set does not exist. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SPOP * @since 2.0 */ + @Nullable List sPop(byte[] key, long count); /** @@ -75,38 +80,42 @@ public interface RedisSetCommands { * * @param srcKey must not be {@literal null}. * @param destKey must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SMOVE */ + @Nullable Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value); /** * Get size of set at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SCARD */ + @Nullable Long sCard(byte[] key); /** * Check if set at {@code key} contains {@code value}. * * @param key must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SISMEMBER */ + @Nullable Boolean sIsMember(byte[] key, byte[] value); /** * Returns the members intersecting all given sets at {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return empty {@link Set} if no intersection found. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SINTER */ + @Nullable Set sInter(byte[]... keys); /** @@ -114,18 +123,20 @@ public interface RedisSetCommands { * * @param destKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SINTERSTORE */ + @Nullable Long sInterStore(byte[] destKey, byte[]... keys); /** * Union all sets at given {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return empty {@link Set} if keys do not exist. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SUNION */ + @Nullable Set sUnion(byte[]... keys); /** @@ -133,18 +144,20 @@ public interface RedisSetCommands { * * @param destKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SUNIONSTORE */ + @Nullable Long sUnionStore(byte[] destKey, byte[]... keys); /** * Diff all sets for given {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SDIFF */ + @Nullable Set sDiff(byte[]... keys); /** @@ -152,27 +165,30 @@ public interface RedisSetCommands { * * @param destKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SDIFFSTORE */ + @Nullable Long sDiffStore(byte[] destKey, byte[]... keys); /** * Get all elements of set at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return empty {@link Set} when key does not exist. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SMEMBERS */ + @Nullable Set sMembers(byte[] key); /** * Get random element from set at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return can be {@literal null}. * @see Redis Documentation: SRANDMEMBER */ + @Nullable byte[] sRandMember(byte[] key); /** @@ -180,9 +196,10 @@ public interface RedisSetCommands { * * @param key must not be {@literal null}. * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SRANDMEMBER */ + @Nullable List sRandMember(byte[] key, long count); /** @@ -190,7 +207,7 @@ public interface RedisSetCommands { * * @param key must not be {@literal null}. * @param options must not be {@literal null}. - * @return + * @return never {@literal null}. * @since 1.4 * @see Redis Documentation: SCAN */ diff --git a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java index 489c46f3e..6963739ca 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.lang.Nullable; /** * String/Value-specific commands supported by Redis. @@ -37,28 +38,31 @@ public interface RedisStringCommands { * Get the value of {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when key does not exist or used in pipeline / transaction. * @see Redis Documentation: GET */ + @Nullable byte[] get(byte[] key); /** * Set {@code value} of {@code key} and return its old value. * * @param key must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return {@literal null} if key did not exist before or when used in pipeline / transaction. * @see Redis Documentation: GETSET */ + @Nullable byte[] getSet(byte[] key, byte[] value); /** * Get multiple {@code keys}. Values are returned in the order of the requested keys. * - * @param keys must not be {@literal null}. - * @return + * @param keys must not be {@literal null}. + * @return empty {@link List} if keys do not exist or when used in pipeline / transaction. * @see Redis Documentation: MGET */ + @Nullable List mGet(byte[]... keys); /** @@ -76,8 +80,8 @@ public interface RedisStringCommands { * * @param key must not be {@literal null}. * @param value must not be {@literal null}. - * @param expiration can be {@literal null}. Defaulted to {@link Expiration#persistent()}. - * @param option can be {@literal null}. Defaulted to {@link SetOption#UPSERT}. + * @param expiration must not be {@literal null}. Use {@link Expiration#persistent()} to not set any ttl. + * @param option must not be {@literal null}. Use {@link SetOption#upsert()} to add non existing. * @since 1.7 * @see Redis Documentation: SET */ @@ -117,7 +121,7 @@ public interface RedisStringCommands { /** * Set multiple keys to multiple values using key-value pairs provided in {@code tuple}. * - * @param tuple must not be {@literal null}. + * @param tuple must not be {@literal null}. * @see Redis Documentation: MSET */ void mSet(Map tuple); @@ -164,7 +168,7 @@ public interface RedisStringCommands { * Decrement an integer value stored as string value of {@code key} by 1. * * @param key must not be {@literal null}. - * @return + * @return never {@literal null}. * @see Redis Documentation: DECR */ Long decr(byte[] key); @@ -174,7 +178,7 @@ public interface RedisStringCommands { * * @param key must not be {@literal null}. * @param value - * @return + * @return never {@literal null}. * @see Redis Documentation: DECRBY */ Long decrBy(byte[] key, long value); @@ -183,8 +187,8 @@ public interface RedisStringCommands { * Append a {@code value} to {@code key}. * * @param key must not be {@literal null}. - * @param value - * @return + * @param value must not be {@literal null}. + * @return never {@literal null}. * @see Redis Documentation: APPEND */ Long append(byte[] key, byte[] value); @@ -215,7 +219,7 @@ public interface RedisStringCommands { * * @param key must not be {@literal null}. * @param offset - * @return + * @return never {@literal null}. * @see Redis Documentation: GETBIT */ Boolean getBit(byte[] key, long offset); @@ -235,7 +239,7 @@ public interface RedisStringCommands { * Count the number of set bits (population counting) in value stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return never {@literal null}. * @see Redis Documentation: BITCOUNT */ Long bitCount(byte[] key); @@ -247,7 +251,7 @@ public interface RedisStringCommands { * @param key must not be {@literal null}. * @param begin * @param end - * @return + * @return never {@literal null}. * @see Redis Documentation: BITCOUNT */ Long bitCount(byte[] key, long begin, long end); @@ -255,10 +259,10 @@ public interface RedisStringCommands { /** * Perform bitwise operations between strings. * - * @param op must not be {@literal null}. + * @param op must not be {@literal null}. * @param destination must not be {@literal null}. * @param keys must not be {@literal null}. - * @return + * @return never {@literal null}. * @see Redis Documentation: BITOP */ Long bitOp(BitOperation op, byte[] destination, byte[]... keys); diff --git a/src/main/java/org/springframework/data/redis/connection/RedisSubscribedConnectionException.java b/src/main/java/org/springframework/data/redis/connection/RedisSubscribedConnectionException.java index b87d9cea9..0bb927f01 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisSubscribedConnectionException.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisSubscribedConnectionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -16,11 +16,13 @@ package org.springframework.data.redis.connection; import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.lang.Nullable; /** * Exception thrown when issuing commands on a connection that is subscribed and waiting for events. * * @author Costin Leau + * @author Christoph Strobl * @see org.springframework.data.redis.connection.RedisPubSubCommands */ public class RedisSubscribedConnectionException extends InvalidDataAccessApiUsageException { @@ -31,7 +33,7 @@ public class RedisSubscribedConnectionException extends InvalidDataAccessApiUsag * @param msg * @param cause */ - public RedisSubscribedConnectionException(String msg, Throwable cause) { + public RedisSubscribedConnectionException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java index d67b238f1..99a761882 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java @@ -19,6 +19,7 @@ import java.util.Set; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -44,8 +45,14 @@ public interface RedisZSetCommands { */ interface Tuple extends Comparable { + /** + * @return the raw value of the member. + */ byte[] getValue(); + /** + * @return the member score value used for sorting. + */ Double getScore(); } @@ -57,8 +64,8 @@ public interface RedisZSetCommands { */ class Range { - Boundary min; - Boundary max; + @Nullable Boundary min; + @Nullable Boundary max; /** * @return new {@link Range} @@ -81,8 +88,8 @@ public interface RedisZSetCommands { /** * Greater Than Equals * - * @param min - * @return + * @param min must not be {@literal null}. + * @return this. */ public Range gte(Object min) { @@ -94,8 +101,8 @@ public interface RedisZSetCommands { /** * Greater Than * - * @param min - * @return + * @param min must not be {@literal null}. + * @return this. */ public Range gt(Object min) { @@ -107,8 +114,8 @@ public interface RedisZSetCommands { /** * Less Then Equals * - * @param max - * @return + * @param max must not be {@literal null}. + * @return this. */ public Range lte(Object max) { @@ -120,8 +127,8 @@ public interface RedisZSetCommands { /** * Less Than * - * @param max - * @return + * @param max must not be {@literal null}. + * @return this. */ public Range lt(Object max) { @@ -133,6 +140,7 @@ public interface RedisZSetCommands { /** * @return {@literal null} if not set. */ + @Nullable public Boundary getMin() { return min; } @@ -140,6 +148,7 @@ public interface RedisZSetCommands { /** * @return {@literal null} if not set. */ + @Nullable public Boundary getMax() { return max; } @@ -150,18 +159,19 @@ public interface RedisZSetCommands { */ public static class Boundary { - Object value; + @Nullable Object value; boolean including; static Boundary infinite() { return new Boundary(null, true); } - Boundary(Object value, boolean including) { + Boundary(@Nullable Object value, boolean including) { this.value = value; this.including = including; } + @Nullable public Object getValue() { return value; } @@ -179,6 +189,19 @@ public interface RedisZSetCommands { */ class Limit { + private static final Limit UNLIMITED = new Limit() { + + @Override + public int getCount() { + return -1; + } + + @Override + public int getOffset() { + return super.getOffset(); + } + }; + int offset; int count; @@ -203,6 +226,18 @@ public interface RedisZSetCommands { public int getOffset() { return offset; } + + public boolean isUnlimited() { + return this.equals(UNLIMITED); + } + + /** + * @return new {@link Limit} indicating no limit; + * @since 1.3 + */ + public static Limit unlimited() { + return UNLIMITED; + } } /** @@ -211,9 +246,10 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param score the score. * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Boolean zAdd(byte[] key, double score, byte[] value); /** @@ -221,9 +257,10 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param tuples must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Long zAdd(byte[] key, Set tuples); /** @@ -231,9 +268,10 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param values must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREM */ + @Nullable Long zRem(byte[] key, byte[]... values); /** @@ -242,19 +280,21 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param increment * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINCRBY */ + @Nullable Double zIncrBy(byte[] key, double increment, byte[] value); /** * Determine the index of element with {@code value} in a sorted set. * * @param key must not be {@literal null}. - * @param value the value. - * @return + * @param value the value. Must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANK */ + @Nullable Long zRank(byte[] key, byte[] value); /** @@ -262,9 +302,10 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANK */ + @Nullable Long zRevRank(byte[] key, byte[] value); /** @@ -273,9 +314,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set zRange(byte[] key, long start, long end); /** @@ -284,9 +327,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set zRangeWithScores(byte[] key, long start, long end); /** @@ -295,9 +340,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScore(byte[] key, double min, double max) { return zRangeByScore(key, new Range().gte(min).lte(max)); } @@ -307,12 +354,14 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScoreWithScores(byte[] key, Range range) { - return zRangeByScoreWithScores(key, range, null); + return zRangeByScoreWithScores(key, range, Limit.unlimited()); } /** @@ -321,9 +370,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScoreWithScores(byte[] key, double min, double max) { return zRangeByScoreWithScores(key, new Range().gte(min).lte(max)); } @@ -337,9 +388,11 @@ public interface RedisZSetCommands { * @param max * @param offset * @param count - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScore(byte[] key, double min, double max, long offset, long count) { return zRangeByScore(key, new Range().gte(min).lte(max), new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue())); @@ -349,14 +402,16 @@ public interface RedisZSetCommands { * Get set of {@link Tuple}s in range from {@code start} to {@code end} where score is between {@code min} and * {@code max} from sorted set. * - * @param key + * @param key must not be {@literal null}. * @param min * @param max * @param offset * @param count - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { return zRangeByScoreWithScores(key, new Range().gte(min).lte(max), new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue())); @@ -368,11 +423,13 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit - * @return + * @param limit must not be {@literal null}. + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set zRangeByScoreWithScores(byte[] key, Range range, Limit limit); /** @@ -381,9 +438,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set zRevRange(byte[] key, long start, long end); /** @@ -392,9 +451,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set zRevRangeWithScores(byte[] key, long start, long end); /** @@ -403,9 +464,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable default Set zRevRangeByScore(byte[] key, double min, double max) { return zRevRangeByScore(key, new Range().gte(min).lte(max)); } @@ -416,12 +479,14 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @since 1.6 * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable default Set zRevRangeByScore(byte[] key, Range range) { - return zRevRangeByScore(key, range, null); + return zRevRangeByScore(key, range, Limit.unlimited()); } /** @@ -431,11 +496,13 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return empty {@link Set} when key does not exists or no members in range. {@literal null} when used in pipeline / + * transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable default Set zRevRangeByScoreWithScores(byte[] key, double min, double max) { - return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max), null); + return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max), Limit.unlimited()); } /** @@ -447,9 +514,10 @@ public interface RedisZSetCommands { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable default Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count) { return zRevRangeByScore(key, new Range().gte(min).lte(max), @@ -462,11 +530,12 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit - * @return + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set zRevRangeByScore(byte[] key, Range range, Limit limit); /** @@ -478,9 +547,10 @@ public interface RedisZSetCommands { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable default Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max), @@ -493,12 +563,13 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable default Set zRevRangeByScoreWithScores(byte[] key, Range range) { - return zRevRangeByScoreWithScores(key, range, null); + return zRevRangeByScoreWithScores(key, range, Limit.unlimited()); } /** @@ -507,11 +578,12 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit - * @return + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit); /** @@ -520,9 +592,10 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCOUNT */ + @Nullable default Long zCount(byte[] key, double min, double max) { return zCount(key, new Range().gte(min).lte(max)); } @@ -532,19 +605,21 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZCOUNT */ + @Nullable Long zCount(byte[] key, Range range); /** * Get the size of sorted set with {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCARD */ + @Nullable Long zCard(byte[] key); /** @@ -552,9 +627,10 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZSCORE */ + @Nullable Double zScore(byte[] key, byte[] value); /** @@ -563,9 +639,10 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREMRANGEBYRANK */ + @Nullable Long zRemRange(byte[] key, long start, long end); /** @@ -574,9 +651,10 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREMRANGEBYSCORE */ + @Nullable default Long zRemRangeByScore(byte[] key, double min, double max) { return zRemRangeByScore(key, new Range().gte(min).lte(max)); } @@ -586,10 +664,11 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZREMRANGEBYSCORE */ + @Nullable Long zRemRangeByScore(byte[] key, Range range); /** @@ -597,9 +676,10 @@ public interface RedisZSetCommands { * * @param destKey must not be {@literal null}. * @param sets must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZUNIONSTORE */ + @Nullable Long zUnionStore(byte[] destKey, byte[]... sets); /** @@ -609,9 +689,10 @@ public interface RedisZSetCommands { * @param aggregate must not be {@literal null}. * @param weights * @param sets must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZUNIONSTORE */ + @Nullable Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets); /** @@ -619,9 +700,10 @@ public interface RedisZSetCommands { * * @param destKey must not be {@literal null}. * @param sets must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINTERSTORE */ + @Nullable Long zInterStore(byte[] destKey, byte[]... sets); /** @@ -634,6 +716,7 @@ public interface RedisZSetCommands { * @return * @see Redis Documentation: ZINTERSTORE */ + @Nullable Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets); /** @@ -653,10 +736,11 @@ public interface RedisZSetCommands { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.5 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScore(byte[] key, String min, String max) { return zRangeByScore(key, new Range().gte(min).lte(max)); } @@ -666,12 +750,13 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable default Set zRangeByScore(byte[] key, Range range) { - return zRangeByScore(key, range, null); + return zRangeByScore(key, range, Limit.unlimited()); } /** @@ -683,10 +768,11 @@ public interface RedisZSetCommands { * @param max must not be {@literal null}. * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.5 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set zRangeByScore(byte[] key, String min, String max, long offset, long count); /** @@ -695,21 +781,23 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param limit - * @return + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set zRangeByScore(byte[] key, Range range, Limit limit); /** * Get all the elements in the sorted set at {@literal key} in lexicographical ordering. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable default Set zRangeByLex(byte[] key) { return zRangeByLex(key, Range.unbounded()); } @@ -719,12 +807,13 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable default Set zRangeByLex(byte[] key, Range range) { - return zRangeByLex(key, range, null); + return zRangeByLex(key, range, Limit.unlimited()); } /** @@ -733,11 +822,12 @@ public interface RedisZSetCommands { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. - * @param range can be {@literal null}. - * @return + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.6 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable Set zRangeByLex(byte[] key, Range range, Limit limit); } diff --git a/src/main/java/org/springframework/data/redis/connection/ReturnType.java b/src/main/java/org/springframework/data/redis/connection/ReturnType.java index cf7162624..b125eb551 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReturnType.java +++ b/src/main/java/org/springframework/data/redis/connection/ReturnType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -17,11 +17,14 @@ package org.springframework.data.redis.connection; import java.util.List; +import org.springframework.lang.Nullable; + /** * Represents a data type returned from Redis, currently used to denote the expected return type of Redis scripting * commands * * @author Jennifer Hickey + * @author Christoph Strobl */ public enum ReturnType { @@ -50,7 +53,12 @@ public enum ReturnType { */ VALUE; - public static ReturnType fromJavaType(Class javaType) { + /** + * @param javaType can be {@literal null} which translates to {@link ReturnType#STATUS}. + * @return never {@literal null}. + */ + public static ReturnType fromJavaType(@Nullable Class javaType) { + if (javaType == null) { return ReturnType.STATUS; } diff --git a/src/main/java/org/springframework/data/redis/connection/SortParameters.java b/src/main/java/org/springframework/data/redis/connection/SortParameters.java index 150205d84..81b64a737 100644 --- a/src/main/java/org/springframework/data/redis/connection/SortParameters.java +++ b/src/main/java/org/springframework/data/redis/connection/SortParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -15,24 +15,28 @@ */ package org.springframework.data.redis.connection; +import org.springframework.lang.Nullable; + /** * Entity containing the parameters for the SORT operation. - * + * * @author Costin Leau + * @author Christoph Strobl */ public interface SortParameters { /** * Sorting order. */ - public enum Order { + enum Order { ASC, DESC } /** * Utility class wrapping the 'LIMIT' setting. */ - static class Range { + class Range { + private final long start; private final long count; @@ -52,37 +56,42 @@ public interface SortParameters { /** * Returns the sorting order. Can be null if nothing is specified. - * - * @return sorting order + * + * @return sorting order. {@literal null} if not set. */ + @Nullable Order getOrder(); /** * Indicates if the sorting is numeric (default) or alphabetical (lexicographical). Can be null if nothing is * specified. - * - * @return the type of sorting + * + * @return the type of sorting. {@literal null} if not set. */ + @Nullable Boolean isAlphabetic(); /** * Returns the pattern (if set) for sorting by external keys (BY). Can be null if nothing is specified. - * - * @return BY pattern. + * + * @return BY pattern. {@literal null} if not set. */ + @Nullable byte[] getByPattern(); /** * Returns the pattern (if set) for retrieving external keys (GET). Can be null if nothing is specified. - * - * @return GET pattern. + * + * @return GET pattern. {@literal null} if not set. */ + @Nullable byte[][] getGetPattern(); /** * Returns the sorting limit (range or pagination). Can be null if nothing is specified. - * - * @return sorting limit/range + * + * @return sorting limit/range. {@literal null} if not set. */ + @Nullable Range getLimit(); } diff --git a/src/main/java/org/springframework/data/redis/connection/Subscription.java b/src/main/java/org/springframework/data/redis/connection/Subscription.java index 91e380be1..1b5b9c566 100644 --- a/src/main/java/org/springframework/data/redis/connection/Subscription.java +++ b/src/main/java/org/springframework/data/redis/connection/Subscription.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -22,20 +22,21 @@ import java.util.Collection; * threads. Note that once a subscription died, it cannot accept any more subscriptions. * * @author Costin Leau + * @author Christoph Strobl */ public interface Subscription { /** * Adds the given channels to the current subscription. - * - * @param channels channel names + * + * @param channels channel names. Must not be empty. */ void subscribe(byte[]... channels) throws RedisInvalidSubscriptionException; /** * Adds the given channel patterns to the current subscription. - * - * @param patterns channel patterns + * + * @param patterns channel patterns. Must not be empty. */ void pSubscribe(byte[]... patterns) throws RedisInvalidSubscriptionException; @@ -46,8 +47,8 @@ public interface Subscription { /** * Cancels the current subscription for all given channels. - * - * @param channels channel names + * + * @param channels channel names. Must not be empty. */ void unsubscribe(byte[]... channels); @@ -58,35 +59,35 @@ public interface Subscription { /** * Cancels the subscription for all channels matching the given patterns. - * - * @param patterns + * + * @param patterns must not be empty. */ void pUnsubscribe(byte[]... patterns); /** * Returns the (named) channels for this subscription. - * + * * @return collection of named channels */ Collection getChannels(); /** * Returns the channel patters for this subscription. - * + * * @return collection of channel patterns */ Collection getPatterns(); /** * Returns the listener used for this subscription. - * + * * @return the listener used for this subscription. */ MessageListener getListener(); /** * Indicates whether this subscription is still 'alive' or not. - * + * * @return true if the subscription still applies, false otherwise. */ boolean isAlive(); diff --git a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java index 5845603a7..1bb816c17 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java @@ -46,6 +46,7 @@ import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisNode.NodeType; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.NumberUtils; @@ -95,11 +96,13 @@ abstract public class Converters { String[] args = source.split(" "); String[] hostAndPort = StringUtils.split(args[HOST_PORT_INDEX], ":"); + Assert.notNull(hostAndPort, "CusterNode information does not define host and port!"); + SlotRange range = parseSlotRange(args); Set flags = parseFlags(args); String portPart = hostAndPort[1]; - if (portPart.contains("@")) { + if (portPart != null && portPart.contains("@")) { portPart = portPart.substring(0, portPart.indexOf('@')); } @@ -211,7 +214,9 @@ abstract public class Converters { } public static Properties toProperties(Map source) { - return MAP_TO_PROPERTIES.convert(source); + + Properties properties = MAP_TO_PROPERTIES.convert(source); + return properties != null ? properties : new Properties(); } public static Boolean toBoolean(Long source) { @@ -424,7 +429,11 @@ abstract public class Converters { INSTANCE; - DistanceConverter forMetric(Metric metric) { + /** + * @param metric can be {@literal null}. Defaults to {@link DistanceUnit#METERS}. + * @return never {@literal null}. + */ + DistanceConverter forMetric(@Nullable Metric metric) { return new DistanceConverter( metric == null || ObjectUtils.nullSafeEquals(Metrics.NEUTRAL, metric) ? DistanceUnit.METERS : metric); } @@ -433,14 +442,22 @@ abstract public class Converters { private Metric metric; - public DistanceConverter(Metric metric) { + /** + * @param metric can be {@literal null}. Defaults to {@link DistanceUnit#METERS}. + * @return never {@literal null}. + */ + DistanceConverter(@Nullable Metric metric) { this.metric = metric == null || ObjectUtils.nullSafeEquals(Metrics.NEUTRAL, metric) ? DistanceUnit.METERS : metric; } + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ @Override public Distance convert(Double source) { - return source == null ? null : new Distance(source, metric); + return new Distance(source, metric); } } } @@ -456,13 +473,13 @@ abstract public class Converters { final RedisSerializer serializer; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ @Override public GeoResults> convert(GeoResults> source) { - if (source == null) { - return new GeoResults<>(Collections.>> emptyList()); - } - List>> values = new ArrayList<>(source.getContent().size()); for (GeoResult> value : source.getContent()) { diff --git a/src/main/java/org/springframework/data/redis/connection/convert/ListConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/ListConverter.java index 569075250..7f5b2f176 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/ListConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/ListConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2013-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. @@ -25,6 +25,7 @@ import org.springframework.core.convert.converter.Converter; * * @author Jennifer Hickey * @author Mark Paluch + * @author Christoph Strobl * @param The type of elements in the List to convert * @param The type of elements in the converted List */ @@ -39,12 +40,13 @@ public class ListConverter implements Converter, List> { this.itemConverter = itemConverter; } + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public List convert(List source) { - if (source == null) { - return null; - } - List results = new ArrayList<>(); for (S result : source) { results.add(itemConverter.convert(result)); diff --git a/src/main/java/org/springframework/data/redis/connection/convert/LongToBooleanConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/LongToBooleanConverter.java index 42414af66..80f80196c 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/LongToBooleanConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/LongToBooleanConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -21,11 +21,17 @@ import org.springframework.core.convert.converter.Converter; * Converts Longs to Booleans * * @author Jennifer Hickey + * @author Christoph Strobl */ public class LongToBooleanConverter implements Converter { + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public Boolean convert(Long result) { - return result != null ? result == 1 : null; + return result == 1; } } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/MapConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/MapConverter.java index 5f1163e3a..d54b98a3e 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/MapConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/MapConverter.java @@ -15,16 +15,18 @@ */ package org.springframework.data.redis.connection.convert; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.collections.map.HashedMap; import org.springframework.core.convert.converter.Converter; /** * Converts a Map of values of one key/value type to a Map of values of another type * * @author Jennifer Hickey + * @author Christoph Strobl * @param The type of keys and values in the Map to convert * @param The type of keys and values in the converted Map */ @@ -33,31 +35,24 @@ public class MapConverter implements Converter, Map> { private Converter itemConverter; /** - * @param itemConverter The {@link Converter} to use for converting individual Map keys and values + * @param itemConverter The {@link Converter} to use for converting individual Map keys and values. Must not be + * {@literal null}. */ public MapConverter(Converter itemConverter) { this.itemConverter = itemConverter; } + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public Map convert(Map source) { - if (source == null) { - return null; - } + return source.entrySet().stream() + .collect(Collectors.toMap(e -> itemConverter.convert(e.getKey()), e -> itemConverter.convert(e.getValue()), + (a, b) -> a, source instanceof LinkedHashMap ? LinkedHashMap::new : HashedMap::new)); - Map results; - - if (source instanceof LinkedHashMap) { - results = new LinkedHashMap<>(); - } else { - results = new HashMap<>(); - } - - for (Map.Entry result : source.entrySet()) { - results.put(itemConverter.convert(result.getKey()), itemConverter.convert(result.getValue())); - } - - return results; } } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/MapToPropertiesConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/MapToPropertiesConverter.java index 4c04af967..431062181 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/MapToPropertiesConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/MapToPropertiesConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-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. @@ -25,16 +25,19 @@ import org.springframework.core.convert.converter.Converter; * @since 1.4 */ public enum MapToPropertiesConverter implements Converter, Properties> { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ @Override public Properties convert(Map source) { - Properties p = new Properties(); - if (source != null) { - p.putAll(source); - } - return p; + Properties target = new Properties(); + target.putAll(source); + return target; } } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/SetConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/SetConverter.java index f6c507e93..c05c67223 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/SetConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/SetConverter.java @@ -18,13 +18,16 @@ package org.springframework.data.redis.connection.convert; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.Assert; /** * Converts a Set of values of one type to a Set of values of another type * * @author Jennifer Hickey + * @author Christoph Strobl * @param The type of elements in the Set to convert * @param The type of elements in the converted Set */ @@ -33,31 +36,23 @@ public class SetConverter implements Converter, Set> { private Converter itemConverter; /** - * @param itemConverter The {@link Converter} to use for converting individual Set items + * @param itemConverter The {@link Converter} to use for converting individual Set items. Must not be {@literal null}. */ public SetConverter(Converter itemConverter) { + + Assert.notNull(itemConverter, "ItemConverter must not be null!"); this.itemConverter = itemConverter; } + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public Set convert(Set source) { - if (source == null) { - return null; - } - - Set results; - - if (source instanceof LinkedHashSet) { - results = new LinkedHashSet<>(); - } else { - results = new HashSet<>(); - } - - for (S result : source) { - results.add(itemConverter.convert(result)); - } - - return results; + return source.stream().map(itemConverter::convert) + .collect(Collectors.toCollection(source instanceof LinkedHashSet ? LinkedHashSet::new : HashSet::new)); } } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/StringToDataTypeConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/StringToDataTypeConverter.java index 933143d5c..5d62ffa59 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/StringToDataTypeConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/StringToDataTypeConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -20,15 +20,18 @@ import org.springframework.data.redis.connection.DataType; /** * Converts Strings to {@link DataType}s - * + * * @author Jennifer Hickey + * @author Christoph Strobl */ public class StringToDataTypeConverter implements Converter { + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public DataType convert(String source) { - if (source == null) { - return null; - } return DataType.fromCode(source); } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/StringToPropertiesConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/StringToPropertiesConverter.java index ca8d99305..97d62e676 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/StringToPropertiesConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/StringToPropertiesConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -23,23 +23,24 @@ import org.springframework.data.redis.RedisSystemException; /** * Converts Strings to {@link Properties} - * + * * @author Jennifer Hickey + * @author Christoph Strobl */ public class StringToPropertiesConverter implements Converter { + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public Properties convert(String source) { - if (source == null) { - return null; - } + Properties info = new Properties(); - StringReader stringReader = new StringReader(source); - try { + try (StringReader stringReader = new StringReader(source)) { info.load(stringReader); } catch (Exception ex) { throw new RedisSystemException("Cannot read Redis info", ex); - } finally { - stringReader.close(); } return info; } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/StringToRedisClientInfoConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/StringToRedisClientInfoConverter.java index 684b8df70..696a31036 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/StringToRedisClientInfoConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/StringToRedisClientInfoConverter.java @@ -16,7 +16,6 @@ package org.springframework.data.redis.connection.convert; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.springframework.core.convert.converter.Converter; @@ -36,19 +35,19 @@ import org.springframework.data.redis.core.types.RedisClientInfo.RedisClientInfo */ public class StringToRedisClientInfoConverter implements Converter> { + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ @Override public List convert(String[] lines) { - if (lines == null) { - return Collections.emptyList(); - } - - List infos = new ArrayList<>(lines.length); + List clientInfoList = new ArrayList<>(lines.length); for (String line : lines) { - infos.add(RedisClientInfoBuilder.fromString(line)); + clientInfoList.add(RedisClientInfoBuilder.fromString(line)); } - return infos; + return clientInfoList; } } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/TransactionResultConverter.java b/src/main/java/org/springframework/data/redis/connection/convert/TransactionResultConverter.java index 0efb608ce..ac92e886c 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/TransactionResultConverter.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/TransactionResultConverter.java @@ -22,6 +22,7 @@ import java.util.Queue; import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.RedisSystemException; import org.springframework.data.redis.connection.FutureResult; /** @@ -29,6 +30,7 @@ import org.springframework.data.redis.connection.FutureResult; * objects returned in the list as well, using the supplied Exception {@link Converter} * * @author Jennifer Hickey + * @author Christoph Strobl * @param The type of {@link FutureResult} of the individual tx operations */ public class TransactionResultConverter implements Converter, List> { @@ -39,19 +41,22 @@ public class TransactionResultConverter implements Converter, Li public TransactionResultConverter(Queue> txResults, Converter exceptionConverter) { + this.txResults = txResults; this.exceptionConverter = exceptionConverter; } + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(Object) + */ + @Override public List convert(List execResults) { - if (execResults == null) { - return null; - } - if (execResults.size() != txResults.size()) { - throw new IllegalArgumentException("Incorrect number of transaction results. Expected: " + txResults.size() - + " Actual: " + execResults.size()); + + throw new IllegalArgumentException( + "Incorrect number of transaction results. Expected: " + txResults.size() + " Actual: " + execResults.size()); } List convertedResults = new ArrayList<>(); @@ -59,7 +64,11 @@ public class TransactionResultConverter implements Converter, Li for (Object result : execResults) { FutureResult futureResult = txResults.remove(); if (result instanceof Exception) { - throw exceptionConverter.convert((Exception) result); + + Exception source = (Exception) result; + DataAccessException convertedException = exceptionConverter.convert(source); + throw convertedException != null ? convertedException + : new RedisSystemException("Error reading future result.", source); } if (!(futureResult.isStatus())) { convertedResults.add(futureResult.convert(result)); diff --git a/src/main/java/org/springframework/data/redis/connection/convert/package-info.java b/src/main/java/org/springframework/data/redis/connection/convert/package-info.java new file mode 100644 index 000000000..51cc4f0bf --- /dev/null +++ b/src/main/java/org/springframework/data/redis/connection/convert/package-info.java @@ -0,0 +1,5 @@ +/** + * Redis specific converters used for sending data and parsing responses. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.connection.convert; diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java index 0e9426763..408dd47d2 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java @@ -23,11 +23,13 @@ import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.lang.Nullable; /** * Default implementation of {@literal JedisClientConfiguration}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ class DefaultJedisClientConfiguration implements JedisClientConfiguration { @@ -42,9 +44,10 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { private final Duration readTimeout; private final Duration connectTimeout; - DefaultJedisClientConfiguration(boolean useSsl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, - HostnameVerifier hostnameVerifier, boolean usePooling, GenericObjectPoolConfig poolConfig, String clientName, - Duration readTimeout, Duration connectTimeout) { + DefaultJedisClientConfiguration(boolean useSsl, @Nullable SSLSocketFactory sslSocketFactory, + @Nullable SSLParameters sslParameters, @Nullable HostnameVerifier hostnameVerifier, boolean usePooling, + @Nullable GenericObjectPoolConfig poolConfig, @Nullable String clientName, Duration readTimeout, + Duration connectTimeout) { this.useSsl = useSsl; this.sslSocketFactory = Optional.ofNullable(sslSocketFactory); @@ -57,7 +60,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { this.connectTimeout = connectTimeout; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#useSsl() */ @Override @@ -65,7 +69,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return useSsl; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getSslSocketFactory() */ @Override @@ -73,7 +78,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return sslSocketFactory; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getSslParameters() */ @Override @@ -81,7 +87,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return sslParameters; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getHostnameVerifier() */ @Override @@ -89,7 +96,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return hostnameVerifier; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#usePooling() */ @Override @@ -97,7 +105,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return usePooling; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getPoolConfig() */ @Override @@ -105,7 +114,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return poolConfig; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getClientName() */ @Override @@ -113,7 +123,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return clientName; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getReadTimeout() */ @Override @@ -121,7 +132,8 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { return readTimeout; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getConnectTimeout() */ @Override diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java index b669e1dd8..9ab7071af 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java @@ -27,6 +27,7 @@ import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -263,12 +264,12 @@ public interface JedisClientConfiguration { JedisPoolingClientConfigurationBuilder, JedisSslClientConfigurationBuilder { private boolean useSsl; - private SSLSocketFactory sslSocketFactory; - private SSLParameters sslParameters; - private HostnameVerifier hostnameVerifier; + private @Nullable SSLSocketFactory sslSocketFactory; + private @Nullable SSLParameters sslParameters; + private @Nullable HostnameVerifier hostnameVerifier; private boolean usePooling; private GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); - private String clientName; + private @Nullable String clientName; private Duration readTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); private Duration connectTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java index 9620cacb0..06417c3ac 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.connection.jedis; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.lang.Nullable; import redis.clients.jedis.BinaryJedis; import redis.clients.jedis.BinaryJedisPubSub; import redis.clients.jedis.HostAndPort; @@ -74,7 +76,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { private ClusterCommandExecutor clusterCommandExecutor; private final boolean disposeClusterCommandExecutorOnClose; - private volatile JedisSubscription subscription; + private volatile @Nullable JedisSubscription subscription; /** * Create new {@link JedisClusterConnection} utilizing native connections via {@link JedisCluster}. @@ -810,7 +812,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { return connection; } - throw new IllegalStateException(String.format("Node %s is unknown to cluster", node)); + throw new DataAccessResourceFailureException(String.format("Node %s is unknown to cluster", node)); } private JedisPool getResourcePoolForSpecificNode(RedisClusterNode node) { @@ -855,7 +857,7 @@ public class JedisClusterConnection implements DefaultedRedisClusterConnection { private final Object lock = new Object(); private final JedisCluster cluster; private long time = 0; - private ClusterTopology cached; + private @Nullable ClusterTopology cached; /** * Create new {@link JedisClusterTopologyProvider}.s diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java index ac7cdb23a..b17f2f988 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterServerCommands.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.connection.jedis; +import org.springframework.lang.Nullable; import redis.clients.jedis.BinaryJedis; import java.util.ArrayList; @@ -477,7 +478,7 @@ class JedisClusterServerCommands implements RedisClusterServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option) { migrate(key, target, dbIndex, option, Long.MAX_VALUE); } @@ -486,7 +487,7 @@ class JedisClusterServerCommands implements RedisClusterServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) */ @Override - public void migrate(final byte[] key, final RedisNode target, final int dbIndex, final MigrateOption option, + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, final long timeout) { final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java index 9d903b21c..6e4db6027 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java @@ -156,11 +156,11 @@ class JedisClusterZSetCommands implements RedisZSetCommands { byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES); try { - if (limit != null) { - return JedisConverters.toTupleSet( - connection.getCluster().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount())); + if (limit.isUnlimited()) { + return JedisConverters.toTupleSet(connection.getCluster().zrangeByScoreWithScores(key, min, max)); } - return JedisConverters.toTupleSet(connection.getCluster().zrangeByScoreWithScores(key, min, max)); + return JedisConverters.toTupleSet( + connection.getCluster().zrangeByScoreWithScores(key, min, max, limit.getOffset(), limit.getCount())); } catch (Exception ex) { throw convertJedisAccessException(ex); } @@ -178,10 +178,10 @@ class JedisClusterZSetCommands implements RedisZSetCommands { byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES); try { - if (limit != null) { - return connection.getCluster().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount()); + if (limit.isUnlimited()) { + return connection.getCluster().zrevrangeByScore(key, max, min); } - return connection.getCluster().zrevrangeByScore(key, max, min); + return connection.getCluster().zrevrangeByScore(key, max, min, limit.getOffset(), limit.getCount()); } catch (Exception ex) { throw convertJedisAccessException(ex); } @@ -200,11 +200,11 @@ class JedisClusterZSetCommands implements RedisZSetCommands { byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES); try { - if (limit != null) { - return JedisConverters.toTupleSet( - connection.getCluster().zrevrangeByScoreWithScores(key, max, min, limit.getOffset(), limit.getCount())); + if (limit.isUnlimited()) { + return JedisConverters.toTupleSet(connection.getCluster().zrevrangeByScoreWithScores(key, max, min)); } - return JedisConverters.toTupleSet(connection.getCluster().zrevrangeByScoreWithScores(key, max, min)); + return JedisConverters.toTupleSet( + connection.getCluster().zrevrangeByScoreWithScores(key, max, min, limit.getOffset(), limit.getCount())); } catch (Exception ex) { throw convertJedisAccessException(ex); } @@ -262,10 +262,10 @@ class JedisClusterZSetCommands implements RedisZSetCommands { byte[] max = JedisConverters.boundaryToBytesForZRange(range.getMax(), JedisConverters.POSITIVE_INFINITY_BYTES); try { - if (limit != null) { - return connection.getCluster().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount()); + if (limit.isUnlimited()) { + return connection.getCluster().zrangeByScore(key, min, max); } - return connection.getCluster().zrangeByScore(key, min, max); + return connection.getCluster().zrangeByScore(key, min, max, limit.getOffset(), limit.getCount()); } catch (Exception ex) { throw convertJedisAccessException(ex); } @@ -279,15 +279,16 @@ class JedisClusterZSetCommands implements RedisZSetCommands { public Set zRangeByLex(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX."); + Assert.notNull(limit, "Limit must not be null!"); byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.toBytes("-")); byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.toBytes("+")); try { - if (limit != null) { - return connection.getCluster().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount()); + if (limit.isUnlimited()) { + return connection.getCluster().zrangeByLex(key, min, max); } - return connection.getCluster().zrangeByLex(key, min, max); + return connection.getCluster().zrangeByLex(key, min, max, limit.getOffset(), limit.getCount()); } catch (Exception ex) { throw convertJedisAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index d1c7faaa0..de5df8c40 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -45,6 +45,7 @@ import org.springframework.data.redis.FallbackExceptionTranslationStrategy; import org.springframework.data.redis.RedisConnectionFailureException; import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.convert.TransactionResultConverter; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; @@ -100,14 +101,14 @@ public class JedisConnection extends AbstractRedisConnection { private final Jedis jedis; private final Client client; - private Transaction transaction; + private @Nullable Transaction transaction; private final Pool pool; /** * flag indicating whether the connection needs to be dropped or not */ private boolean broken = false; - private volatile JedisSubscription subscription; - private volatile Pipeline pipeline; + private volatile @Nullable JedisSubscription subscription; + private volatile @Nullable Pipeline pipeline; private final int dbIndex; private final String clientName; private boolean convertPipelineAndTxResults = true; @@ -125,10 +126,13 @@ public class JedisConnection extends AbstractRedisConnection { @SuppressWarnings("unchecked") public Object get() { - if (convertPipelineAndTxResults && converter != null) { - return converter.convert(resultHolder.get()); + + Object raw = resultHolder.get(); + if (!convertPipelineAndTxResults || raw == null) { + return raw; } - return resultHolder.get(); + + return converter != null ? converter.convert(raw) : raw; } } @@ -594,10 +598,12 @@ public class JedisConnection extends AbstractRedisConnection { } } + @Nullable public Pipeline getPipeline() { return pipeline; } + @Nullable public Transaction getTransaction() { return transaction; } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java index e4c801ccf..ee340a4da 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.connection.jedis; +import org.springframework.lang.Nullable; import redis.clients.jedis.Client; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; @@ -91,16 +92,16 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, JedisConverters.exceptionConverter()); private final JedisClientConfiguration clientConfiguration; - private JedisShardInfo shardInfo; + private @Nullable JedisShardInfo shardInfo; private boolean providedShardInfo = false; - private Pool pool; + private @Nullable Pool pool; private boolean convertPipelineAndTxResults = true; private RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration("localhost", Protocol.DEFAULT_PORT); - private RedisSentinelConfiguration sentinelConfig; - private RedisClusterConfiguration clusterConfig; - private JedisCluster cluster; - private ClusterCommandExecutor clusterCommandExecutor; + private @Nullable RedisSentinelConfiguration sentinelConfig; + private @Nullable RedisClusterConfiguration clusterConfig; + private @Nullable JedisCluster cluster; + private @Nullable ClusterCommandExecutor clusterCommandExecutor; /** * Constructs a new JedisConnectionFactory instance with default settings (default connection pooling, no @@ -609,6 +610,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, * @deprecated since 2.0. */ @Deprecated + @Nullable public JedisShardInfo getShardInfo() { return shardInfo; } @@ -896,12 +898,12 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, static class MutableJedisClientConfiguration implements JedisClientConfiguration { private boolean useSsl; - private SSLSocketFactory sslSocketFactory; - private SSLParameters sslParameters; - private HostnameVerifier hostnameVerifier; + private @Nullable SSLSocketFactory sslSocketFactory; + private @Nullable SSLParameters sslParameters; + private @Nullable HostnameVerifier hostnameVerifier; private boolean usePooling = true; private GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); - private String clientName; + private @Nullable String clientName; private Duration readTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); private Duration connectTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java index a66303a83..e90a6361c 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisServerCommands.java @@ -24,6 +24,7 @@ import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult; import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -453,7 +454,7 @@ class JedisServerCommands implements RedisServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option) { migrate(key, target, dbIndex, option, Long.MAX_VALUE); } @@ -462,7 +463,7 @@ class JedisServerCommands implements RedisServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, long timeout) { final int timeoutToUse = timeout <= Integer.MAX_VALUE ? (int) timeout : Integer.MAX_VALUE; diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java index cc78a8197..2f523eb56 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisStringCommands.java @@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.redis.connection.RedisStringCommands; import org.springframework.data.redis.connection.jedis.JedisConnection.JedisResult; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -114,9 +115,12 @@ class JedisStringCommands implements RedisStringCommands { @Override public void set(byte[] key, byte[] value, Expiration expiration, SetOption option) { - if (expiration == null || expiration.isPersistent()) { + Assert.notNull(expiration, "Expiration must not be null!"); + Assert.notNull(option, "Option must not be null!"); - if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) { + if (expiration.isPersistent()) { + + if (ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) { set(key, value); } else { @@ -143,7 +147,7 @@ class JedisStringCommands implements RedisStringCommands { } else { - if (option == null || ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) { + if (ObjectUtils.nullSafeEquals(SetOption.UPSERT, option)) { if (ObjectUtils.nullSafeEquals(TimeUnit.MILLISECONDS, expiration.getTimeUnit())) { pSetEx(key, expiration.getExpirationTime(), value); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/package-info.java b/src/main/java/org/springframework/data/redis/connection/jedis/package-info.java index 9bac91781..ad559c158 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/package-info.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/package-info.java @@ -1,5 +1,5 @@ /** * Connection package for Jedis library. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.connection.jedis; - diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java index 91d705c0a..8e4b29e8d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java @@ -21,6 +21,8 @@ import io.lettuce.core.resource.ClientResources; import java.time.Duration; import java.util.Optional; +import org.springframework.lang.Nullable; + /** * Default implementation of {@literal LettuceClientConfiguration}. * @@ -39,7 +41,8 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration { private final Duration shutdownTimeout; DefaultLettuceClientConfiguration(boolean useSsl, boolean verifyPeer, boolean startTls, - ClientResources clientResources, ClientOptions clientOptions, Duration timeout, Duration shutdownTimeout) { + @Nullable ClientResources clientResources, @Nullable ClientOptions clientOptions, Duration timeout, + Duration shutdownTimeout) { this.useSsl = useSsl; this.verifyPeer = verifyPeer; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java index 7701a5e6a..7fffeae27 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java @@ -31,6 +31,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.InitializingBean; import org.springframework.data.redis.connection.PoolException; import org.springframework.data.redis.connection.RedisSentinelConfiguration; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -46,16 +47,16 @@ import org.springframework.util.StringUtils; public class DefaultLettucePool implements LettucePool, InitializingBean { @SuppressWarnings("rawtypes") // - private GenericObjectPool> internalPool; - private RedisClient client; + private @Nullable GenericObjectPool> internalPool; + private @Nullable RedisClient client; private int dbIndex = 0; private GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); private String hostName = "localhost"; private int port = 6379; - private String password; + private @Nullable String password; private long timeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS); - private RedisSentinelConfiguration sentinelConfiguration; - private ClientResources clientResources; + private @Nullable RedisSentinelConfiguration sentinelConfiguration; + private @Nullable ClientResources clientResources; /** * Constructs a new DefaultLettucePool instance with default settings. @@ -128,8 +129,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { private RedisURI getRedisURI() { RedisURI redisUri = isRedisSentinelAware() - ? LettuceConverters.sentinelConfigurationToRedisURI(sentinelConfiguration) - : createSimpleHostRedisURI(); + ? LettuceConverters.sentinelConfigurationToRedisURI(sentinelConfiguration) : createSimpleHostRedisURI(); if (StringUtils.hasText(password)) { redisUri.setPassword(password); @@ -202,6 +202,8 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { /** * @return The Redis client */ + @Override + @Nullable public RedisClient getClient() { return client; } @@ -244,6 +246,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { * * @return password for authentication */ + @Nullable public String getPassword() { return password; } @@ -317,6 +320,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean { * @return {@literal null} if not set. * @since 1.7 */ + @Nullable public ClientResources getClientResources() { return clientResources; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java index b3f556bd0..7a3ba0e08 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java @@ -23,6 +23,7 @@ import java.time.Duration; import java.util.Optional; import java.util.concurrent.TimeUnit; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -129,8 +130,8 @@ public interface LettuceClientConfiguration { boolean useSsl; boolean verifyPeer = true; boolean startTls; - ClientResources clientResources; - ClientOptions clientOptions; + @Nullable ClientResources clientResources; + @Nullable ClientOptions clientOptions; Duration timeout = Duration.ofSeconds(RedisURI.DEFAULT_TIMEOUT); Duration shutdownTimeout = Duration.ofMillis(100); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java index d93f398c2..7073e0fe4 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java @@ -36,6 +36,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.PassThroughExceptionTranslationStrategy; @@ -45,6 +46,7 @@ import org.springframework.data.redis.connection.ClusterCommandExecutor.MultiKey import org.springframework.data.redis.connection.ClusterCommandExecutor.NodeResult; import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; import org.springframework.data.redis.connection.convert.Converters; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -608,7 +610,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau static class LettuceClusterNodeResourceProvider implements ClusterNodeResourceProvider, DisposableBean { private final LettuceConnectionProvider connectionProvider; - private volatile StatefulRedisClusterConnection connection; + private volatile @Nullable StatefulRedisClusterConnection connection; @Override @SuppressWarnings("unchecked") @@ -627,12 +629,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau try { return connection.getConnection(node.getHost(), node.getPort()).sync(); } catch (RedisException e) { - - // unwrap cause when cluster node not known in cluster - if (e.getCause() instanceof IllegalArgumentException) { - throw (IllegalArgumentException) e.getCause(); - } - throw e; + throw new DataAccessResourceFailureException(e.getMessage(), e); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index f50ce9fa7..7a0d412f4 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -66,6 +66,7 @@ import org.springframework.data.redis.connection.convert.TransactionResultConver import org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider.TargetAware; import org.springframework.data.redis.core.RedisCommand; import org.springframework.data.redis.core.ScanOptions; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -95,7 +96,7 @@ public class LettuceConnection extends AbstractRedisConnection { private final LettuceConnectionProvider connectionProvider; private final StatefulConnection asyncSharedConn; - private StatefulConnection asyncDedicatedConn; + private @Nullable StatefulConnection asyncDedicatedConn; private final long timeout; @@ -103,9 +104,9 @@ public class LettuceConnection extends AbstractRedisConnection { private boolean isClosed = false; private boolean isMulti = false; private boolean isPipelined = false; - private List ppline; + private @Nullable List ppline; private Queue> txResults = new LinkedList<>(); - private volatile LettuceSubscription subscription; + private volatile @Nullable LettuceSubscription subscription; /** flag indicating whether the connection needs to be dropped or not */ private boolean convertPipelineAndTxResults = true; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java index 3ecb738e8..9c93cd6d1 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java @@ -42,6 +42,7 @@ import org.springframework.data.redis.ExceptionTranslationStrategy; import org.springframework.data.redis.PassThroughExceptionTranslationStrategy; import org.springframework.data.redis.RedisConnectionFailureException; import org.springframework.data.redis.connection.*; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -81,20 +82,20 @@ public class LettuceConnectionFactory private final Log log = LogFactory.getLog(getClass()); private final LettuceClientConfiguration clientConfiguration; - private AbstractRedisClient client; - private LettuceConnectionProvider connectionProvider; - private LettuceConnectionProvider reactiveConnectionProvider; + private @Nullable AbstractRedisClient client; + private @Nullable LettuceConnectionProvider connectionProvider; + private @Nullable LettuceConnectionProvider reactiveConnectionProvider; private boolean validateConnection = false; private boolean shareNativeConnection = true; - private StatefulRedisConnection connection; - private LettucePool pool; + private @Nullable StatefulRedisConnection connection; + private @Nullable LettucePool pool; /** Synchronization monitor for the shared Connection */ private final Object connectionMonitor = new Object(); private boolean convertPipelineAndTxResults = true; private RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration("localhost", 6379); - private RedisSentinelConfiguration sentinelConfiguration; - private RedisClusterConfiguration clusterConfiguration; - private ClusterCommandExecutor clusterCommandExecutor; + private @Nullable RedisSentinelConfiguration sentinelConfiguration; + private @Nullable RedisClusterConfiguration clusterConfiguration; + private @Nullable ClusterCommandExecutor clusterCommandExecutor; /** * Constructs a new {@link LettuceConnectionFactory} instance with default settings. @@ -697,6 +698,7 @@ public class LettuceConnectionFactory * @return the {@link RedisStandaloneConfiguration}, may be {@literal null}. * @since 2.0 */ + @Nullable public RedisSentinelConfiguration getSentinelConfiguration() { return sentinelConfiguration; } @@ -705,6 +707,7 @@ public class LettuceConnectionFactory * @return the {@link RedisClusterConfiguration}, may be {@literal null}. * @since 2.0 */ + @Nullable public RedisClusterConfiguration getClusterConfiguration() { return clusterConfiguration; } @@ -893,7 +896,7 @@ public class LettuceConnectionFactory private boolean useSsl; private boolean verifyPeer = true; private boolean startTls; - private ClientResources clientResources; + private @Nullable ClientResources clientResources; private Duration timeout = Duration.ofSeconds(RedisURI.DEFAULT_TIMEOUT); private Duration shutdownTimeout = Duration.ofMillis(100); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java index 48f0cb42b..3d0254bb0 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java @@ -60,6 +60,7 @@ import org.springframework.data.redis.connection.convert.StringToRedisClientInfo import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.data.redis.util.ByteUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -721,7 +722,7 @@ abstract public class LettuceConverters extends Converters { * @param option can be {@literal null}. * @since 1.7 */ - public static SetArgs toSetArgs(Expiration expiration, SetOption option) { + public static SetArgs toSetArgs(@Nullable Expiration expiration, @Nullable SetOption option) { SetArgs args = new SetArgs(); if (expiration != null && !expiration.isPersistent()) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePool.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePool.java index f60a1eb51..a6023441b 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePool.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePool.java @@ -19,6 +19,7 @@ import io.lettuce.core.AbstractRedisClient; import io.lettuce.core.api.StatefulConnection; import org.springframework.data.redis.connection.Pool; +import org.springframework.lang.Nullable; /** * Pool of Lettuce {@link StatefulConnection}s @@ -34,6 +35,7 @@ public interface LettucePool extends Pool> { /** * @return The {@link AbstractRedisClient} used to create pooled connections */ + @Nullable AbstractRedisClient getClient(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java index feb4837b2..0a5ba80c0 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java @@ -317,7 +317,8 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands { Assert.notNull(command.getKey(), "Key must not be null!"); Range range = command.getRange(); - return (range != null ? cmd.bitcount(command.getKey(), range.getLowerBound().getValue().orElse(null), + + return (!Range.unbounded().equals(range) ? cmd.bitcount(command.getKey(), range.getLowerBound().getValue().orElse(null), range.getUpperBound().getValue().orElse(null)) : cmd.bitcount(command.getKey())) .map(responseValue -> new NumericResponse<>(command, responseValue)); })); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java index 117bb7844..33d7d8252 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java @@ -229,7 +229,7 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands { Assert.notNull(command.getKey(), "Key must not be null!"); Assert.notNull(command.getRange(), "Range must not be null!"); - boolean isLimited = command.getLimit().isPresent(); + boolean isLimited = command.getLimit().isPresent() && !command.getLimit().get().isUnlimited(); Publisher result; @@ -445,7 +445,7 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands { Flux result; - if (command.getLimit() != null) { + if (!command.getLimit().isUnlimited()) { if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) { result = cmd.zrangebylex(command.getKey(), ArgumentConverters.toRange(command.getRange()), diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceSentinelConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceSentinelConnection.java index ddf1636fe..5b7541ce5 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceSentinelConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceSentinelConnection.java @@ -44,7 +44,7 @@ public class LettuceSentinelConnection implements RedisSentinelConnection { LettuceConverters.exceptionConverter()); private final LettuceConnectionProvider provider; - private StatefulRedisSentinelConnection connection; + private StatefulRedisSentinelConnection connection; // no that should not be null /** * Creates a {@link LettuceSentinelConnection} with a dedicated client for a supplied {@link RedisNode}. diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java index 7cd93a421..97f68d210 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceServerCommands.java @@ -28,6 +28,7 @@ import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult; import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult; import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -494,7 +495,7 @@ class LettuceServerCommands implements RedisServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option) { migrate(key, target, dbIndex, option, Long.MAX_VALUE); } @@ -503,7 +504,7 @@ class LettuceServerCommands implements RedisServerCommands { * @see org.springframework.data.redis.connection.RedisServerCommands#migrate(byte[], org.springframework.data.redis.connection.RedisNode, int, org.springframework.data.redis.connection.RedisServerCommands.MigrateOption, long) */ @Override - public void migrate(byte[] key, RedisNode target, int dbIndex, MigrateOption option, long timeout) { + public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable MigrateOption option, long timeout) { try { if (isPipelined()) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java index 79260171a..4966281fb 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java @@ -27,6 +27,7 @@ import org.springframework.data.redis.connection.RedisStringCommands; import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceResult; import org.springframework.data.redis.connection.lettuce.LettuceConnection.LettuceTxResult; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.util.Assert; /** * @author Christoph Strobl @@ -80,6 +81,9 @@ class LettuceStringCommands implements RedisStringCommands { @Override public void set(byte[] key, byte[] value, Expiration expiration, SetOption option) { + Assert.notNull(expiration, "Expiration must not be null!"); + Assert.notNull(option, "Option must not be null!"); + try { if (isPipelined()) { pipeline(connection.newLettuceStatusResult( diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java index 7b5409837..d2cb7e3f7 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java @@ -259,36 +259,37 @@ class LettuceZSetCommands implements RedisZSetCommands { public Set zRangeByScore(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range for ZRANGEBYSCORE must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); try { if (isPipelined()) { - if (limit != null) { - pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, LettuceConverters.toRange(range), - LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); - } else { + if (limit.isUnlimited()) { pipeline( connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); + } else { + pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscore(key, LettuceConverters.toRange(range), + LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); } return null; } if (isQueueing()) { - if (limit != null) { - transaction(connection.newLettuceTxResult( - getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.bytesListToBytesSet())); - } else { + if (limit.isUnlimited()) { transaction( connection.newLettuceTxResult(getConnection().zrangebyscore(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); + } else { + transaction(connection.newLettuceTxResult( + getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.bytesListToBytesSet())); } return null; } - if (limit != null) { - return LettuceConverters.toBytesSet( - getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); + if (limit.isUnlimited()) { + return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, LettuceConverters.toRange(range))); } - return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, LettuceConverters.toRange(range))); + return LettuceConverters.toBytesSet( + getConnection().zrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); } catch (Exception ex) { throw convertLettuceAccessException(ex); } @@ -302,38 +303,39 @@ class LettuceZSetCommands implements RedisZSetCommands { public Set zRangeByScoreWithScores(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range for ZRANGEBYSCOREWITHSCORES must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); try { if (isPipelined()) { - if (limit != null) { - pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.scoredValuesToTupleSet())); - } else { + if (limit.isUnlimited()) { pipeline(connection.newLettuceResult( getAsyncConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range)), LettuceConverters.scoredValuesToTupleSet())); + } else { + pipeline(connection.newLettuceResult(getAsyncConnection().zrangebyscoreWithScores(key, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.scoredValuesToTupleSet())); } return null; } if (isQueueing()) { - if (limit != null) { - transaction(connection.newLettuceTxResult(getConnection().zrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.scoredValuesToTupleSet())); - } else { + if (limit.isUnlimited()) { transaction(connection.newLettuceTxResult( getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range)), LettuceConverters.scoredValuesToTupleSet())); + } else { + transaction(connection.newLettuceTxResult(getConnection().zrangebyscoreWithScores(key, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.scoredValuesToTupleSet())); } return null; } - if (limit != null) { - return LettuceConverters.toTupleSet(getConnection().zrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); + if (limit.isUnlimited()) { + return LettuceConverters + .toTupleSet(getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range))); } - return LettuceConverters - .toTupleSet(getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range))); + return LettuceConverters.toTupleSet(getConnection().zrangebyscoreWithScores(key, LettuceConverters.toRange(range), + LettuceConverters.toLimit(limit))); } catch (Exception ex) { throw convertLettuceAccessException(ex); } @@ -370,37 +372,38 @@ class LettuceZSetCommands implements RedisZSetCommands { public Set zRevRangeByScore(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range for ZREVRANGEBYSCORE must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); try { if (isPipelined()) { - if (limit != null) { - pipeline( - connection.newLettuceResult(getAsyncConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), - LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); - } else { + if (limit.isUnlimited()) { pipeline( connection.newLettuceResult(getAsyncConnection().zrevrangebyscore(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); + } else { + pipeline( + connection.newLettuceResult(getAsyncConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), + LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); } return null; } if (isQueueing()) { - if (limit != null) { - transaction(connection.newLettuceTxResult( - getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.bytesListToBytesSet())); - } else { + if (limit.isUnlimited()) { transaction( connection.newLettuceTxResult(getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); + } else { + transaction(connection.newLettuceTxResult( + getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.bytesListToBytesSet())); } return null; } - if (limit != null) { - return LettuceConverters.toBytesSet( - getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); + if (limit.isUnlimited()) { + return LettuceConverters.toBytesSet(getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range))); } - return LettuceConverters.toBytesSet(getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range))); + return LettuceConverters.toBytesSet( + getConnection().zrevrangebyscore(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); } catch (Exception ex) { throw convertLettuceAccessException(ex); } @@ -414,38 +417,39 @@ class LettuceZSetCommands implements RedisZSetCommands { public Set zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range for ZREVRANGEBYSCOREWITHSCORES must not be null!"); + Assert.notNull(limit, "Limit must not be null!"); try { if (isPipelined()) { - if (limit != null) { - pipeline(connection.newLettuceResult(getAsyncConnection().zrevrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.scoredValuesToTupleSet())); - } else { + if (limit.isUnlimited()) { pipeline(connection.newLettuceResult( getAsyncConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range)), LettuceConverters.scoredValuesToTupleSet())); + } else { + pipeline(connection.newLettuceResult(getAsyncConnection().zrevrangebyscoreWithScores(key, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.scoredValuesToTupleSet())); } return null; } if (isQueueing()) { - if (limit != null) { - transaction(connection.newLettuceTxResult(getConnection().zrevrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), - LettuceConverters.scoredValuesToTupleSet())); - } else { + if (limit.isUnlimited()) { transaction(connection.newLettuceTxResult( getConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range)), LettuceConverters.scoredValuesToTupleSet())); + } else { + transaction(connection.newLettuceTxResult(getConnection().zrevrangebyscoreWithScores(key, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + LettuceConverters.scoredValuesToTupleSet())); } return null; } - if (limit != null) { - return LettuceConverters.toTupleSet(getConnection().zrevrangebyscoreWithScores(key, - LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); + if (limit.isUnlimited()) { + return LettuceConverters + .toTupleSet(getConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range))); } - return LettuceConverters - .toTupleSet(getConnection().zrevrangebyscoreWithScores(key, LettuceConverters.toRange(range))); + return LettuceConverters.toTupleSet(getConnection().zrevrangebyscoreWithScores(key, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); } catch (Exception ex) { throw convertLettuceAccessException(ex); } @@ -751,38 +755,39 @@ class LettuceZSetCommands implements RedisZSetCommands { public Set zRangeByLex(byte[] key, Range range, Limit limit) { Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX."); + Assert.notNull(limit, "Limit must not be null!"); try { if (isPipelined()) { - if (limit != null) { - pipeline(connection.newLettuceResult( - getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + if (limit.isUnlimited()) { + pipeline(connection.newLettuceResult(getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); } else { - pipeline(connection.newLettuceResult(getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range)), + pipeline(connection.newLettuceResult( + getAsyncConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); } return null; } if (isQueueing()) { - if (limit != null) { - transaction(connection.newLettuceTxResult( - getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), + if (limit.isUnlimited()) { + transaction(connection.newLettuceTxResult(getConnection().zrangebylex(key, LettuceConverters.toRange(range)), LettuceConverters.bytesListToBytesSet())); } else { - transaction(connection.newLettuceTxResult(getConnection().zrangebylex(key, LettuceConverters.toRange(range)), + transaction(connection.newLettuceTxResult( + getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)), LettuceConverters.bytesListToBytesSet())); } return null; } - if (limit != null) { - return LettuceConverters.bytesListToBytesSet().convert( - getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); + if (limit.isUnlimited()) { + return LettuceConverters.bytesListToBytesSet() + .convert(getConnection().zrangebylex(key, LettuceConverters.toRange(range))); } + return LettuceConverters.bytesListToBytesSet().convert( + getConnection().zrangebylex(key, LettuceConverters.toRange(range), LettuceConverters.toLimit(limit))); - return LettuceConverters.bytesListToBytesSet() - .convert(getConnection().zrangebylex(key, LettuceConverters.toRange(range))); } catch (Exception ex) { throw convertLettuceAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/package-info.java b/src/main/java/org/springframework/data/redis/connection/lettuce/package-info.java index 5f69d43da..f8b09f070 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/package-info.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/package-info.java @@ -1,5 +1,5 @@ /** - * Connection package for Lettuce Redis client. + * Connection package for Lettuce Redis client. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.connection.lettuce; - diff --git a/src/main/java/org/springframework/data/redis/connection/package-info.java b/src/main/java/org/springframework/data/redis/connection/package-info.java index fa07c3cf8..4c78de6fc 100644 --- a/src/main/java/org/springframework/data/redis/connection/package-info.java +++ b/src/main/java/org/springframework/data/redis/connection/package-info.java @@ -4,5 +4,6 @@ * *

Performs exception translation between the underlying library exceptions to Spring's DAO hierarchy. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.connection; diff --git a/src/main/java/org/springframework/data/redis/connection/util/AbstractSubscription.java b/src/main/java/org/springframework/data/redis/connection/util/AbstractSubscription.java index f6f947d3b..7d58b7e6c 100644 --- a/src/main/java/org/springframework/data/redis/connection/util/AbstractSubscription.java +++ b/src/main/java/org/springframework/data/redis/connection/util/AbstractSubscription.java @@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.RedisInvalidSubscriptionException; import org.springframework.data.redis.connection.Subscription; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -30,6 +31,7 @@ import org.springframework.util.ObjectUtils; * the actual registration/unregistration. * * @author Costin Leau + * @author Christoph Strobl */ public abstract class AbstractSubscription implements Subscription { @@ -47,12 +49,14 @@ public abstract class AbstractSubscription implements Subscription { * subscription w/o triggering a subscription action (as some clients (Jedis) require an initial call before entering * into listening mode). * - * @param listener - * @param channels - * @param patterns + * @param listener must not be {@literal null}. + * @param channels can be {@literal null}. + * @param patterns can be {@literal null}. */ - protected AbstractSubscription(MessageListener listener, byte[][] channels, byte[][] patterns) { + protected AbstractSubscription(MessageListener listener, @Nullable byte[][] channels, @Nullable byte[][] patterns) { + Assert.notNull(listener, "MessageListener must not be null!"); + this.listener = listener; synchronized (this.channels) { @@ -146,7 +150,7 @@ public abstract class AbstractSubscription implements Subscription { unsubscribe((byte[][]) null); } - public void pUnsubscribe(byte[]... patts) { + public void pUnsubscribe(@Nullable byte[]... patts) { if (!isAlive()) { return; } @@ -173,7 +177,7 @@ public abstract class AbstractSubscription implements Subscription { closeIfUnsubscribed(); } - public void unsubscribe(byte[]... chans) { + public void unsubscribe(@Nullable byte[]... chans) { if (!isAlive()) { return; } @@ -225,7 +229,7 @@ public abstract class AbstractSubscription implements Subscription { return list; } - private static void add(Collection col, byte[]... bytes) { + private static void add(Collection col, @Nullable byte[]... bytes) { if (!ObjectUtils.isEmpty(bytes)) { for (byte[] bs : bytes) { col.add(new ByteArrayWrapper(bs)); @@ -233,7 +237,7 @@ public abstract class AbstractSubscription implements Subscription { } } - private static void remove(Collection col, byte[]... bytes) { + private static void remove(Collection col, @Nullable byte[]... bytes) { if (!ObjectUtils.isEmpty(bytes)) { for (byte[] bs : bytes) { col.remove(new ByteArrayWrapper(bs)); diff --git a/src/main/java/org/springframework/data/redis/connection/util/Base64.java b/src/main/java/org/springframework/data/redis/connection/util/Base64.java index c37f8b69d..4f1110662 100644 --- a/src/main/java/org/springframework/data/redis/connection/util/Base64.java +++ b/src/main/java/org/springframework/data/redis/connection/util/Base64.java @@ -2,6 +2,8 @@ package org.springframework.data.redis.connection.util; import java.util.Arrays; +import org.springframework.lang.Nullable; + /** * A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance with RFC 2045.
*
@@ -12,7 +14,8 @@ import java.util.Arrays; * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and about 50% faster for * decoding large arrays. This implementation is about twice as fast on very small arrays (< 30 bytes). If * source/destination is a String this version is about three times as fast due to the fact that the - * Commons Codec result has to be recoded to a String from byte[], which is very expensive.
+ * Commons Codec result has to be recoded to a String from byte[], which is very + * expensive.
*
* This encode/decode algorithm doesn't create any temporary arrays as many other codecs do, it only allocates the * resulting array. This produces less garbage and it is possible to handle arrays twice as large as algorithms that @@ -76,7 +79,7 @@ class Base64 { * faster. * @return A BASE64 encoded array. Never null. */ - public final static char[] encodeToChar(byte[] sArr, boolean lineSep) { + public final static char[] encodeToChar(@Nullable byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) @@ -129,7 +132,8 @@ class Base64 { * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including '=') isn't divideable by 4. (I.e. definitely corrupted). */ - public final static byte[] decode(char[] sArr) { + @Nullable + public final static byte[] decode(@Nullable char[] sArr) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) @@ -256,7 +260,7 @@ class Base64 { * faster. * @return A BASE64 encoded array. Never null. */ - public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) { + public final static byte[] encodeToByte(@Nullable byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) @@ -309,6 +313,7 @@ class Base64 { * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including '=') isn't divideable by 4. (I.e. definitely corrupted). */ + @Nullable public final static byte[] decode(byte[] sArr) { // Check special case int sLen = sArr.length; @@ -451,7 +456,8 @@ class Base64 { * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including '=') isn't divideable by 4. (I.e. definitely corrupted). */ - public final static byte[] decode(String str) { + @Nullable + public final static byte[] decode(@Nullable String str) { // Check special case int sLen = str != null ? str.length() : 0; if (sLen == 0) diff --git a/src/main/java/org/springframework/data/redis/connection/util/DecodeUtils.java b/src/main/java/org/springframework/data/redis/connection/util/DecodeUtils.java index 9b7a2fa65..d853fbc9e 100644 --- a/src/main/java/org/springframework/data/redis/connection/util/DecodeUtils.java +++ b/src/main/java/org/springframework/data/redis/connection/util/DecodeUtils.java @@ -23,10 +23,13 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.lang.Nullable; + /** * Simple class containing various decoding utilities. * * @author Costin Leau + * @auhtor Christoph Strobl */ public abstract class DecodeUtils { @@ -42,7 +45,8 @@ public abstract class DecodeUtils { return result; } - public static byte[] encode(String string) { + @Nullable + public static byte[] encode(@Nullable String string) { return (string == null ? null : Base64.decode(string)); } diff --git a/src/main/java/org/springframework/data/redis/connection/util/package-info.java b/src/main/java/org/springframework/data/redis/connection/util/package-info.java index e24d76afa..05f261de6 100644 --- a/src/main/java/org/springframework/data/redis/connection/util/package-info.java +++ b/src/main/java/org/springframework/data/redis/connection/util/package-info.java @@ -1,5 +1,6 @@ /** * Internal utility package for encoding/decoding Strings to byte[] (using Base64) library. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.connection.util; diff --git a/src/main/java/org/springframework/data/redis/core/AbstractOperations.java b/src/main/java/org/springframework/data/redis/core/AbstractOperations.java index 19e3b0153..442f83762 100644 --- a/src/main/java/org/springframework/data/redis/core/AbstractOperations.java +++ b/src/main/java/org/springframework/data/redis/core/AbstractOperations.java @@ -32,6 +32,7 @@ import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -88,6 +89,7 @@ abstract class AbstractOperations { return template.getStringSerializer(); } + @Nullable T execute(RedisCallback callback, boolean b) { return template.execute(callback, b); } @@ -282,8 +284,9 @@ abstract class AbstractOperations { } @SuppressWarnings("unchecked") - Map deserializeHashMap(Map entries) { + Map deserializeHashMap(@Nullable Map entries) { // connection in pipeline/multi mode + if (entries == null) { return null; } diff --git a/src/main/java/org/springframework/data/redis/core/BoundGeoOperations.java b/src/main/java/org/springframework/data/redis/core/BoundGeoOperations.java index e32a2d18b..b2bbccfa6 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundGeoOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundGeoOperations.java @@ -25,6 +25,7 @@ import org.springframework.data.geo.Metric; import org.springframework.data.geo.Point; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs; +import org.springframework.lang.Nullable; /** * {@link GeoOperations} bound to a certain key. @@ -41,10 +42,11 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param point must not be {@literal null}. * @param member must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(Point point, M member); /** @@ -52,11 +54,12 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param point must not be {@literal null}. * @param member must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Point, Object)}. */ @Deprecated + @Nullable default Long geoAdd(Point point, M member) { return add(point, member); } @@ -65,21 +68,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Add {@link GeoLocation} to {@literal key}. * * @param location must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(GeoLocation location); /** * Add {@link GeoLocation} to {@literal key}. * * @param location must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(GeoLocation)}. */ @Deprecated + @Nullable default Long geoAdd(GeoLocation location) { return add(location); } @@ -88,21 +93,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Add {@link Map} of member / {@link Point} pairs to {@literal key}. * * @param memberCoordinateMap must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(Map memberCoordinateMap); /** * Add {@link Map} of member / {@link Point} pairs to {@literal key}. * * @param memberCoordinateMap must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Map)}. */ @Deprecated + @Nullable default Long geoAdd(Map memberCoordinateMap) { return add(memberCoordinateMap); } @@ -111,21 +118,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Add {@link GeoLocation}s to {@literal key} * * @param locations must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(Iterable> locations); /** * Add {@link GeoLocation}s to {@literal key} * * @param locations must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Iterable)}. */ @Deprecated + @Nullable default Long geoAdd(Iterable> locations) { return add(locations); } @@ -139,6 +148,7 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @since 2.0 * @see Redis Documentation: GEODIST */ + @Nullable Distance distance(M member1, M member2); /** @@ -151,6 +161,7 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @deprecated since 2.0, use {@link #distance(Object, Object)}. */ @Deprecated + @Nullable default Distance geoDist(M member1, M member2) { return distance(member1, member2); } @@ -165,6 +176,7 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @since 2.0 * @see Redis Documentation: GEODIST */ + @Nullable Distance distance(M member1, M member2, Metric metric); /** @@ -178,6 +190,7 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @deprecated since 2.0, use {@link #distance(Object, Object, Metric)}. */ @Deprecated + @Nullable default Distance geoDist(M member1, M member2, Metric metric) { return distance(member1, member2, metric); } @@ -186,21 +199,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Get Geohash representation of the position for one or more {@literal member}s. * * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOHASH */ + @Nullable List hash(M... members); /** * Get Geohash representation of the position for one or more {@literal member}s. * * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEOHASH * @deprecated since 2.0, use {@link #hash(Object[])}. */ @Deprecated + @Nullable default List geoHash(M... members) { return hash(members); } @@ -209,21 +224,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Get the {@link Point} representation of positions for one or more {@literal member}s. * * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOPOS */ + @Nullable List position(M... members); /** * Get the {@link Point} representation of positions for one or more {@literal member}s. * * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEOPOS * @deprecated since 2.0, use {@link #position(Object[])}. */ @Deprecated + @Nullable default List geoPos(M... members) { return position(members); } @@ -232,21 +249,23 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Get the {@literal member}s within the boundaries of a given {@link Circle}. * * @param within must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> radius(Circle within); /** * Get the {@literal member}s within the boundaries of a given {@link Circle}. * * @param within must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUS * @deprecated since 2.0, use {@link #radius(Circle)}. */ @Deprecated + @Nullable default GeoResults> geoRadius(Circle within) { return radius(within); } @@ -256,10 +275,11 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param within must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> radius(Circle within, GeoRadiusCommandArgs args); /** @@ -267,11 +287,12 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param within must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUS * @deprecated since 2.0, use {@link #radius(Circle, GeoRadiusCommandArgs)}. */ @Deprecated + @Nullable default GeoResults> geoRadius(Circle within, GeoRadiusCommandArgs args) { return radius(within, args); } @@ -282,10 +303,11 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param member must not be {@literal null}. * @param radius - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(K key, M member, double radius); /** @@ -294,11 +316,12 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param member must not be {@literal null}. * @param radius - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Object, double)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(K key, M member, double radius) { return radius(key, member, radius); } @@ -309,10 +332,11 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param member must not be {@literal null}. * @param distance must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(M member, Distance distance); /** @@ -321,11 +345,12 @@ public interface BoundGeoOperations extends BoundKeyOperations { * * @param member must not be {@literal null}. * @param distance must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Distance)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(M member, Distance distance) { return radius(member, distance); } @@ -337,10 +362,11 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @param member must not be {@literal null}. * @param distance must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(M member, Distance distance, GeoRadiusCommandArgs args); /** @@ -350,11 +376,12 @@ public interface BoundGeoOperations extends BoundKeyOperations { * @param member must not be {@literal null}. * @param distance must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Distance, GeoRadiusCommandArgs)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(M member, Distance distance, GeoRadiusCommandArgs args) { return radius(member, distance, args); } @@ -363,19 +390,21 @@ public interface BoundGeoOperations extends BoundKeyOperations { * Remove the {@literal member}s. * * @param members must not be {@literal null}. - * @return Number of elements removed. + * @return Number of elements removed. {@literal null} when used in pipeline / transaction. * @since 2.0 */ + @Nullable Long remove(M... members); /** * Remove the {@literal member}s. * * @param members must not be {@literal null}. - * @return Number of elements removed. + * @return Number of elements removed. {@literal null} when used in pipeline / transaction. * @deprecated since 2.0, use {@link #remove(Object[])}. */ @Deprecated + @Nullable default Long geoRemove(M... members) { return remove(members); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java index 8c39ce643..b4a4a9015 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.lang.Nullable; + /** * Hash operations bound to a certain key. * @@ -34,32 +36,36 @@ public interface BoundHashOperations extends BoundKeyOperations { * Delete given hash {@code keys} at the bound key. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Long delete(Object... keys); /** * Determine if given hash {@code key} exists at the bound key. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean hasKey(Object key); /** * Get value for given {@code key} from the hash at the bound key. * - * @param key must not be {@literal null}. - * @return + * @param member must not be {@literal null}. + * @return {@literal null} when member does not exist or when used in pipeline / transaction. */ - HV get(Object key); + @Nullable + HV get(Object member); /** * Get values for given {@code keys} from the hash at the bound key. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable List multiGet(Collection keys); /** @@ -67,8 +73,9 @@ public interface BoundHashOperations extends BoundKeyOperations { * * @param key must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Long increment(HK key, long delta); /** @@ -76,22 +83,25 @@ public interface BoundHashOperations extends BoundKeyOperations { * * @param key must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Double increment(HK key, double delta); /** * Get key set (fields) of hash at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Set keys(); /** * Get size of hash at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Long size(); /** @@ -114,22 +124,25 @@ public interface BoundHashOperations extends BoundKeyOperations { * * @param key must not be {@literal null}. * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean putIfAbsent(HK key, HV value); /** * Get entry set (values) of hash at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable List values(); /** * Get entire hash at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Map entries(); /** @@ -142,7 +155,7 @@ public interface BoundHashOperations extends BoundKeyOperations { Cursor> scan(ScanOptions options); /** - * @return + * @return never {@literal null}. */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundKeyOperations.java b/src/main/java/org/springframework/data/redis/core/BoundKeyOperations.java index 088bd39d0..961b93a9f 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundKeyOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundKeyOperations.java @@ -19,6 +19,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; import org.springframework.data.redis.connection.DataType; +import org.springframework.lang.Nullable; /** * Operations over a Redis key. Useful for executing common key-'bound' operations to all implementations. @@ -35,54 +36,59 @@ public interface BoundKeyOperations { /** * Returns the key associated with this entity. - * + * * @return key associated with the implementing entity */ K getKey(); /** * Returns the associated Redis type. - * - * @return key type + * + * @return key type. {@literal null} when used in pipeline / transaction. */ + @Nullable DataType getType(); /** * Returns the expiration of this key. - * - * @return expiration value (in seconds) + * + * @return expiration value (in seconds). {@literal null} when used in pipeline / transaction. */ + @Nullable Long getExpire(); /** * Sets the key time-to-live/expiration. - * + * * @param timeout expiration value * @param unit expiration unit - * @return true if expiration was set, false otherwise + * @return true if expiration was set, false otherwise. {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean expire(long timeout, TimeUnit unit); /** * Sets the key time-to-live/expiration. - * + * * @param date expiration date - * @return true if expiration was set, false otherwise + * @return true if expiration was set, false otherwise. {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean expireAt(Date date); /** * Removes the expiration (if any) of the key. - * - * @return true if expiration was removed, false otherwise + * + * @return true if expiration was removed, false otherwise. {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean persist(); /** * Renames the key.
* Note: The new name for empty collections will be propagated on add of first element. - * - * @param newKey new key + * + * @param newKey new key. Must not be {@literal null}. */ void rename(K newKey); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java index 7347bd391..86402ee9a 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java @@ -18,6 +18,8 @@ package org.springframework.data.redis.core; import java.util.List; import java.util.concurrent.TimeUnit; +import org.springframework.lang.Nullable; + /** * List operations bound to a certain key. * @@ -31,9 +33,10 @@ public interface BoundListOperations extends BoundKeyOperations { * * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LRANGE */ + @Nullable List range(long start, long end); /** @@ -48,81 +51,90 @@ public interface BoundListOperations extends BoundKeyOperations { /** * Get the size of list stored at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LLEN */ + @Nullable Long size(); /** * Prepend {@code value} to the bound key. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSH */ + @Nullable Long leftPush(V value); /** * Prepend {@code values} to the bound key. * * @param values - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSH */ + @Nullable Long leftPushAll(V... values); /** * Prepend {@code values} to the bound key only if the list exists. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSHX */ + @Nullable Long leftPushIfPresent(V value); /** * Prepend {@code values} to the bound key before {@code value}. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPUSH */ + @Nullable Long leftPush(V pivot, V value); /** * Append {@code value} to the bound key. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSH */ + @Nullable Long rightPush(V value); /** * Append {@code values} to the bound key. * * @param values - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSH */ + @Nullable Long rightPushAll(V... values); /** * Append {@code values} to the bound key only if the list exists. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSHX */ + @Nullable Long rightPushIfPresent(V value); /** * Append {@code values} to the bound key before {@code value}. * * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPUSH */ + @Nullable Long rightPush(V pivot, V value); /** @@ -139,26 +151,29 @@ public interface BoundListOperations extends BoundKeyOperations { * * @param count * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LREM */ + @Nullable Long remove(long count, Object value); /** * Get element at {@code index} form list at the bound key. * * @param index - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LINDEX */ + @Nullable V index(long index); /** * Removes and returns first element in list stored at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: LPOP */ + @Nullable V leftPop(); /** @@ -167,17 +182,19 @@ public interface BoundListOperations extends BoundKeyOperations { * * @param timeout * @param unit must not be {@literal null}. - * @return + * @return {@literal null} when timeout reached or used in pipeline / transaction. * @see Redis Documentation: BLPOP */ + @Nullable V leftPop(long timeout, TimeUnit unit); /** * Removes and returns last element in list stored at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RPOP */ + @Nullable V rightPop(); /** @@ -186,9 +203,10 @@ public interface BoundListOperations extends BoundKeyOperations { * * @param timeout * @param unit must not be {@literal null}. - * @return + * @return {@literal null} when timeout reached or used in pipeline / transaction. * @see Redis Documentation: BRPOP */ + @Nullable V rightPop(long timeout, TimeUnit unit); RedisOperations getOperations(); diff --git a/src/main/java/org/springframework/data/redis/core/BoundSetOperations.java b/src/main/java/org/springframework/data/redis/core/BoundSetOperations.java index 6dd2526a3..84788fb4b 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundSetOperations.java @@ -19,9 +19,11 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import org.springframework.lang.Nullable; + /** * Set operations bound to a certain key. - * + * * @author Costin Leau * @author Mark Paluch */ @@ -31,26 +33,29 @@ public interface BoundSetOperations extends BoundKeyOperations { * Add given {@code values} to set at the bound key. * * @param values - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SADD */ + @Nullable Long add(V... values); /** * Remove given {@code values} from set at the bound key and return the number of removed elements. * * @param values - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SREM */ + @Nullable Long remove(Object... values); /** * Remove and return a random member from set at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SPOP */ + @Nullable V pop(); /** @@ -58,44 +63,49 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param destKey must not be {@literal null}. * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SMOVE */ + @Nullable Boolean move(K destKey, V value); /** * Get size of set at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SCARD */ + @Nullable Long size(); /** * Check if set at the bound key contains {@code value}. * * @param o - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SISMEMBER */ + @Nullable Boolean isMember(Object o); /** * Returns the members intersecting all given sets at the bound key and {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SINTER */ + @Nullable Set intersect(K key); /** * Returns the members intersecting all given sets at the bound key and {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SINTER */ + @Nullable Set intersect(Collection keys); /** @@ -103,7 +113,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param key must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SINTERSTORE */ void intersectAndStore(K key, K destKey); @@ -113,7 +122,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param keys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SINTERSTORE */ void intersectAndStore(Collection keys, K destKey); @@ -122,18 +130,20 @@ public interface BoundSetOperations extends BoundKeyOperations { * Union all sets at given {@code key} and {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SUNION */ + @Nullable Set union(K key); /** * Union all sets at given {@code keys} and {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SUNION */ + @Nullable Set union(Collection keys); /** @@ -141,7 +151,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param key must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SUNIONSTORE */ void unionAndStore(K key, K destKey); @@ -151,7 +160,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param keys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SUNIONSTORE */ void unionAndStore(Collection keys, K destKey); @@ -160,18 +168,20 @@ public interface BoundSetOperations extends BoundKeyOperations { * Diff all sets for given the bound key and {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SDIFF */ + @Nullable Set diff(K key); /** * Diff all sets for given the bound key and {@code keys}. * * @param keys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SDIFF */ + @Nullable Set diff(Collection keys); /** @@ -179,7 +189,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param keys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SDIFFSTORE */ void diffAndStore(K keys, K destKey); @@ -189,7 +198,6 @@ public interface BoundSetOperations extends BoundKeyOperations { * * @param keys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: SDIFFSTORE */ void diffAndStore(Collection keys, K destKey); @@ -197,44 +205,52 @@ public interface BoundSetOperations extends BoundKeyOperations { /** * Get all elements of set at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SMEMBERS */ + @Nullable Set members(); /** * Get random element from set at the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SRANDMEMBER */ + @Nullable V randomMember(); /** * Get {@code count} distinct random elements from set at the bound key. * * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SRANDMEMBER */ + @Nullable Set distinctRandomMembers(long count); /** * Get {@code count} random elements from set at the bound key. * * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SRANDMEMBER */ + @Nullable List randomMembers(long count); /** * @param options - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.4 */ + @Nullable Cursor scan(ScanOptions options); - + + /** + * @return never {@literal null}. + */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java b/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java index 8b3381d91..031472071 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundValueOperations.java @@ -17,6 +17,8 @@ package org.springframework.data.redis.core; import java.util.concurrent.TimeUnit; +import org.springframework.lang.Nullable; + /** * Value (or String in Redis terminology) operations bound to a certain key. * @@ -28,7 +30,7 @@ public interface BoundValueOperations extends BoundKeyOperations { /** * Set {@code value} for the bound key. * - * @param value + * @param value must not be {@literal null}. * @see Redis Documentation: SET */ void set(V value); @@ -36,7 +38,7 @@ public interface BoundValueOperations extends BoundKeyOperations { /** * Set the {@code value} and expiration {@code timeout} for the bound key. * - * @param value + * @param value must not be {@literal null}. * @param timeout * @param unit must not be {@literal null}. * @see Redis Documentation: SETEX @@ -46,47 +48,59 @@ public interface BoundValueOperations extends BoundKeyOperations { /** * Set the bound key to hold the string {@code value} if the bound key is absent. * - * @param value + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SETNX */ + @Nullable Boolean setIfAbsent(V value); /** * Get the value of the bound key. * + * @return {@literal null} when used in pipeline / transaction.ø * @see Redis Documentation: GET */ + @Nullable V get(); /** * Set {@code value} of the bound key and return its old value. * + * @return {@literal null} when used in pipeline / transaction.ø * @see Redis Documentation: GETSET */ + @Nullable V getAndSet(V value); /** * Increment an integer value stored as string value under the bound key by {@code delta}. * * @param delta + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: INCR */ + @Nullable Long increment(long delta); /** * Increment a floating point number value stored as string value under the bound key by {@code delta}. * * @param delta + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: INCRBYFLOAT */ + @Nullable Double increment(double delta); /** * Append a {@code value} to the bound key. * - * @param value + * @param value must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: APPEND */ + @Nullable Integer append(String value); /** @@ -96,12 +110,13 @@ public interface BoundValueOperations extends BoundKeyOperations { * @param end * @see Redis Documentation: GETRANGE */ + @Nullable String get(long start, long end); /** * Overwrite parts of the bound key starting at the specified {@code offset} with given {@code value}. * - * @param value + * @param value must not be {@literal null}. * @param offset * @see Redis Documentation: SETRANGE */ @@ -110,9 +125,14 @@ public interface BoundValueOperations extends BoundKeyOperations { /** * Get the length of the value stored at the bound key. * + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: STRLEN */ + @Nullable Long size(); + /** + * @return never {@literal null}. + */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java b/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java index 7027cabb8..64b8df62f 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java @@ -22,6 +22,7 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Limit; import org.springframework.data.redis.connection.RedisZSetCommands.Range; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; +import org.springframework.lang.Nullable; /** * ZSet (or SortedSet) operations bound to a certain key. @@ -37,27 +38,30 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param score the score. * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Boolean add(V value, double score); /** * Add {@code tuples} to a sorted set at the bound key, or update its {@code score} if it already exists. * * @param tuples must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Long add(Set> tuples); /** * Remove {@code values} from sorted set. Return number of removed elements. * * @param values must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREM */ + @Nullable Long remove(Object... values); /** @@ -65,27 +69,30 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param delta * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINCRBY */ + @Nullable Double incrementScore(V value, double delta); /** * Determine the index of element with {@code value} in a sorted set. * * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANK */ + @Nullable Long rank(Object o); /** * Determine the index of element with {@code value} in a sorted set when scored high to low. * * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANK */ + @Nullable Long reverseRank(Object o); /** @@ -93,9 +100,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set range(long start, long end); /** @@ -103,9 +111,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set> rangeWithScores(long start, long end); /** @@ -113,9 +122,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set rangeByScore(double min, double max); /** @@ -123,9 +133,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set> rangeByScoreWithScores(double min, double max); /** @@ -133,9 +144,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set reverseRange(long start, long end); /** @@ -143,9 +155,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set> reverseRangeWithScores(long start, long end); /** @@ -153,9 +166,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set reverseRangeByScore(double min, double max); /** @@ -164,9 +178,10 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set> reverseRangeByScoreWithScores(double min, double max); /** @@ -174,36 +189,40 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCOUNT */ + @Nullable Long count(double min, double max); /** * Returns the number of elements of the sorted set stored with given the bound key. * * @see #zCard() - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCARD */ + @Nullable Long size(); /** * Get the size of sorted set with the bound key. * - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.3 * @see Redis Documentation: ZCARD */ + @Nullable Long zCard(); /** * Get the score of element with {@code value} from sorted set with key the bound key. * * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZSCORE */ + @Nullable Double score(Object o); /** @@ -211,7 +230,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param start * @param end - * @return * @see Redis Documentation: ZREMRANGEBYRANK */ void removeRange(long start, long end); @@ -221,7 +239,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param min * @param max - * @return * @see Redis Documentation: ZREMRANGEBYSCORE */ void removeRangeByScore(double min, double max); @@ -231,7 +248,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param otherKey must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: ZUNIONSTORE */ void unionAndStore(K otherKey, K destKey); @@ -241,7 +257,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param otherKeys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: ZUNIONSTORE */ void unionAndStore(Collection otherKeys, K destKey); @@ -251,7 +266,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param otherKey must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: ZINTERSTORE */ void intersectAndStore(K otherKey, K destKey); @@ -261,7 +275,6 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param otherKeys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return * @see Redis Documentation: ZINTERSTORE */ void intersectAndStore(Collection otherKeys, K destKey); @@ -281,9 +294,11 @@ public interface BoundZSetOperations extends BoundKeyOperations { * {@link Range#getMax()}. * * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.7 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable Set rangeByLex(Range range); /** @@ -293,11 +308,15 @@ public interface BoundZSetOperations extends BoundKeyOperations { * * @param range must not be {@literal null}. * @param limit can be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.7 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable Set rangeByLex(Range range, Limit limit); + /** + * @return never {@literal null}. + */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/CloseSuppressingInvocationHandler.java b/src/main/java/org/springframework/data/redis/core/CloseSuppressingInvocationHandler.java index 149659364..c151a7500 100644 --- a/src/main/java/org/springframework/data/redis/core/CloseSuppressingInvocationHandler.java +++ b/src/main/java/org/springframework/data/redis/core/CloseSuppressingInvocationHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -20,12 +20,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.lang.Nullable; /** * Invocation handler that suppresses close calls on {@link RedisConnection}. * * @see RedisConnection#close() * @author Costin Leau + * @author Christoph Strobl */ class CloseSuppressingInvocationHandler implements InvocationHandler { @@ -39,6 +41,8 @@ class CloseSuppressingInvocationHandler implements InvocationHandler { this.target = target; } + @Override + @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals(EQUALS)) { diff --git a/src/main/java/org/springframework/data/redis/core/ConvertingCursor.java b/src/main/java/org/springframework/data/redis/core/ConvertingCursor.java index a2a8994ba..398fc45f0 100644 --- a/src/main/java/org/springframework/data/redis/core/ConvertingCursor.java +++ b/src/main/java/org/springframework/data/redis/core/ConvertingCursor.java @@ -18,6 +18,7 @@ package org.springframework.data.redis.core; import java.io.IOException; import org.springframework.core.convert.converter.Converter; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -61,6 +62,7 @@ public class ConvertingCursor implements Cursor { * @see java.util.Iterator#next() */ @Override + @Nullable public T next() { return converter.convert(delegate.next()); } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundKeyOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundKeyOperations.java index 322f07fed..9b8dfaef3 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundKeyOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundKeyOperations.java @@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit; * Default {@link BoundKeyOperations} implementation. Meant for internal usage. * * @author Costin Leau + * @author Christoph Strobl */ abstract class DefaultBoundKeyOperations implements BoundKeyOperations { @@ -30,7 +31,7 @@ abstract class DefaultBoundKeyOperations implements BoundKeyOperations { DefaultBoundKeyOperations(K key, RedisOperations operations) { - setKey(key); + this.key = key; this.ops = operations; } @@ -43,10 +44,6 @@ abstract class DefaultBoundKeyOperations implements BoundKeyOperations { return key; } - protected void setKey(K key) { - this.key = key; - } - /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundKeyOperations#expire(long, java.util.concurrent.TimeUnit) diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java index 8db6cdd0c..660903214 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java @@ -170,7 +170,7 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl */ @Override public Set rangeByLex(Range range) { - return rangeByLex(range, null); + return rangeByLex(range, Limit.unlimited()); } /* diff --git a/src/main/java/org/springframework/data/redis/core/DefaultClusterOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultClusterOperations.java index 5b76000c4..cce15f9b6 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultClusterOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultClusterOperations.java @@ -24,6 +24,7 @@ import org.springframework.data.redis.connection.RedisClusterConnection; import org.springframework.data.redis.connection.RedisClusterNode; import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; import org.springframework.data.redis.connection.RedisServerCommands.MigrateOption; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -257,9 +258,10 @@ class DefaultClusterOperations extends AbstractOperations implements /** * Executed wrapped command upon {@link RedisClusterConnection}. * - * @param callback - * @return + * @param callback must not be {@literal null}. + * @return execution result. Can be {@literal null}. */ + @Nullable public T execute(RedisClusterCallback callback) { Assert.notNull(callback, "ClusterCallback must not be null!"); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java index 6f43705c5..3dd849fe6 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java @@ -51,7 +51,7 @@ class DefaultHashOperations extends AbstractOperations imp byte[] rawHashKey = rawHashKey(hashKey); byte[] rawHashValue = execute(connection -> connection.hGet(rawKey, rawHashKey), true); - return (HV) deserializeHashValue(rawHashValue); + return (HV) rawHashValue != null ? deserializeHashValue(rawHashValue) : null; } /* @@ -100,7 +100,7 @@ class DefaultHashOperations extends AbstractOperations imp byte[] rawKey = rawKey(key); Set rawValues = execute(connection -> connection.hKeys(rawKey), true); - return deserializeHashKeys(rawValues); + return rawValues != null ? deserializeHashKeys(rawValues) : Collections.emptySet(); } /* @@ -204,7 +204,7 @@ class DefaultHashOperations extends AbstractOperations imp byte[] rawKey = rawKey(key); List rawValues = execute(connection -> connection.hVals(rawKey), true); - return deserializeHashValues(rawValues); + return rawValues != null ? deserializeHashValues(rawValues) : Collections.emptyList(); } /* @@ -230,7 +230,7 @@ class DefaultHashOperations extends AbstractOperations imp byte[] rawKey = rawKey(key); Map entries = execute(connection -> connection.hGetAll(rawKey), true); - return deserializeHashMap(entries); + return entries != null ? deserializeHashMap(entries) : Collections.emptyMap(); } /* diff --git a/src/main/java/org/springframework/data/redis/core/DefaultTypedTuple.java b/src/main/java/org/springframework/data/redis/core/DefaultTypedTuple.java index 2f61c9055..b2e79013a 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultTypedTuple.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultTypedTuple.java @@ -18,6 +18,7 @@ package org.springframework.data.redis.core; import java.util.Arrays; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; +import org.springframework.lang.Nullable; /** * Default implementation of TypedTuple. @@ -26,24 +27,26 @@ import org.springframework.data.redis.core.ZSetOperations.TypedTuple; */ public class DefaultTypedTuple implements TypedTuple { - private final Double score; - private final V value; + private final @Nullable Double score; + private final @Nullable V value; /** * Constructs a new DefaultTypedTuple instance. * - * @param value - * @param score + * @param value can be {@literal null}. + * @param score can be {@literal null}. */ - public DefaultTypedTuple(V value, Double score) { + public DefaultTypedTuple(@Nullable V value, @Nullable Double score) { this.score = score; this.value = value; } + @Nullable public Double getScore() { return score; } + @Nullable public V getValue() { return value; } diff --git a/src/main/java/org/springframework/data/redis/core/GeoOperations.java b/src/main/java/org/springframework/data/redis/core/GeoOperations.java index 321b1bb24..202e5381a 100644 --- a/src/main/java/org/springframework/data/redis/core/GeoOperations.java +++ b/src/main/java/org/springframework/data/redis/core/GeoOperations.java @@ -25,6 +25,7 @@ import org.springframework.data.geo.Metric; import org.springframework.data.geo.Point; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs; +import org.springframework.lang.Nullable; /** * Redis operations for geo commands. @@ -43,10 +44,11 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param point must not be {@literal null}. * @param member must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(K key, Point point, M member); /** @@ -55,11 +57,12 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param point must not be {@literal null}. * @param member must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Object, Point, Object)}. */ @Deprecated + @Nullable default Long geoAdd(K key, Point point, M member) { return add(key, point, member); } @@ -69,10 +72,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param location must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(K key, GeoLocation location); /** @@ -80,11 +84,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param location must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Object, GeoLocation)}. */ @Deprecated + @Nullable default Long geoAdd(K key, GeoLocation location) { return add(key, location); } @@ -94,10 +99,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param memberCoordinateMap must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(K key, Map memberCoordinateMap); /** @@ -105,11 +111,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param memberCoordinateMap must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Object, Map)}. */ @Deprecated + @Nullable default Long geoAdd(K key, Map memberCoordinateMap) { return add(key, memberCoordinateMap); } @@ -119,10 +126,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param locations must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOADD */ + @Nullable Long add(K key, Iterable> locations); /** @@ -130,11 +138,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param locations must not be {@literal null}. - * @return Number of elements added. + * @return Number of elements added. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: GEOADD * @deprecated since 2.0, use {@link #add(Object, Iterable)}. */ @Deprecated + @Nullable default Long geoAdd(K key, Iterable> locations) { return add(key, locations); } @@ -149,6 +158,7 @@ public interface GeoOperations { * @since 2.0 * @see Redis Documentation: GEODIST */ + @Nullable Distance distance(K key, M member1, M member2); /** @@ -162,6 +172,7 @@ public interface GeoOperations { * @deprecated since 2.0, use {@link #distance(Object, Object, Object)}. */ @Deprecated + @Nullable default Distance geoDist(K key, M member1, M member2) { return distance(key, member1, member2); } @@ -177,6 +188,7 @@ public interface GeoOperations { * @since 2.0 * @see Redis Documentation: GEODIST */ + @Nullable Distance distance(K key, M member1, M member2, Metric metric); /** @@ -191,6 +203,7 @@ public interface GeoOperations { * @deprecated since 2.0, use {@link #distance(Object, Object, Object, Metric)}. */ @Deprecated + @Nullable default Distance geoDist(K key, M member1, M member2, Metric metric) { return distance(key, member1, member2, metric); } @@ -200,10 +213,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOHASH */ + @Nullable List hash(K key, M... members); /** @@ -211,11 +225,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEOHASH * @deprecated since 2.0, use {@link #hash(Object, Object[])}. */ @Deprecated + @Nullable default List geoHash(K key, M... members) { return hash(key, members); } @@ -225,10 +240,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEOPOS */ + @Nullable List position(K key, M... members); /** @@ -236,11 +252,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEOPOS * @deprecated since 2.0, use {@link #position(Object, Object[])}. */ @Deprecated + @Nullable default List geoPos(K key, M... members) { return position(key, members); } @@ -250,10 +267,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param within must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> radius(K key, Circle within); /** @@ -261,11 +279,12 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param within must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUS * @deprecated since 2.0, use {@link #radius(Object, Circle)}. */ @Deprecated + @Nullable default GeoResults> geoRadius(K key, Circle within) { return radius(key, within); } @@ -276,10 +295,11 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param within must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUS */ + @Nullable GeoResults> radius(K key, Circle within, GeoRadiusCommandArgs args); /** @@ -288,11 +308,12 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param within must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUS * @deprecated since 2.0, use {@link #radius(Object, Circle, GeoRadiusCommandArgs)}. */ @Deprecated + @Nullable default GeoResults> geoRadius(K key, Circle within, GeoRadiusCommandArgs args) { return radius(key, within, args); } @@ -304,10 +325,11 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param radius - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(K key, M member, double radius); /** @@ -317,11 +339,12 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param radius - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Object, double)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(K key, M member, double radius) { return radius(key, member, radius); } @@ -333,10 +356,11 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param distance must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(K key, M member, Distance distance); /** @@ -346,11 +370,12 @@ public interface GeoOperations { * @param key must not be {@literal null}. * @param member must not be {@literal null}. * @param distance must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Object, Distance)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(K key, M member, Distance distance) { return radius(key, member, distance); } @@ -363,10 +388,11 @@ public interface GeoOperations { * @param member must not be {@literal null}. * @param distance must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @since 2.0 * @see Redis Documentation: GEORADIUSBYMEMBER */ + @Nullable GeoResults> radius(K key, M member, Distance distance, GeoRadiusCommandArgs args); /** @@ -377,11 +403,12 @@ public interface GeoOperations { * @param member must not be {@literal null}. * @param distance must not be {@literal null}. * @param args must not be {@literal null}. - * @return never {@literal null}. + * @return never {@literal null} unless used in pipeline / transaction. * @see Redis Documentation: GEORADIUSBYMEMBER * @deprecated since 2.0, use {@link #radius(Object, Object, Distance, GeoRadiusCommandArgs)}. */ @Deprecated + @Nullable default GeoResults> geoRadiusByMember(K key, M member, Distance distance, GeoRadiusCommandArgs args) { return radius(key, member, distance, args); } @@ -391,9 +418,10 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return Number of elements removed. + * @return Number of elements removed. {@literal null} when used in pipeline / transaction. * @since 2.0 */ + @Nullable Long remove(K key, M... members); /** @@ -401,10 +429,11 @@ public interface GeoOperations { * * @param key must not be {@literal null}. * @param members must not be {@literal null}. - * @return Number of elements removed. + * @return Number of elements removed. {@literal null} when used in pipeline / transaction. * @deprecated since 2.0, use {@link #remove(Object, Object[])}. */ @Deprecated + @Nullable default Long geoRemove(K key, M... members) { return remove(key, members); } diff --git a/src/main/java/org/springframework/data/redis/core/HashOperations.java b/src/main/java/org/springframework/data/redis/core/HashOperations.java index 911f956a5..e278e2d47 100644 --- a/src/main/java/org/springframework/data/redis/core/HashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/HashOperations.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.lang.Nullable; + /** * Redis map specific operations working on a hash. * @@ -34,7 +36,7 @@ public interface HashOperations { * * @param key must not be {@literal null}. * @param hashKeys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ Long delete(H key, Object... hashKeys); @@ -43,7 +45,7 @@ public interface HashOperations { * * @param key must not be {@literal null}. * @param hashKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ Boolean hasKey(H key, Object hashKey); @@ -52,8 +54,9 @@ public interface HashOperations { * * @param key must not be {@literal null}. * @param hashKey must not be {@literal null}. - * @return + * @return {@literal null} when key or hashKey does not exist or used in pipeline / transaction. */ + @Nullable HV get(H key, Object hashKey); /** @@ -61,7 +64,7 @@ public interface HashOperations { * * @param key must not be {@literal null}. * @param hashKeys must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ List multiGet(H key, Collection hashKeys); @@ -71,7 +74,7 @@ public interface HashOperations { * @param key must not be {@literal null}. * @param hashKey must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. */ Long increment(H key, HK hashKey, long delta); @@ -81,7 +84,7 @@ public interface HashOperations { * @param key must not be {@literal null}. * @param hashKey must not be {@literal null}. * @param delta - * @return + * @return {@literal null} when used in pipeline / transaction. */ Double increment(H key, HK hashKey, double delta); @@ -89,7 +92,7 @@ public interface HashOperations { * Get key set (fields) of hash at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ Set keys(H key); @@ -97,7 +100,7 @@ public interface HashOperations { * Get size of hash at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ Long size(H key); @@ -124,7 +127,7 @@ public interface HashOperations { * @param key must not be {@literal null}. * @param hashKey must not be {@literal null}. * @param value - * @return + * @return {@literal null} when used in pipeline / transaction. */ Boolean putIfAbsent(H key, HK hashKey, HV value); @@ -132,7 +135,7 @@ public interface HashOperations { * Get entry set (values) of hash at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ List values(H key); @@ -140,7 +143,7 @@ public interface HashOperations { * Get entire hash stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ Map entries(H key); @@ -150,13 +153,13 @@ public interface HashOperations { * * @param key must not be {@literal null}. * @param options - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.4 */ Cursor> scan(H key, ScanOptions options); /** - * @return + * @return never {@literal null}. */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/RedisAccessor.java b/src/main/java/org/springframework/data/redis/core/RedisAccessor.java index 84d6fc7f8..a8ab8a716 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisAccessor.java +++ b/src/main/java/org/springframework/data/redis/core/RedisAccessor.java @@ -19,6 +19,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -31,17 +32,18 @@ public class RedisAccessor implements InitializingBean { /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); - private RedisConnectionFactory connectionFactory; + private @Nullable RedisConnectionFactory connectionFactory; public void afterPropertiesSet() { - Assert.notNull(getConnectionFactory(), "RedisConnectionFactory is required"); + Assert.state(getConnectionFactory() != null, "RedisConnectionFactory is required"); } /** * Returns the connectionFactory. * - * @return Returns the connectionFactory + * @return Returns the connectionFactory. Can be {@literal null} */ + @Nullable public RedisConnectionFactory getConnectionFactory() { return connectionFactory; } diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java index 7502ebc30..29875d1b5 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java @@ -60,6 +60,7 @@ import org.springframework.data.redis.listener.KeyExpirationEventMessageListener import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.util.ByteUtils; import org.springframework.data.util.CloseableIterator; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -103,13 +104,12 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter private RedisOperations redisOps; private RedisConverter converter; - private RedisMessageListenerContainer messageListenerContainer; - private final AtomicReference expirationListener = new AtomicReference<>( - null); - private ApplicationEventPublisher eventPublisher; + private @Nullable RedisMessageListenerContainer messageListenerContainer; + private final AtomicReference expirationListener = new AtomicReference<>(null); + private @Nullable ApplicationEventPublisher eventPublisher; private EnableKeyspaceEvents enableKeyspaceEvents = EnableKeyspaceEvents.OFF; - private String keyspaceNotificationsConfigParameter = null; + private @Nullable String keyspaceNotificationsConfigParameter = null; /** * Creates new {@link RedisKeyValueAdapter} with default {@link RedisMappingContext} and default @@ -751,7 +751,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.redis.listener.KeyspaceEventMessageListener#onMessage(org.springframework.data.redis.connection.Message, byte[]) */ @Override - public void onMessage(Message message, byte[] pattern) { + public void onMessage(Message message, @Nullable byte[] pattern) { if (!isKeyExpirationMessage(message)) { return; @@ -775,8 +775,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter Object value = converter.read(Object.class, new RedisData(hash)); String channel = !ObjectUtils.isEmpty(message.getChannel()) - ? converter.getConversionService().convert(message.getChannel(), String.class) - : null; + ? converter.getConversionService().convert(message.getChannel(), String.class) : null; RedisKeyExpiredEvent event = new RedisKeyExpiredEvent(channel, key, value); diff --git a/src/main/java/org/springframework/data/redis/core/RedisOperations.java b/src/main/java/org/springframework/data/redis/core/RedisOperations.java index df88d966c..9c43880ef 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisOperations.java +++ b/src/main/java/org/springframework/data/redis/core/RedisOperations.java @@ -28,6 +28,7 @@ import org.springframework.data.redis.core.query.SortQuery; import org.springframework.data.redis.core.script.RedisScript; import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.lang.Nullable; /** * Interface that specified a basic set of Redis operations, implemented by {@link RedisTemplate}. Not often used but a @@ -50,9 +51,10 @@ public interface RedisOperations { * the template do its work. * * @param return type - * @param action callback object that specifies the Redis action + * @param action callback object that specifies the Redis action. Must not be {@literal null}. * @return a result object returned by the action or null */ + @Nullable T execute(RedisCallback action); /** @@ -60,9 +62,10 @@ public interface RedisOperations { * capabilities through {@link #multi()} and {@link #watch(Collection)} operations. * * @param return type - * @param session session callback + * @param session session callback. Must not be {@literal null}. * @return result object returned by the action or null */ + @Nullable T execute(SessionCallback session); /** @@ -115,6 +118,7 @@ public interface RedisOperations { * @return The return value of the script or null if {@link RedisScript#getResultType()} is null, likely indicating a * throw-away status reply (i.e. "OK") */ + @Nullable T execute(RedisScript script, List keys, Object... args); /** @@ -129,6 +133,7 @@ public interface RedisOperations { * @return The return value of the script or null if {@link RedisScript#getResultType()} is null, likely indicating a * throw-away status reply (i.e. "OK") */ + @Nullable T execute(RedisScript script, RedisSerializer argsSerializer, RedisSerializer resultSerializer, List keys, Object... args); @@ -140,6 +145,7 @@ public interface RedisOperations { * @return * @since 1.8 */ + @Nullable T executeWithStickyConnection(RedisCallback callback); // ------------------------------------------------------------------------- @@ -162,41 +168,46 @@ public interface RedisOperations { * @return {@literal true} if the key was removed. * @see Redis Documentation: DEL */ + @Nullable Boolean delete(K key); /** * Delete given {@code keys}. * * @param keys must not be {@literal null}. - * @return The number of keys that were removed. + * @return The number of keys that were removed. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: DEL */ + @Nullable Long delete(Collection keys); /** * Determine the type stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: TYPE */ + @Nullable DataType type(K key); /** * Find all keys matching the given {@code pattern}. * * @param pattern must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: KEYS */ + @Nullable Set keys(K pattern); /** * Return a random key from the keyspace. * - * @return + * @return {@literal null} no keys exist or when used in pipeline / transaction. * @see Redis Documentation: RANDOMKEY */ + @Nullable K randomKey(); /** @@ -213,9 +224,10 @@ public interface RedisOperations { * * @param oldKey must not be {@literal null}. * @param newKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: RENAMENX */ + @Nullable Boolean renameIfAbsent(K oldKey, K newKey); /** @@ -224,8 +236,9 @@ public interface RedisOperations { * @param key must not be {@literal null}. * @param timeout * @param unit must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean expire(K key, long timeout, TimeUnit unit); /** @@ -233,17 +246,19 @@ public interface RedisOperations { * * @param key must not be {@literal null}. * @param date must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. */ + @Nullable Boolean expireAt(K key, Date date); /** * Remove the expiration from given {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: PERSIST */ + @Nullable Boolean persist(K key); /** @@ -251,18 +266,20 @@ public interface RedisOperations { * * @param key must not be {@literal null}. * @param dbIndex - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: MOVE */ + @Nullable Boolean move(K key, int dbIndex); /** * Retrieve serialized version of the value stored at {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: DUMP */ + @Nullable byte[] dump(K key); /** @@ -280,9 +297,10 @@ public interface RedisOperations { * Get the time to live for {@code key} in seconds. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: TTL */ + @Nullable Long getExpire(K key); /** @@ -290,45 +308,50 @@ public interface RedisOperations { * * @param key must not be {@literal null}. * @param timeUnit must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.8 */ + @Nullable Long getExpire(K key, TimeUnit timeUnit); /** * Sort the elements for {@code query}. * * @param query must not be {@literal null}. - * @return the results of sort. + * @return the results of sort. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable List sort(SortQuery query); /** * Sort the elements for {@code query} applying {@link RedisSerializer}. * * @param query must not be {@literal null}. - * @return the deserialized results of sort. + * @return the deserialized results of sort. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable List sort(SortQuery query, RedisSerializer resultSerializer); /** * Sort the elements for {@code query} applying {@link BulkMapper}. * * @param query must not be {@literal null}. - * @return the deserialized results of sort. + * @return the deserialized results of sort. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable List sort(SortQuery query, BulkMapper bulkMapper); /** * Sort the elements for {@code query} applying {@link BulkMapper} and {@link RedisSerializer}. * * @param query must not be {@literal null}. - * @return the deserialized results of sort. + * @return the deserialized results of sort. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable List sort(SortQuery query, BulkMapper bulkMapper, RedisSerializer resultSerializer); /** @@ -336,9 +359,10 @@ public interface RedisOperations { * * @param query must not be {@literal null}. * @param storeKey must not be {@literal null}. - * @return number of values. + * @return number of values. {@literal null} when used in pipeline / transaction. * @see Redis Documentation: SORT */ + @Nullable Long sort(SortQuery query, K storeKey); // ------------------------------------------------------------------------- @@ -414,6 +438,7 @@ public interface RedisOperations { * @return {@link List} of {@link RedisClientInfo} objects. * @since 1.3 */ + @Nullable List getClientList(); /** diff --git a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java index 191b5d933..6428c5592 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java @@ -49,6 +49,7 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationUtils; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.lang.Nullable; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -88,8 +89,8 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation private boolean exposeConnection = false; private boolean initialized = false; private boolean enableDefaultSerializer = true; - private RedisSerializer defaultSerializer; - private ClassLoader classLoader; + private @Nullable RedisSerializer defaultSerializer; + private @Nullable ClassLoader classLoader; @SuppressWarnings("rawtypes") private RedisSerializer keySerializer = null; @SuppressWarnings("rawtypes") private RedisSerializer valueSerializer = null; @@ -97,15 +98,15 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation @SuppressWarnings("rawtypes") private RedisSerializer hashValueSerializer = null; private RedisSerializer stringSerializer = new StringRedisSerializer(); - private ScriptExecutor scriptExecutor; + private @Nullable ScriptExecutor scriptExecutor; // cache singleton objects (where possible) - private ValueOperations valueOps; - private ListOperations listOps; - private SetOperations setOps; - private ZSetOperations zSetOps; - private GeoOperations geoOps; - private HyperLogLogOperations hllOps; + private @Nullable ValueOperations valueOps; + private @Nullable ListOperations listOps; + private @Nullable SetOperations setOps; + private @Nullable ZSetOperations zSetOps; + private @Nullable GeoOperations geoOps; + private @Nullable HyperLogLogOperations hllOps; /** * Constructs a new RedisTemplate instance. @@ -165,6 +166,7 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation * @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.RedisCallback) */ @Override + @Nullable public T execute(RedisCallback action) { return execute(action, isExposeConnection()); } @@ -177,6 +179,7 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation * @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code * @return object returned by the action */ + @Nullable public T execute(RedisCallback action, boolean exposeConnection) { return execute(action, exposeConnection, false); } @@ -191,6 +194,7 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation * @param pipeline whether to pipeline or not the connection for the execution * @return object returned by the action */ + @Nullable public T execute(RedisCallback action, boolean exposeConnection, boolean pipeline) { Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); @@ -435,6 +439,7 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation * * @return template default serializer */ + @Nullable public RedisSerializer getDefaultSerializer() { return defaultSerializer; } @@ -684,7 +689,9 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation } protected List execRaw() { - return execute(RedisTxCommands::exec); + + List raw = execute(RedisTxCommands::exec); + return raw == null ? Collections.emptyList() : raw; } /* diff --git a/src/main/java/org/springframework/data/redis/core/ScanOptions.java b/src/main/java/org/springframework/data/redis/core/ScanOptions.java index 83bc1a8ef..744b1bc7e 100644 --- a/src/main/java/org/springframework/data/redis/core/ScanOptions.java +++ b/src/main/java/org/springframework/data/redis/core/ScanOptions.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core; +import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; /** @@ -28,8 +29,8 @@ public class ScanOptions { public static ScanOptions NONE = new ScanOptions(); - private Long count; - private String pattern; + private @Nullable Long count; + private @Nullable String pattern; private ScanOptions() {} @@ -42,10 +43,12 @@ public class ScanOptions { return new ScanOptionsBuilder(); } + @Nullable public Long getCount() { return count; } + @Nullable public String getPattern() { return pattern; } diff --git a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java index 9634b2837..90c728e23 100644 --- a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java @@ -21,6 +21,7 @@ import java.util.Set; import org.springframework.data.redis.connection.RedisZSetCommands.Limit; import org.springframework.data.redis.connection.RedisZSetCommands.Range; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.lang.Nullable; /** * Redis ZSet/sorted set specific operations. @@ -36,8 +37,11 @@ public interface ZSetOperations { * Typed ZSet tuple. */ interface TypedTuple extends Comparable> { + + @Nullable V getValue(); + @Nullable Double getScore(); } @@ -47,9 +51,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param score the score. * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Boolean add(K key, V value, double score); /** @@ -57,9 +62,10 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param tuples must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZADD */ + @Nullable Long add(K key, Set> tuples); /** @@ -67,9 +73,10 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param values must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREM */ + @Nullable Long remove(K key, Object... values); /** @@ -78,9 +85,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param delta * @param value the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINCRBY */ + @Nullable Double incrementScore(K key, V value, double delta); /** @@ -88,9 +96,10 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANK */ + @Nullable Long rank(K key, Object o); /** @@ -98,9 +107,10 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANK */ + @Nullable Long reverseRank(K key, Object o); /** @@ -109,9 +119,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set range(K key, long start, long end); /** @@ -120,9 +131,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGE */ + @Nullable Set> rangeWithScores(K key, long start, long end); /** @@ -131,9 +143,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set rangeByScore(K key, double min, double max); /** @@ -142,9 +155,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set> rangeByScoreWithScores(K key, double min, double max); /** @@ -156,9 +170,10 @@ public interface ZSetOperations { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set rangeByScore(K key, double min, double max, long offset, long count); /** @@ -170,9 +185,10 @@ public interface ZSetOperations { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZRANGEBYSCORE */ + @Nullable Set> rangeByScoreWithScores(K key, double min, double max, long offset, long count); /** @@ -181,9 +197,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set reverseRange(K key, long start, long end); /** @@ -192,9 +209,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set> reverseRangeWithScores(K key, long start, long end); /** @@ -203,9 +221,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGE */ + @Nullable Set reverseRangeByScore(K key, double min, double max); /** @@ -215,9 +234,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set> reverseRangeByScoreWithScores(K key, double min, double max); /** @@ -229,9 +249,10 @@ public interface ZSetOperations { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set reverseRangeByScore(K key, double min, double max, long offset, long count); /** @@ -243,9 +264,10 @@ public interface ZSetOperations { * @param max * @param offset * @param count - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREVRANGEBYSCORE */ + @Nullable Set> reverseRangeByScoreWithScores(K key, double min, double max, long offset, long count); /** @@ -254,9 +276,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCOUNT */ + @Nullable Long count(K key, double min, double max); /** @@ -264,19 +287,21 @@ public interface ZSetOperations { * * @see #zCard(Object) * @param key - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZCARD */ + @Nullable Long size(K key); /** * Get the size of sorted set with {@code key}. * * @param key must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.3 * @see Redis Documentation: ZCARD */ + @Nullable Long zCard(K key); /** @@ -284,9 +309,10 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param o the value. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZSCORE */ + @Nullable Double score(K key, Object o); /** @@ -295,9 +321,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param start * @param end - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREMRANGEBYRANK */ + @Nullable Long removeRange(K key, long start, long end); /** @@ -306,9 +333,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param min * @param max - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZREMRANGEBYSCORE */ + @Nullable Long removeRangeByScore(K key, double min, double max); /** @@ -317,9 +345,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param otherKey must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZUNIONSTORE */ + @Nullable Long unionAndStore(K key, K otherKey, K destKey); /** @@ -328,9 +357,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param otherKeys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZUNIONSTORE */ + @Nullable Long unionAndStore(K key, Collection otherKeys, K destKey); /** @@ -339,9 +369,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param otherKey must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINTERSTORE */ + @Nullable Long intersectAndStore(K key, K otherKey, K destKey); /** @@ -350,9 +381,10 @@ public interface ZSetOperations { * @param key must not be {@literal null}. * @param otherKeys must not be {@literal null}. * @param destKey must not be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZINTERSTORE */ + @Nullable Long intersectAndStore(K key, Collection otherKeys, K destKey); /** @@ -361,7 +393,7 @@ public interface ZSetOperations { * * @param key * @param options - * @return + * @return {@literal null} when used in pipeline / transaction. * @see Redis Documentation: ZSCAN * @since 1.4 */ @@ -373,9 +405,11 @@ public interface ZSetOperations { * * @param key must not be {@literal null}. * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. * @since 1.7 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable Set rangeByLex(K key, Range range); /** @@ -386,11 +420,15 @@ public interface ZSetOperations { * @param key must not be {@literal null} * @param range must not be {@literal null}. * @param limit can be {@literal null}. - * @return + * @return {@literal null} when used in pipeline / transaction. * @since 1.7 * @see Redis Documentation: ZRANGEBYLEX */ + @Nullable Set rangeByLex(K key, Range range, Limit limit); + /** + * @return never {@literal null}. + */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/core/convert/BinaryConverters.java b/src/main/java/org/springframework/data/redis/core/convert/BinaryConverters.java index efc43ada3..44c2b3000 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/BinaryConverters.java +++ b/src/main/java/org/springframework/data/redis/core/convert/BinaryConverters.java @@ -25,6 +25,7 @@ import org.springframework.core.convert.converter.ConverterFactory; import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.WritingConverter; import org.springframework.util.NumberUtils; +import org.springframework.util.ObjectUtils; /** * Set of {@link ReadingConverter} and {@link WritingConverter} used to convert Objects into binary format. @@ -49,11 +50,6 @@ final class BinaryConverters { static class StringBasedConverter { byte[] fromString(String source) { - - if (source == null) { - return new byte[] {}; - } - return source.getBytes(CHARSET); } @@ -98,11 +94,6 @@ final class BinaryConverters { @Override public byte[] convert(Number source) { - - if (source == null) { - return new byte[] {}; - } - return fromString(source.toString()); } } @@ -117,11 +108,6 @@ final class BinaryConverters { @Override public byte[] convert(Enum source) { - - if (source == null) { - return new byte[] {}; - } - return fromString(source.name()); } } @@ -162,12 +148,11 @@ final class BinaryConverters { @Override public T convert(byte[] source) { - String value = toString(source); - - if (value == null || value.length() == 0) { + if (ObjectUtils.isEmpty(source)) { return null; } - return Enum.valueOf(this.enumType, value.trim()); + + return Enum.valueOf(this.enumType, toString(source).trim()); } } } @@ -196,7 +181,7 @@ final class BinaryConverters { @Override public T convert(byte[] source) { - if (source == null || source.length == 0) { + if (ObjectUtils.isEmpty(source)) { return null; } @@ -217,11 +202,6 @@ final class BinaryConverters { @Override public byte[] convert(Boolean source) { - - if (source == null) { - return new byte[] {}; - } - return source.booleanValue() ? _true : _false; } } @@ -236,7 +216,7 @@ final class BinaryConverters { @Override public Boolean convert(byte[] source) { - if (source == null || source.length == 0) { + if (ObjectUtils.isEmpty(source)) { return null; } @@ -254,11 +234,6 @@ final class BinaryConverters { @Override public byte[] convert(Date source) { - - if (source == null) { - return new byte[] {}; - } - return fromString(Long.toString(source.getTime())); } } @@ -273,7 +248,7 @@ final class BinaryConverters { @Override public Date convert(byte[] source) { - if (source == null || source.length == 0) { + if (ObjectUtils.isEmpty(source)) { return null; } diff --git a/src/main/java/org/springframework/data/redis/core/convert/Bucket.java b/src/main/java/org/springframework/data/redis/core/convert/Bucket.java index 0d290ac68..171b696bd 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/Bucket.java +++ b/src/main/java/org/springframework/data/redis/core/convert/Bucket.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -198,9 +199,6 @@ public class Bucket { public static Bucket newBucketFromRawMap(Map source) { Bucket bucket = new Bucket(); - if (source == null) { - return bucket; - } for (Map.Entry entry : source.entrySet()) { bucket.put(new String(entry.getKey(), CHARSET), entry.getValue()); @@ -217,13 +215,10 @@ public class Bucket { public static Bucket newBucketFromStringMap(Map source) { Bucket bucket = new Bucket(); - if (source == null) { - return bucket; - } for (Map.Entry entry : source.entrySet()) { - bucket.put(entry.getKey(), StringUtils.hasText(entry.getValue()) ? entry.getValue().getBytes(CHARSET) - : new byte[] {}); + bucket.put(entry.getKey(), + StringUtils.hasText(entry.getValue()) ? entry.getValue().getBytes(CHARSET) : new byte[] {}); } return bucket; } @@ -251,6 +246,7 @@ public class Bucket { } + @Nullable private String toUtf8String(byte[] raw) { try { diff --git a/src/main/java/org/springframework/data/redis/core/convert/IndexResolver.java b/src/main/java/org/springframework/data/redis/core/convert/IndexResolver.java index ce79e6c40..30d9b5d92 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/IndexResolver.java +++ b/src/main/java/org/springframework/data/redis/core/convert/IndexResolver.java @@ -19,6 +19,7 @@ import java.util.Set; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Nullable; /** * {@link IndexResolver} extracts secondary index structures to be applied on a given path, {@link PersistentProperty} @@ -36,7 +37,7 @@ public interface IndexResolver { * @param value the actual value. Can be {@literal null}. * @return never {@literal null}. */ - Set resolveIndexesFor(TypeInformation typeInformation, Object value); + Set resolveIndexesFor(TypeInformation typeInformation, @Nullable Object value); /** * Resolves all indexes for given type information / value combination. @@ -47,6 +48,7 @@ public interface IndexResolver { * @param value the actual value. Can be {@literal null}. * @return never {@literal null}. */ - Set resolveIndexesFor(String keyspace, String path, TypeInformation typeInformation, Object value); + Set resolveIndexesFor(String keyspace, String path, TypeInformation typeInformation, + @Nullable Object value); } diff --git a/src/main/java/org/springframework/data/redis/core/convert/KeyspaceConfiguration.java b/src/main/java/org/springframework/data/redis/core/convert/KeyspaceConfiguration.java index 215aa4b9b..040449dd7 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/KeyspaceConfiguration.java +++ b/src/main/java/org/springframework/data/redis/core/convert/KeyspaceConfiguration.java @@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.TimeToLive; import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -153,8 +154,8 @@ public class KeyspaceConfiguration { private final String keyspace; private final Class type; private final boolean inherit; - private Long timeToLive; - private String timeToLivePropertyName; + private @Nullable Long timeToLive; + private @Nullable String timeToLivePropertyName; public KeyspaceSettings(Class type, String keyspace) { this(type, keyspace, true); @@ -183,6 +184,7 @@ public class KeyspaceConfiguration { this.timeToLive = timeToLive; } + @Nullable public Long getTimeToLive() { return timeToLive; } @@ -191,6 +193,7 @@ public class KeyspaceConfiguration { timeToLivePropertyName = propertyName; } + @Nullable public String getTimeToLivePropertyName() { return timeToLivePropertyName; } diff --git a/src/main/java/org/springframework/data/redis/core/convert/RedisData.java b/src/main/java/org/springframework/data/redis/core/convert/RedisData.java index 5774d0551..c994d68f3 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/RedisData.java +++ b/src/main/java/org/springframework/data/redis/core/convert/RedisData.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -33,13 +34,13 @@ import org.springframework.util.Assert; */ public class RedisData { - private String keyspace; - private String id; + private @Nullable String keyspace; + private @Nullable String id; private Bucket bucket; private Set indexedData; - private Long timeToLive; + private @Nullable Long timeToLive; /** * Creates new {@link RedisData} with empty {@link Bucket}. @@ -81,6 +82,7 @@ public class RedisData { /** * @return */ + @Nullable public String getId() { return this.id; } @@ -90,6 +92,7 @@ public class RedisData { * * @return {@literal null} if not set. */ + @Nullable public Long getTimeToLive() { return timeToLive; } @@ -122,6 +125,7 @@ public class RedisData { /** * @return */ + @Nullable public String getKeyspace() { return keyspace; } diff --git a/src/main/java/org/springframework/data/redis/core/convert/SpelIndexResolver.java b/src/main/java/org/springframework/data/redis/core/convert/SpelIndexResolver.java index a08515727..0fe113461 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/SpelIndexResolver.java +++ b/src/main/java/org/springframework/data/redis/core/convert/SpelIndexResolver.java @@ -32,6 +32,7 @@ import org.springframework.expression.BeanResolver; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -47,7 +48,7 @@ public class SpelIndexResolver implements IndexResolver { private final SpelExpressionParser parser; private final RedisMappingContext mappingContext; - private BeanResolver beanResolver; + private @Nullable BeanResolver beanResolver; private Map expressionCache; @@ -79,7 +80,7 @@ public class SpelIndexResolver implements IndexResolver { /* (non-Javadoc) * @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(org.springframework.data.util.TypeInformation, java.lang.Object) */ - public Set resolveIndexesFor(TypeInformation typeInformation, Object value) { + public Set resolveIndexesFor(TypeInformation typeInformation, @Nullable Object value) { if (value == null) { return Collections.emptySet(); diff --git a/src/main/java/org/springframework/data/redis/core/convert/package-info.java b/src/main/java/org/springframework/data/redis/core/convert/package-info.java new file mode 100644 index 000000000..d064994da --- /dev/null +++ b/src/main/java/org/springframework/data/redis/core/convert/package-info.java @@ -0,0 +1,5 @@ +/** + * Converters for Redis repository support utilizing mapping metadata. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.core.convert; diff --git a/src/main/java/org/springframework/data/redis/core/index/RedisIndexDefinition.java b/src/main/java/org/springframework/data/redis/core/index/RedisIndexDefinition.java index 08563c315..0d6f25082 100644 --- a/src/main/java/org/springframework/data/redis/core/index/RedisIndexDefinition.java +++ b/src/main/java/org/springframework/data/redis/core/index/RedisIndexDefinition.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -36,7 +37,7 @@ public abstract class RedisIndexDefinition implements IndexDefinition { private final String indexName; private final String path; private List> conditions; - private IndexValueTransformer valueTransformer; + private @Nullable IndexValueTransformer valueTransformer; /** * Creates new {@link RedisIndexDefinition}. diff --git a/src/main/java/org/springframework/data/redis/core/index/package-info.java b/src/main/java/org/springframework/data/redis/core/index/package-info.java new file mode 100644 index 000000000..3c348dc53 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/core/index/package-info.java @@ -0,0 +1,5 @@ +/** + * Abstractions for Redis secondary indexes. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.core.index; diff --git a/src/main/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntity.java b/src/main/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntity.java index 59f8aed32..42d4e2855 100644 --- a/src/main/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntity.java +++ b/src/main/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntity.java @@ -22,6 +22,7 @@ import org.springframework.data.mapping.MappingException; import org.springframework.data.redis.core.TimeToLive; import org.springframework.data.redis.core.TimeToLiveAccessor; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -74,6 +75,7 @@ public class BasicRedisPersistentEntity extends BasicKeyValuePersistentEntity * @see org.springframework.data.redis.core.mapping.RedisPersistentEntity#getExplicitTimeToLiveProperty() */ @Override + @Nullable public RedisPersistentProperty getExplicitTimeToLiveProperty() { return this.getPersistentProperty(TimeToLive.class); } @@ -83,6 +85,7 @@ public class BasicRedisPersistentEntity extends BasicKeyValuePersistentEntity * @see org.springframework.data.mapping.model.BasicPersistentEntity#returnPropertyIfBetterIdPropertyCandidateOrNull(org.springframework.data.mapping.PersistentProperty) */ @Override + @Nullable protected RedisPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(RedisPersistentProperty property) { Assert.notNull(property, "Property must not be null!"); diff --git a/src/main/java/org/springframework/data/redis/core/mapping/RedisMappingContext.java b/src/main/java/org/springframework/data/redis/core/mapping/RedisMappingContext.java index 27e274500..2f0a28ab4 100644 --- a/src/main/java/org/springframework/data/redis/core/mapping/RedisMappingContext.java +++ b/src/main/java/org/springframework/data/redis/core/mapping/RedisMappingContext.java @@ -41,6 +41,7 @@ import org.springframework.data.redis.core.convert.MappingConfiguration; import org.springframework.data.redis.core.convert.RedisCustomConversions; import org.springframework.data.redis.core.index.IndexConfiguration; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.NumberUtils; @@ -61,7 +62,7 @@ public class RedisMappingContext extends KeyValueMappingContext extends KeyValuePersistentEntityRedis with Spring concepts. - * - *

Provides template support and callback for low-level access. + * Core package for integrating Redis with Spring concepts. + *

+ * Provides template support and callback for low-level access. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.core; - diff --git a/src/main/java/org/springframework/data/redis/core/query/DefaultSortCriterion.java b/src/main/java/org/springframework/data/redis/core/query/DefaultSortCriterion.java index de0d0b46a..d03a8a5d1 100644 --- a/src/main/java/org/springframework/data/redis/core/query/DefaultSortCriterion.java +++ b/src/main/java/org/springframework/data/redis/core/query/DefaultSortCriterion.java @@ -20,21 +20,23 @@ import java.util.List; import org.springframework.data.redis.connection.SortParameters.Order; import org.springframework.data.redis.connection.SortParameters.Range; +import org.springframework.lang.Nullable; /** * Default implementation for {@link SortCriterion}. * * @author Costin Leau + * @author Christoph Strobl */ class DefaultSortCriterion implements SortCriterion { private final K key; - private String by; + private @Nullable String by; private final List getKeys = new ArrayList<>(4); - private Range limit; - private Order order; - private Boolean alpha; + private @Nullable Range limit; + private @Nullable Order order; + private @Nullable Boolean alpha; DefaultSortCriterion(K key) { this.key = key; @@ -54,6 +56,8 @@ class DefaultSortCriterion implements SortCriterion { return this; } + // TODO: check if we can use differnt range from SD commons here?? + public SortCriterion limit(Range range) { this.limit = range; return this; diff --git a/src/main/java/org/springframework/data/redis/core/query/package-info.java b/src/main/java/org/springframework/data/redis/core/query/package-info.java index d2c434a6d..ab0db10ef 100644 --- a/src/main/java/org/springframework/data/redis/core/query/package-info.java +++ b/src/main/java/org/springframework/data/redis/core/query/package-info.java @@ -1,5 +1,6 @@ /** * Query package for Redis template. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.core.query; diff --git a/src/main/java/org/springframework/data/redis/core/script/DefaultRedisScript.java b/src/main/java/org/springframework/data/redis/core/script/DefaultRedisScript.java index 7723ef0ed..894891bae 100644 --- a/src/main/java/org/springframework/data/redis/core/script/DefaultRedisScript.java +++ b/src/main/java/org/springframework/data/redis/core/script/DefaultRedisScript.java @@ -19,6 +19,7 @@ import java.io.IOException; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; +import org.springframework.lang.Nullable; import org.springframework.scripting.ScriptSource; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.scripting.support.StaticScriptSource; @@ -36,9 +37,9 @@ import org.springframework.util.Assert; */ public class DefaultRedisScript implements RedisScript, InitializingBean { - private ScriptSource scriptSource; - private String sha1; - private Class resultType; + private @Nullable ScriptSource scriptSource; + private @Nullable String sha1; + private @Nullable Class resultType; private final Object shaModifiedMonitor = new Object(); /** @@ -96,6 +97,7 @@ public class DefaultRedisScript implements RedisScript, InitializingBean { * (non-Javadoc) * @see org.springframework.data.redis.core.script.RedisScript#getResultType() */ + @Nullable public Class getResultType() { return this.resultType; } diff --git a/src/main/java/org/springframework/data/redis/core/script/RedisScript.java b/src/main/java/org/springframework/data/redis/core/script/RedisScript.java index 68e42a1c0..f2f12b672 100644 --- a/src/main/java/org/springframework/data/redis/core/script/RedisScript.java +++ b/src/main/java/org/springframework/data/redis/core/script/RedisScript.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.core.script; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -37,6 +38,7 @@ public interface RedisScript { * @return The script result type. Should be one of Long, Boolean, List, or deserialized value type. {@literal null} * if the script returns a throw-away status (i.e "OK"). */ + @Nullable Class getResultType(); /** diff --git a/src/main/java/org/springframework/data/redis/core/script/package-info.java b/src/main/java/org/springframework/data/redis/core/script/package-info.java new file mode 100644 index 000000000..ae6deb18f --- /dev/null +++ b/src/main/java/org/springframework/data/redis/core/script/package-info.java @@ -0,0 +1,5 @@ +/** + * Lua script execution abstraction. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.core.script; diff --git a/src/main/java/org/springframework/data/redis/core/types/package-info.java b/src/main/java/org/springframework/data/redis/core/types/package-info.java new file mode 100644 index 000000000..64571585d --- /dev/null +++ b/src/main/java/org/springframework/data/redis/core/types/package-info.java @@ -0,0 +1,5 @@ +/** + * Redis domain specific types. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.core.types; diff --git a/src/main/java/org/springframework/data/redis/hash/package-info.java b/src/main/java/org/springframework/data/redis/hash/package-info.java index 48420b78c..358dfbc10 100644 --- a/src/main/java/org/springframework/data/redis/hash/package-info.java +++ b/src/main/java/org/springframework/data/redis/hash/package-info.java @@ -1,7 +1,5 @@ /** - * Dedicated support package for Redis hashes. - * - * Provides mapping of objects to hashes/maps (and vice versa). + * Dedicated support package for Redis hashes. Provides mapping of objects to hashes/maps (and vice versa). */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.hash; - diff --git a/src/main/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListener.java b/src/main/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListener.java index 3c4b63066..8d047af3b 100644 --- a/src/main/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListener.java +++ b/src/main/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListener.java @@ -20,6 +20,7 @@ import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.core.RedisKeyExpiredEvent; +import org.springframework.lang.Nullable; /** * {@link MessageListener} publishing {@link RedisKeyExpiredEvent}s via {@link ApplicationEventPublisher} by listening @@ -31,7 +32,7 @@ import org.springframework.data.redis.core.RedisKeyExpiredEvent; public class KeyExpirationEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware { - private ApplicationEventPublisher publisher; + private @Nullable ApplicationEventPublisher publisher; private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@*__:expired"); /** diff --git a/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java b/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java index ab9535bb9..7b5c92cc9 100644 --- a/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java +++ b/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java @@ -22,7 +22,9 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -54,9 +56,9 @@ public abstract class KeyspaceEventMessageListener implements MessageListener, I * @see org.springframework.data.redis.connection.MessageListener#onMessage(org.springframework.data.redis.connection.Message, byte[]) */ @Override - public void onMessage(Message message, byte[] pattern) { + public void onMessage(Message message, @Nullable byte[] pattern) { - if (message == null || message.getChannel() == null || message.getBody() == null) { + if (message == null || ObjectUtils.isEmpty(message.getChannel()) || ObjectUtils.isEmpty(message.getBody())) { return; } diff --git a/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java b/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java index db4110601..10d9990fb 100644 --- a/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java +++ b/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java @@ -44,6 +44,7 @@ import org.springframework.data.redis.connection.Subscription; import org.springframework.data.redis.connection.util.ByteArrayWrapper; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.lang.Nullable; import org.springframework.scheduling.SchedulingAwareRunnable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -92,15 +93,15 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab private long initWait = TimeUnit.SECONDS.toMillis(5); - private Executor subscriptionExecutor; + private @Nullable Executor subscriptionExecutor; - private Executor taskExecutor; + private @Nullable Executor taskExecutor; - private RedisConnectionFactory connectionFactory; + private @Nullable RedisConnectionFactory connectionFactory; - private String beanName; + private @Nullable String beanName; - private ErrorHandler errorHandler; + private @Nullable ErrorHandler errorHandler; private final Object monitor = new Object(); // whether the container is running (or not) @@ -297,6 +298,7 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab * * @return Returns the connectionFactory */ + @Nullable public RedisConnectionFactory getConnectionFactory() { return connectionFactory; } @@ -305,6 +307,8 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab * @param connectionFactory The connectionFactory to set. */ public void setConnectionFactory(RedisConnectionFactory connectionFactory) { + + Assert.notNull(connectionFactory, "ConnectionFactory must not be null!"); this.connectionFactory = connectionFactory; } @@ -715,7 +719,7 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab } } - private volatile RedisConnection connection; + private volatile @Nullable RedisConnection connection; private boolean subscriptionTaskRunning = false; private final Object localMonitor = new Object(); private long subscriptionWait = TimeUnit.SECONDS.toMillis(5); @@ -940,7 +944,8 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab */ private class DispatchMessageListener implements MessageListener { - public void onMessage(Message message, byte[] pattern) { + @Override + public void onMessage(Message message, @Nullable byte[] pattern) { Collection listeners = null; // if it's a pattern, disregard channel diff --git a/src/main/java/org/springframework/data/redis/listener/adapter/MessageListenerAdapter.java b/src/main/java/org/springframework/data/redis/listener/adapter/MessageListenerAdapter.java index 18b9a6a8a..8176953e7 100644 --- a/src/main/java/org/springframework/data/redis/listener/adapter/MessageListenerAdapter.java +++ b/src/main/java/org/springframework/data/redis/listener/adapter/MessageListenerAdapter.java @@ -31,6 +31,7 @@ import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -95,7 +96,7 @@ import org.springframework.util.StringUtils; */ public class MessageListenerAdapter implements InitializingBean, MessageListener { - + // TODO move this down. private class MethodInvoker { private final Object delegate; @@ -129,9 +130,9 @@ public class MessageListenerAdapter implements InitializingBean, MessageListener Class[] types = m.getParameterTypes(); Object[] args = // - types.length == 2 // - && types[0].isInstance(arguments[0]) // - && types[1].isInstance(arguments[1]) ? arguments : message; + types.length == 2 // + && types[0].isInstance(arguments[0]) // + && types[1].isInstance(arguments[1]) ? arguments : message; if (!types[0].isInstance(args[0])) { continue; @@ -161,15 +162,15 @@ public class MessageListenerAdapter implements InitializingBean, MessageListener /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); - private volatile Object delegate; + private volatile @Nullable Object delegate; - private volatile MethodInvoker invoker; + private volatile @Nullable MethodInvoker invoker; private String defaultListenerMethod = ORIGINAL_DEFAULT_LISTENER_METHOD; - private RedisSerializer serializer; + private @Nullable RedisSerializer serializer; - private RedisSerializer stringSerializer; + private @Nullable RedisSerializer stringSerializer; /** * Create a new {@link MessageListenerAdapter} with default settings. @@ -220,6 +221,7 @@ public class MessageListenerAdapter implements InitializingBean, MessageListener * * @return message listening delegation */ + @Nullable public Object getDelegate() { return this.delegate; } @@ -284,8 +286,8 @@ public class MessageListenerAdapter implements InitializingBean, MessageListener * @param message the incoming Redis message * @see #handleListenerException */ - - public void onMessage(Message message, byte[] pattern) { + @Override + public void onMessage(Message message, @Nullable byte[] pattern) { try { // Check whether the delegate is a MessageListener impl itself. // In that case, the adapter will simply act as a pass-through. diff --git a/src/main/java/org/springframework/data/redis/listener/adapter/package-info.java b/src/main/java/org/springframework/data/redis/listener/adapter/package-info.java index 50806356e..37aa45274 100644 --- a/src/main/java/org/springframework/data/redis/listener/adapter/package-info.java +++ b/src/main/java/org/springframework/data/redis/listener/adapter/package-info.java @@ -1,7 +1,6 @@ /** - * Message listener adapter package. - * The adapter delegates to target listener methods, converting messages to appropriate message content types - * (such as String or byte array) that get passed into listener methods. + * Message listener adapter package. The adapter delegates to target listener methods, converting messages to + * appropriate message content types (such as String or byte array) that get passed into listener methods. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.listener.adapter; - diff --git a/src/main/java/org/springframework/data/redis/listener/package-info.java b/src/main/java/org/springframework/data/redis/listener/package-info.java index 855cc5f5b..52912f83b 100644 --- a/src/main/java/org/springframework/data/redis/listener/package-info.java +++ b/src/main/java/org/springframework/data/redis/listener/package-info.java @@ -1,5 +1,5 @@ /** - * Base package for Redis message listener / pubsub container facility + * Base package for Redis message listener / pubsub container facility */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.listener; - diff --git a/src/main/java/org/springframework/data/redis/package-info.java b/src/main/java/org/springframework/data/redis/package-info.java index 441d731df..bd4936a42 100644 --- a/src/main/java/org/springframework/data/redis/package-info.java +++ b/src/main/java/org/springframework/data/redis/package-info.java @@ -1,8 +1,7 @@ /** - * Root package for integrating Redis with Spring concepts. + * Root package for integrating Redis with Spring concepts. *

- * Provides Redis specific exception hierarchy on top of the {@code org.springframework.dao} package. - * + * Provides Redis specific exception hierarchy on top of the {@code org.springframework.dao} package. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis; - diff --git a/src/main/java/org/springframework/data/redis/repository/cdi/package-info.java b/src/main/java/org/springframework/data/redis/repository/cdi/package-info.java index 85bc35bf6..97d838c0b 100644 --- a/src/main/java/org/springframework/data/redis/repository/cdi/package-info.java +++ b/src/main/java/org/springframework/data/redis/repository/cdi/package-info.java @@ -1,20 +1,5 @@ -/* - * Copyright 2016 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. - */ - /** * CDI support for Redis specific repository implementation. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.repository.cdi; diff --git a/src/main/java/org/springframework/data/redis/repository/configuration/package-info.java b/src/main/java/org/springframework/data/redis/repository/configuration/package-info.java new file mode 100644 index 000000000..33682f5ac --- /dev/null +++ b/src/main/java/org/springframework/data/redis/repository/configuration/package-info.java @@ -0,0 +1,5 @@ +/** + * Redis repository specific configuration and bean registration. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.repository.configuration; diff --git a/src/main/java/org/springframework/data/redis/repository/core/package-info.java b/src/main/java/org/springframework/data/redis/repository/core/package-info.java new file mode 100644 index 000000000..72facbc20 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/repository/core/package-info.java @@ -0,0 +1,5 @@ +/** + * Core domain entities for repository support. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.repository.core; \ No newline at end of file diff --git a/src/main/java/org/springframework/data/redis/repository/package-info.java b/src/main/java/org/springframework/data/redis/repository/package-info.java new file mode 100644 index 000000000..db7ca62a1 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/repository/package-info.java @@ -0,0 +1,5 @@ +/** + * Redis specific implementation of repository support + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.repository; diff --git a/src/main/java/org/springframework/data/redis/repository/query/RedisOperationChain.java b/src/main/java/org/springframework/data/redis/repository/query/RedisOperationChain.java index e34418f81..c7c736489 100644 --- a/src/main/java/org/springframework/data/redis/repository/query/RedisOperationChain.java +++ b/src/main/java/org/springframework/data/redis/repository/query/RedisOperationChain.java @@ -24,6 +24,8 @@ import java.util.Set; import org.springframework.data.geo.Distance; import org.springframework.data.geo.Point; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -36,7 +38,7 @@ public class RedisOperationChain { private Set sismember = new LinkedHashSet<>(); private Set orSismember = new LinkedHashSet<>(); - private NearPath near; + private @Nullable NearPath near; public void sismember(String path, Object value) { sismember(new PathAndValue(path, value)); @@ -67,9 +69,12 @@ public class RedisOperationChain { } public void near(NearPath near) { + + Assert.notNull(near, "Near must not be null!"); this.near = near; } + @Nullable public NearPath getNear() { return near; } @@ -85,7 +90,7 @@ public class RedisOperationChain { this.values = Collections.singleton(singleValue); } - public PathAndValue(String path, Collection values) { + public PathAndValue(String path, @Nullable Collection values) { this.path = path; this.values = values != null ? values : Collections.emptySet(); @@ -148,7 +153,7 @@ public class RedisOperationChain { public static class NearPath extends PathAndValue { public NearPath(String path, Point point, Distance distance) { - super(path, Arrays. asList(point, distance)); + super(path, Arrays.asList(point, distance)); } public Point getPoint() { diff --git a/src/main/java/org/springframework/data/redis/repository/query/package-info.java b/src/main/java/org/springframework/data/redis/repository/query/package-info.java new file mode 100644 index 000000000..7be95016a --- /dev/null +++ b/src/main/java/org/springframework/data/redis/repository/query/package-info.java @@ -0,0 +1,5 @@ +/** + * Redis specific query execution engine. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.repository.query; diff --git a/src/main/java/org/springframework/data/redis/repository/support/package-info.java b/src/main/java/org/springframework/data/redis/repository/support/package-info.java new file mode 100644 index 000000000..d2be454d6 --- /dev/null +++ b/src/main/java/org/springframework/data/redis/repository/support/package-info.java @@ -0,0 +1,5 @@ +/** + * Spring context specific factory support. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.repository.support; 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 59439f285..b4d810e06 100644 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementReader.java @@ -19,6 +19,8 @@ import lombok.RequiredArgsConstructor; import java.nio.ByteBuffer; +import org.springframework.lang.Nullable; + /** * Default implementation of {@link RedisElementReader}. * @@ -29,7 +31,7 @@ import java.nio.ByteBuffer; @RequiredArgsConstructor class DefaultRedisElementReader implements RedisElementReader { - private final RedisSerializer serializer; + private final @Nullable RedisSerializer serializer; /* (non-Javadoc) * @see org.springframework.data.redis.serializer.RedisElementReader#read(java.nio.ByteBuffer) diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementWriter.java b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementWriter.java index 49fa19e0f..f404d732c 100644 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementWriter.java +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisElementWriter.java @@ -19,16 +19,19 @@ import lombok.RequiredArgsConstructor; import java.nio.ByteBuffer; +import org.springframework.lang.Nullable; + /** * Default implementation of {@link RedisElementWriter}. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 */ @RequiredArgsConstructor class DefaultRedisElementWriter implements RedisElementWriter { - private final RedisSerializer serializer; + private final @Nullable RedisSerializer serializer; /* (non-Javadoc) * @see org.springframework.data.redis.serializer.RedisElementWriter#write(java.lang.Object) @@ -36,19 +39,19 @@ class DefaultRedisElementWriter implements RedisElementWriter { @Override public ByteBuffer write(T value) { - if (serializer == null) { - - if (value instanceof byte[]) { - return ByteBuffer.wrap((byte[]) value); - } - - if (value instanceof ByteBuffer) { - return (ByteBuffer) value; - } - - throw new IllegalStateException("Cannot serialize value without a serializer"); + if (serializer != null) { + return ByteBuffer.wrap(serializer.serialize((T) value)); } - return ByteBuffer.wrap(serializer.serialize((T) value)); + if (value instanceof byte[]) { + return ByteBuffer.wrap((byte[]) value); + } + + if (value instanceof ByteBuffer) { + return (ByteBuffer) value; + } + + throw new IllegalStateException("Cannot serialize value without a serializer"); + } } diff --git a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java index 2fc1de814..772fd52f1 100644 --- a/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java +++ b/src/main/java/org/springframework/data/redis/serializer/DefaultRedisSerializationContext.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.serializer; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -93,10 +94,10 @@ class DefaultRedisSerializationContext implements RedisSerializationContex */ static class DefaultRedisSerializationContextBuilder implements RedisSerializationContextBuilder { - private SerializationPair keyTuple; - private SerializationPair valueTuple; - private SerializationPair hashKeyTuple; - private SerializationPair hashValueTuple; + private @Nullable SerializationPair keyTuple; + private @Nullable SerializationPair valueTuple; + private @Nullable SerializationPair hashKeyTuple; + private @Nullable SerializationPair hashValueTuple; private SerializationPair stringTuple = SerializationPair.fromSerializer(new StringRedisSerializer()); /* (non-Javadoc) diff --git a/src/main/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializer.java index 3d000328c..f9ac7ad19 100644 --- a/src/main/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializer.java @@ -18,6 +18,7 @@ package org.springframework.data.redis.serializer; import java.io.IOException; import org.springframework.cache.support.NullValue; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -87,7 +88,7 @@ public class GenericJackson2JsonRedisSerializer implements RedisSerializer T deserialize(byte[] source, Class type) throws SerializationException { + public T deserialize(@Nullable byte[] source, Class type) throws SerializationException { Assert.notNull(type, "Deserialization type must not be null! Pleaes provide Object.class to make use of Jackson2 default typing."); diff --git a/src/main/java/org/springframework/data/redis/serializer/GenericToStringSerializer.java b/src/main/java/org/springframework/data/redis/serializer/GenericToStringSerializer.java index 666d53331..fd6532c90 100644 --- a/src/main/java/org/springframework/data/redis/serializer/GenericToStringSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/GenericToStringSerializer.java @@ -24,6 +24,7 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -61,7 +62,9 @@ public class GenericToStringSerializer implements RedisSerializer, BeanFac converter = new Converter(typeConverter); } - public T deserialize(byte[] bytes) { + @Override + public T deserialize(@Nullable byte[] bytes) { + if (bytes == null) { return null; } @@ -70,7 +73,8 @@ public class GenericToStringSerializer implements RedisSerializer, BeanFac return converter.convert(string, type); } - public byte[] serialize(T object) { + @Override + public byte[] serialize(@Nullable T object) { if (object == null) { return null; } @@ -83,7 +87,8 @@ public class GenericToStringSerializer implements RedisSerializer, BeanFac ConfigurableBeanFactory cFB = (ConfigurableBeanFactory) beanFactory; ConversionService conversionService = cFB.getConversionService(); - converter = (conversionService != null ? new Converter(conversionService) : new Converter(cFB.getTypeConverter())); + converter = (conversionService != null ? new Converter(conversionService) + : new Converter(cFB.getTypeConverter())); } } diff --git a/src/main/java/org/springframework/data/redis/serializer/Jackson2JsonRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/Jackson2JsonRedisSerializer.java index c8b86c8ab..82eea9b32 100644 --- a/src/main/java/org/springframework/data/redis/serializer/Jackson2JsonRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/Jackson2JsonRedisSerializer.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.serializer; import java.nio.charset.Charset; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import com.fasterxml.jackson.databind.JavaType; @@ -62,7 +63,7 @@ public class Jackson2JsonRedisSerializer implements RedisSerializer { } @SuppressWarnings("unchecked") - public T deserialize(byte[] bytes) throws SerializationException { + public T deserialize(@Nullable byte[] bytes) throws SerializationException { if (SerializationUtils.isEmpty(bytes)) { return null; @@ -74,7 +75,8 @@ public class Jackson2JsonRedisSerializer implements RedisSerializer { } } - public byte[] serialize(Object t) throws SerializationException { + @Override + public byte[] serialize(@Nullable Object t) throws SerializationException { if (t == null) { return SerializationUtils.EMPTY_ARRAY; diff --git a/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java index e7fde0c23..0794e3e10 100644 --- a/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java @@ -20,6 +20,7 @@ import org.springframework.core.serializer.DefaultDeserializer; import org.springframework.core.serializer.DefaultSerializer; import org.springframework.core.serializer.support.DeserializingConverter; import org.springframework.core.serializer.support.SerializingConverter; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -71,7 +72,8 @@ public class JdkSerializationRedisSerializer implements RedisSerializer this.deserializer = deserializer; } - public Object deserialize(byte[] bytes) { + public Object deserialize(@Nullable byte[] bytes) { + if (SerializationUtils.isEmpty(bytes)) { return null; } @@ -83,7 +85,8 @@ public class JdkSerializationRedisSerializer implements RedisSerializer } } - public byte[] serialize(Object object) { + @Override + public byte[] serialize(@Nullable Object object) { if (object == null) { return SerializationUtils.EMPTY_ARRAY; } diff --git a/src/main/java/org/springframework/data/redis/serializer/OxmSerializer.java b/src/main/java/org/springframework/data/redis/serializer/OxmSerializer.java index 0555f2ab9..0ca7380ca 100644 --- a/src/main/java/org/springframework/data/redis/serializer/OxmSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/OxmSerializer.java @@ -22,6 +22,7 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.springframework.beans.factory.InitializingBean; +import org.springframework.lang.Nullable; import org.springframework.oxm.Marshaller; import org.springframework.oxm.Unmarshaller; import org.springframework.util.Assert; @@ -34,12 +35,13 @@ import org.springframework.util.Assert; */ public class OxmSerializer implements InitializingBean, RedisSerializer { - private Marshaller marshaller; - private Unmarshaller unmarshaller; + private @Nullable Marshaller marshaller; + private @Nullable Unmarshaller unmarshaller; public OxmSerializer() {} public OxmSerializer(Marshaller marshaller, Unmarshaller unmarshaller) { + this.marshaller = marshaller; this.unmarshaller = unmarshaller; @@ -47,7 +49,8 @@ public class OxmSerializer implements InitializingBean, RedisSerializer } public void afterPropertiesSet() { - Assert.notNull(marshaller, "non-null marshaller required"); + + Assert.notNull(marshaller, "non-null marshaller required"); // TODO: use Illegal state exception Assert.notNull(unmarshaller, "non-null unmarshaller required"); } @@ -65,7 +68,8 @@ public class OxmSerializer implements InitializingBean, RedisSerializer this.unmarshaller = unmarshaller; } - public Object deserialize(byte[] bytes) throws SerializationException { + @Override + public Object deserialize(@Nullable byte[] bytes) throws SerializationException { if (SerializationUtils.isEmpty(bytes)) { return null; } @@ -77,7 +81,8 @@ public class OxmSerializer implements InitializingBean, RedisSerializer } } - public byte[] serialize(Object t) throws SerializationException { + @Override + public byte[] serialize(@Nullable Object t) throws SerializationException { if (t == null) { return SerializationUtils.EMPTY_ARRAY; } diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisElementReader.java b/src/main/java/org/springframework/data/redis/serializer/RedisElementReader.java index dc39b0e81..abba654ff 100644 --- a/src/main/java/org/springframework/data/redis/serializer/RedisElementReader.java +++ b/src/main/java/org/springframework/data/redis/serializer/RedisElementReader.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.serializer; import java.nio.ByteBuffer; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -34,8 +35,9 @@ public interface RedisElementReader { * Deserialize a {@link ByteBuffer} into the according type. * * @param buffer must not be {@literal null}. - * @return the deserialized value. + * @return the deserialized value. Can be {@literal null}. */ + @Nullable T read(ByteBuffer buffer); /** diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java index 434fa73ad..f1c4b0496 100644 --- a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.serializer; +import org.springframework.lang.Nullable; + /** * Basic interface serialization and deserialization of Objects to byte arrays (binary data). It is recommended that * implementations are designed to handle null objects/empty arrays on serialization and deserialization side. Note that @@ -22,22 +24,25 @@ package org.springframework.data.redis.serializer; * * @author Mark Pollack * @author Costin Leau + * @author Christoph Strobl */ public interface RedisSerializer { /** * Serialize the given object to binary data. * - * @param t object to serialize - * @return the equivalent binary data + * @param t object to serialize. Can be {@literal null}. + * @return the equivalent binary data. Can be {@literal null}. */ - byte[] serialize(T t) throws SerializationException; + @Nullable + byte[] serialize(@Nullable T t) throws SerializationException; /** * Deserialize an object from the given binary data. * - * @param bytes object binary representation - * @return the equivalent object instance + * @param bytes object binary representation. Can be {@literal null}. + * @return the equivalent object instance. Can be {@literal null}. */ - T deserialize(byte[] bytes) throws SerializationException; + @Nullable + T deserialize(@Nullable byte[] bytes) throws SerializationException; } diff --git a/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java b/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java index 59be7f1c4..a5fcfeb4d 100644 --- a/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java +++ b/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java @@ -17,12 +17,16 @@ package org.springframework.data.redis.serializer; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.core.CollectionFactory; +import org.springframework.lang.Nullable; + /** * Utility class with various serialization-related methods. * @@ -32,16 +36,16 @@ public abstract class SerializationUtils { static final byte[] EMPTY_ARRAY = new byte[0]; - static boolean isEmpty(byte[] data) { + static boolean isEmpty(@Nullable byte[] data) { return (data == null || data.length == 0); } @SuppressWarnings("unchecked") - static > T deserializeValues(Collection rawValues, Class type, + static > T deserializeValues(@Nullable Collection rawValues, Class type, RedisSerializer redisSerializer) { // connection in pipeline/multi mode if (rawValues == null) { - return null; + return (T) CollectionFactory.createCollection(type, 0); } Collection values = (List.class.isAssignableFrom(type) ? new ArrayList<>(rawValues.size()) @@ -54,23 +58,25 @@ public abstract class SerializationUtils { } @SuppressWarnings("unchecked") - public static Set deserialize(Set rawValues, RedisSerializer redisSerializer) { + public static Set deserialize(@Nullable Set rawValues, RedisSerializer redisSerializer) { return deserializeValues(rawValues, Set.class, redisSerializer); } @SuppressWarnings("unchecked") - public static List deserialize(List rawValues, RedisSerializer redisSerializer) { + public static List deserialize(@Nullable List rawValues, RedisSerializer redisSerializer) { return deserializeValues(rawValues, List.class, redisSerializer); } @SuppressWarnings("unchecked") - public static Collection deserialize(Collection rawValues, RedisSerializer redisSerializer) { + public static Collection deserialize(@Nullable Collection rawValues, + RedisSerializer redisSerializer) { return deserializeValues(rawValues, List.class, redisSerializer); } - public static Map deserialize(Map rawValues, RedisSerializer redisSerializer) { + public static Map deserialize(@Nullable Map rawValues, RedisSerializer redisSerializer) { + if (rawValues == null) { - return null; + return Collections.emptyMap(); } Map ret = new LinkedHashMap<>(rawValues.size()); for (Map.Entry entry : rawValues.entrySet()) { @@ -80,17 +86,18 @@ public abstract class SerializationUtils { } @SuppressWarnings("unchecked") - public static Map deserialize(Map rawValues, RedisSerializer hashKeySerializer, - RedisSerializer hashValueSerializer) { + public static Map deserialize(@Nullable Map rawValues, + RedisSerializer hashKeySerializer, RedisSerializer hashValueSerializer) { + if (rawValues == null) { - return null; + return Collections.emptyMap(); } Map map = new LinkedHashMap<>(rawValues.size()); for (Map.Entry entry : rawValues.entrySet()) { // May want to deserialize only key or value HK key = hashKeySerializer != null ? (HK) hashKeySerializer.deserialize(entry.getKey()) : (HK) entry.getKey(); - HV value = hashValueSerializer != null ? (HV) hashValueSerializer.deserialize(entry.getValue()) : (HV) entry - .getValue(); + HV value = hashValueSerializer != null ? (HV) hashValueSerializer.deserialize(entry.getValue()) + : (HV) entry.getValue(); map.put(key, value); } return map; diff --git a/src/main/java/org/springframework/data/redis/serializer/StringRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/StringRedisSerializer.java index 5aa898840..3c1a5c22a 100644 --- a/src/main/java/org/springframework/data/redis/serializer/StringRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/StringRedisSerializer.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.serializer; import java.nio.charset.Charset; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -43,11 +44,11 @@ public class StringRedisSerializer implements RedisSerializer { this.charset = charset; } - public String deserialize(byte[] bytes) { + public String deserialize(@Nullable byte[] bytes) { return (bytes == null ? null : new String(bytes, charset)); } - public byte[] serialize(String string) { + public byte[] serialize(@Nullable String string) { return (string == null ? null : string.getBytes(charset)); } } diff --git a/src/main/java/org/springframework/data/redis/serializer/package-info.java b/src/main/java/org/springframework/data/redis/serializer/package-info.java index 3956423a5..f11776cf2 100644 --- a/src/main/java/org/springframework/data/redis/serializer/package-info.java +++ b/src/main/java/org/springframework/data/redis/serializer/package-info.java @@ -1,5 +1,5 @@ /** - * Serialization/Deserialization package for converting Object to (and from) binary data. + * Serialization/Deserialization package for converting Object to (and from) binary data. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.serializer; - diff --git a/src/main/java/org/springframework/data/redis/support/atomic/package-info.java b/src/main/java/org/springframework/data/redis/support/atomic/package-info.java index 872a8018a..ee64b49b2 100644 --- a/src/main/java/org/springframework/data/redis/support/atomic/package-info.java +++ b/src/main/java/org/springframework/data/redis/support/atomic/package-info.java @@ -1,5 +1,5 @@ /** - * Small toolkit mirroring the {@code java.util.atomic} package in Redis. + * Small toolkit mirroring the {@code java.util.atomic} package in Redis. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.support.atomic; - diff --git a/src/main/java/org/springframework/data/redis/support/collections/AbstractRedisCollection.java b/src/main/java/org/springframework/data/redis/support/collections/AbstractRedisCollection.java index b79622fc9..1d942c22f 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/AbstractRedisCollection.java +++ b/src/main/java/org/springframework/data/redis/support/collections/AbstractRedisCollection.java @@ -21,6 +21,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.RedisOperations; +import org.springframework.lang.Nullable; /** * Base implementation for {@link RedisCollection}. Provides a skeletal implementation. Note that the collection support @@ -124,7 +125,7 @@ public abstract class AbstractRedisCollection extends AbstractCollection i key = newKey; } - protected void checkResult(Object obj) { + protected void checkResult(@Nullable Object obj) { if (obj == null) { throw new IllegalStateException("Cannot read collection with Redis connection in pipeline/multi-exec mode"); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisList.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisList.java index dc822b98b..da32533e7 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisList.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisList.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.core.BoundListOperations; import org.springframework.data.redis.core.RedisOperations; +import org.springframework.lang.Nullable; /** * Default implementation for {@link RedisList}. Suitable for not just lists, but also queues (FIFO ordering) or stacks @@ -34,6 +35,7 @@ import org.springframework.data.redis.core.RedisOperations; * not - the list will always accept new items (trimming the tail after each insert in case of capped collections). * * @author Costin Leau + * @author Christoph Strobl */ public class DefaultRedisList extends AbstractRedisCollection implements RedisList { @@ -220,6 +222,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R } public E set(int index, E e) { + E object = get(index); listOps.set(index, e); return object; @@ -235,8 +238,9 @@ public class DefaultRedisList extends AbstractRedisCollection implements R public E element() { E value = peek(); - if (value == null) + if (value == null) { throw new NoSuchElementException(); + } return value; } @@ -247,18 +251,22 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return true; } + @Nullable public E peek() { return listOps.index(0); } + @Nullable public E poll() { return listOps.leftPop(); } public E remove() { + E value = poll(); - if (value == null) + if (value == null) { throw new NoSuchElementException(); + } return value; } @@ -304,23 +312,28 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return true; } + @Nullable public E peekFirst() { return peek(); } + @Nullable public E peekLast() { return listOps.index(-1); } + @Nullable public E pollFirst() { return poll(); } + @Nullable public E pollLast() { return listOps.rightPop(); } public E pop() { + E e = poll(); if (e == null) { throw new NoSuchElementException(); @@ -356,7 +369,6 @@ public class DefaultRedisList extends AbstractRedisCollection implements R // // BlockingQueue // - public int drainTo(Collection c, int maxElements) { if (this.equals(c)) { throw new IllegalArgumentException("Cannot drain a queue to itself"); @@ -380,6 +392,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return offer(e); } + @Nullable public E poll(long timeout, TimeUnit unit) throws InterruptedException { E element = listOps.leftPop(timeout, unit); return (element == null ? null : element); @@ -393,6 +406,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return Integer.MAX_VALUE; } + @Nullable public E take() throws InterruptedException { return poll(0, TimeUnit.SECONDS); } @@ -409,10 +423,12 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return offerLast(e); } + @Nullable public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { return poll(timeout, unit); } + @Nullable public E pollLast(long timeout, TimeUnit unit) throws InterruptedException { E element = listOps.rightPop(timeout, unit); return (element == null ? null : element); @@ -426,10 +442,12 @@ public class DefaultRedisList extends AbstractRedisCollection implements R put(e); } + @Nullable public E takeFirst() throws InterruptedException { return take(); } + @Nullable public E takeLast() throws InterruptedException { return pollLast(0, TimeUnit.SECONDS); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java index cdeaef4f2..e89a7ba96 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java @@ -30,12 +30,14 @@ import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.SessionCallback; +import org.springframework.lang.Nullable; /** * Default implementation for {@link RedisMap}. Note that the current implementation doesn't provide the same locking * semantics across all methods. In highly concurrent environments, race conditions might appear. * * @author Costin Leau + * @author Christoph Strobl */ public class DefaultRedisMap implements RedisMap { @@ -44,9 +46,10 @@ public class DefaultRedisMap implements RedisMap { private class DefaultRedisMapEntry implements Map.Entry { private K key; - private V value; + private @Nullable V value; + + public DefaultRedisMapEntry(K key, @Nullable V value) { - public DefaultRedisMapEntry(K key, V value) { this.key = key; this.value = value; } @@ -55,11 +58,12 @@ public class DefaultRedisMap implements RedisMap { return key; } + @Nullable public V getValue() { return value; } - public V setValue(V value) { + public V setValue(@Nullable V value) { throw new UnsupportedOperationException(); } } @@ -125,6 +129,7 @@ public class DefaultRedisMap implements RedisMap { return entries; } + @Nullable public V get(Object key) { return hashOps.get(key); } @@ -147,6 +152,7 @@ public class DefaultRedisMap implements RedisMap { hashOps.putAll(m); } + @Nullable public V remove(Object key) { V v = get(key); hashOps.delete(key); @@ -186,6 +192,7 @@ public class DefaultRedisMap implements RedisMap { return sb.toString(); } + @Nullable public V putIfAbsent(K key, V value) { return (hashOps.putIfAbsent(key, value) ? null : get(key)); } @@ -214,7 +221,7 @@ public class DefaultRedisMap implements RedisMap { }); } - public boolean replace(final K key, final V oldValue, final V newValue) { + public boolean replace(final K key, V oldValue, V newValue) { if (oldValue == null || newValue == null) { throw new NullPointerException(); } @@ -238,6 +245,7 @@ public class DefaultRedisMap implements RedisMap { }); } + @Nullable public V replace(final K key, final V value) { if (value == null) { throw new NullPointerException(); @@ -290,7 +298,7 @@ public class DefaultRedisMap implements RedisMap { return hashOps.getType(); } - private void checkResult(Object obj) { + private void checkResult(@Nullable Object obj) { if (obj == null) { throw new IllegalStateException("Cannot read collection with Redis connection in pipeline/multi-exec mode"); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java index 97e164467..59335c227 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java @@ -225,8 +225,9 @@ public class DefaultRedisZSet extends AbstractRedisCollection implements R checkResult(members); Iterator iterator = members.iterator(); - if (iterator.hasNext()) + if (iterator.hasNext()) { return iterator.next(); + } throw new NoSuchElementException(); } @@ -234,8 +235,9 @@ public class DefaultRedisZSet extends AbstractRedisCollection implements R Set members = boundZSetOps.reverseRange(0, 0); checkResult(members); Iterator iterator = members.iterator(); - if (iterator.hasNext()) + if (iterator.hasNext()) { return iterator.next(); + } throw new NoSuchElementException(); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisCollectionFactoryBean.java b/src/main/java/org/springframework/data/redis/support/collections/RedisCollectionFactoryBean.java index 110751d48..22a5afae5 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisCollectionFactoryBean.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisCollectionFactoryBean.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -72,11 +73,11 @@ public class RedisCollectionFactoryBean implements InitializingBean, BeanNameAwa abstract DataType dataType(); } - private RedisStore store; - private CollectionType type = null; - private RedisTemplate template; - private String key; - private String beanName; + private @Nullable RedisStore store; + private @Nullable CollectionType type = null; + private @Nullable RedisTemplate template; + private @Nullable String key; + private @Nullable String beanName; public void afterPropertiesSet() { if (!StringUtils.hasText(key)) { diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisIterator.java b/src/main/java/org/springframework/data/redis/support/collections/RedisIterator.java index 569803991..049e6bba9 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisIterator.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisIterator.java @@ -17,6 +17,8 @@ package org.springframework.data.redis.support.collections; import java.util.Iterator; +import org.springframework.lang.Nullable; + /** * Iterator extension for Redis collection removal. * @@ -26,7 +28,7 @@ abstract class RedisIterator implements Iterator { private final Iterator delegate; - private E item; + private @Nullable E item; /** * Constructs a new RedisIterator instance. diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisStore.java b/src/main/java/org/springframework/data/redis/support/collections/RedisStore.java index 797b5e412..7620f0c77 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisStore.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisStore.java @@ -29,7 +29,7 @@ public interface RedisStore extends BoundKeyOperations { /** * Returns the underlying Redis operations used by the backing implementation. * - * @return operations + * @return operations never {@literal null}. */ RedisOperations getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/package-info.java b/src/main/java/org/springframework/data/redis/support/collections/package-info.java index a87ab4c74..946aef46f 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/package-info.java +++ b/src/main/java/org/springframework/data/redis/support/collections/package-info.java @@ -1,12 +1,15 @@ /** * Package providing implementations for most of the {@code java.util} collections on top of Redis. *

- * For indexed collections, such as {@link java.util.List}, {@link java.util.Queue} or {@link java.util.Deque} - * consider {@link org.springframework.data.redis.support.collections.RedisList}.

- * For collections without duplicates the obvious candidate is {@link org.springframework.data.redis.support.collections.RedisSet}. Use - * {@link org.springframework.data.redis.support.collections.RedisZSet} if a - * certain order is required.

- * Lastly, for key/value associations {@link org.springframework.data.redis.support.collections.RedisMap} providing a Map-like abstraction on top of a Redis hash. + * For indexed collections, such as {@link java.util.List}, {@link java.util.Queue} or {@link java.util.Deque} consider + * {@link org.springframework.data.redis.support.collections.RedisList}. + *

+ * For collections without duplicates the obvious candidate is + * {@link org.springframework.data.redis.support.collections.RedisSet}. Use + * {@link org.springframework.data.redis.support.collections.RedisZSet} if a certain order is required. + *

+ * Lastly, for key/value associations {@link org.springframework.data.redis.support.collections.RedisMap} providing a + * Map-like abstraction on top of a Redis hash. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.support.collections; - diff --git a/src/main/java/org/springframework/data/redis/support/package-info.java b/src/main/java/org/springframework/data/redis/support/package-info.java index 6635f4edc..22350f2a6 100644 --- a/src/main/java/org/springframework/data/redis/support/package-info.java +++ b/src/main/java/org/springframework/data/redis/support/package-info.java @@ -1,5 +1,5 @@ /** * Classes supporting the Redis packages, such as collection or atomic counters. */ +@org.springframework.lang.NonNullApi package org.springframework.data.redis.support; - diff --git a/src/main/java/org/springframework/data/redis/util/ByteUtils.java b/src/main/java/org/springframework/data/redis/util/ByteUtils.java index 36d966c1f..3a718bed7 100644 --- a/src/main/java/org/springframework/data/redis/util/ByteUtils.java +++ b/src/main/java/org/springframework/data/redis/util/ByteUtils.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Some handy methods for dealing with byte arrays. @@ -59,7 +60,7 @@ public final class ByteUtils { public static byte[][] split(byte[] source, int c) { - if (source == null || source.length == 0) { + if (ObjectUtils.isEmpty(source)) { return new byte[][] {}; } diff --git a/src/main/java/org/springframework/data/redis/util/package-info.java b/src/main/java/org/springframework/data/redis/util/package-info.java new file mode 100644 index 000000000..3c8b91f8d --- /dev/null +++ b/src/main/java/org/springframework/data/redis/util/package-info.java @@ -0,0 +1,5 @@ +/** + * Commonly used stuff for data manipulation throughout different driver specific implementations. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.redis.util; diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java index 7a211ee15..fc1e269e0 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -643,7 +643,6 @@ public abstract class AbstractConnectionIntegrationTests { MessageListener listener = (message, pattern) -> { messages.add(message); - System.out.println("Received message '" + new String(message.getBody()) + "'"); }; Thread th = new Thread(() -> { @@ -1354,8 +1353,7 @@ public abstract class AbstractConnectionIntegrationTests { actual.add(connection.sAdd("myset", "foo")); actual.add(connection.sAdd("myset", "bar")); actual.add(connection.sMembers("myset")); - verifyResults( - Arrays.asList(new Object[] { 1l, 1l, new HashSet<>(Arrays.asList(new String[] { "foo", "bar" })) })); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, new HashSet<>(Arrays.asList(new String[] { "foo", "bar" })) })); } @Test @@ -1363,8 +1361,8 @@ public abstract class AbstractConnectionIntegrationTests { actual.add(connection.sAdd("myset", "foo", "bar")); actual.add(connection.sAdd("myset", "baz")); actual.add(connection.sMembers("myset")); - verifyResults(Arrays - .asList(new Object[] { 2l, 1l, new HashSet<>(Arrays.asList(new String[] { "foo", "bar", "baz" })) })); + verifyResults( + Arrays.asList(new Object[] { 2l, 1l, new HashSet<>(Arrays.asList(new String[] { "foo", "bar", "baz" })) })); } @Test @@ -1391,8 +1389,7 @@ public abstract class AbstractConnectionIntegrationTests { actual.add(connection.sAdd("otherset", "bar")); actual.add(connection.sDiffStore("thirdset", "myset", "otherset")); actual.add(connection.sMembers("thirdset")); - verifyResults( - Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, new HashSet<>(Collections.singletonList("foo")) })); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, new HashSet<>(Collections.singletonList("foo")) })); } @Test @@ -1411,8 +1408,7 @@ public abstract class AbstractConnectionIntegrationTests { actual.add(connection.sAdd("otherset", "bar")); actual.add(connection.sInterStore("thirdset", "myset", "otherset")); actual.add(connection.sMembers("thirdset")); - verifyResults( - Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, new HashSet<>(Collections.singletonList("bar")) })); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, new HashSet<>(Collections.singletonList("bar")) })); } @Test @@ -1438,8 +1434,7 @@ public abstract class AbstractConnectionIntegrationTests { actual.add(connection.sAdd("myset", "foo")); actual.add(connection.sAdd("myset", "bar")); actual.add(connection.sPop("myset")); - assertTrue( - new HashSet<>(Arrays.asList(new String[] { "foo", "bar" })).contains((String) getResults().get(2))); + assertTrue(new HashSet<>(Arrays.asList(new String[] { "foo", "bar" })).contains((String) getResults().get(2))); } @Test // DATAREDIS-688 @@ -2212,19 +2207,12 @@ public abstract class AbstractConnectionIntegrationTests { assertThat(values, not(hasItems("a", "b", "c", "d"))); } - @Test // DATAREDIS-316 + @Test(expected = IllegalArgumentException.class) // DATAREDIS-316, DATAREDIS-692 @WithRedisDriver({ RedisDriver.JEDIS, RedisDriver.LETTUCE }) - public void setWithExpirationAndNullOpionShouldSetTtlWhenKeyDoesNotExist() { + public void setWithExpirationAndNullOpionShouldThrowException() { String key = "exp-" + UUID.randomUUID(); connection.set(key, "foo", Expiration.milliseconds(500), null); - - actual.add(connection.exists(key)); - actual.add(connection.pTtl(key)); - - List result = getResults(); - assertThat(result.get(0), is(Boolean.TRUE)); - assertThat(((Long) result.get(1)).doubleValue(), is(closeTo(500d, 499d))); } @Test // DATAREDIS-316 @@ -2329,19 +2317,12 @@ public abstract class AbstractConnectionIntegrationTests { assertThat(((Long) result.get(1)).doubleValue(), is(closeTo(-2, 0))); } - @Test // DATAREDIS-316 + @Test(expected = IllegalArgumentException.class) // DATAREDIS-316, DATAREDIS-692 @WithRedisDriver({ RedisDriver.JEDIS, RedisDriver.LETTUCE }) - public void setWithNullExpirationAndUpsertOpionShouldSetTtlWhenKeyDoesNotExist() { + public void setWithNullExpirationAndUpsertOpionShouldThrowException() { String key = "exp-" + UUID.randomUUID(); connection.set(key, "foo", null, SetOption.upsert()); - - actual.add(connection.exists(key)); - actual.add(connection.pTtl(key)); - - List result = getResults(); - assertThat(result.get(0), is(Boolean.TRUE)); - assertThat(((Long) result.get(1)).doubleValue(), is(closeTo(-1, 0))); } @Test // DATAREDIS-316 diff --git a/src/test/java/org/springframework/data/redis/connection/ClusterCommandExecutorUnitTests.java b/src/test/java/org/springframework/data/redis/connection/ClusterCommandExecutorUnitTests.java index 29289086b..2ac25c1ca 100644 --- a/src/test/java/org/springframework/data/redis/connection/ClusterCommandExecutorUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/ClusterCommandExecutorUnitTests.java @@ -78,7 +78,7 @@ public class ClusterCommandExecutorUnitTests { static final RedisClusterNode CLUSTER_NODE_2_LOOKUP = RedisClusterNode.newRedisClusterNode() .withId("0f2ee5df45d18c50aca07228cc18b1da96fd5e84").build(); - static final RedisClusterNode UNKNOWN_CLUSTER_NODE = new RedisClusterNode("8.8.8.8", 7379, null); + static final RedisClusterNode UNKNOWN_CLUSTER_NODE = new RedisClusterNode("8.8.8.8", 7379, SlotRange.empty()); private ClusterCommandExecutor executor; diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java index df58c2be3..b5fc03e0d 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java @@ -22,6 +22,7 @@ import static org.springframework.data.redis.connection.RedisGeoCommands.Distanc import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*; import static org.springframework.data.redis.core.ScanOptions.*; +import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPool; @@ -199,7 +200,7 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - Set keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, null), + Set keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty()), JedisConverters.toBytes("*")); assertThat(keysOnNode, hasItems(KEY_2_BYTES)); @@ -345,9 +346,9 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7379, null)), is(1L)); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7380, null)), is(1L)); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7381, null)), is(0L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())), is(1L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7380, SlotRange.empty())), is(1L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7381, SlotRange.empty())), is(0L)); } @Test // DATAREDIS-315 @@ -1653,7 +1654,7 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests { @Test // DATAREDIS-315 public void pingShouldRetrunPongForExistingNode() { - assertThat(clusterConnection.ping(new RedisClusterNode("127.0.0.1", 7379, null)), is("PONG")); + assertThat(clusterConnection.ping(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())), is("PONG")); } @Test // DATAREDIS-315 @@ -1684,7 +1685,7 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - clusterConnection.flushDb(new RedisClusterNode("127.0.0.1", 7379, null)); + clusterConnection.flushDb(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())); assertThat(nativeConnection.get(KEY_1), notNullValue()); assertThat(nativeConnection.get(KEY_2), nullValue()); diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionUnitTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionUnitTests.java index ec1c4ff3e..e66f2e7a5 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionUnitTests.java @@ -45,6 +45,7 @@ import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; +import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.redis.ClusterStateFailureException; import org.springframework.data.redis.connection.ClusterInfo; import org.springframework.data.redis.connection.RedisClusterCommands.AddSlots; @@ -59,22 +60,16 @@ import org.springframework.data.redis.connection.jedis.JedisClusterConnection.Je public class JedisClusterConnectionUnitTests { private static final String CLUSTER_NODES_RESPONSE = "" // - + MASTER_NODE_1_ID + " " + CLUSTER_HOST + ":" + MASTER_NODE_1_PORT - + " myself,master - 0 0 1 connected 0-5460" - + "\n" + MASTER_NODE_2_ID + " " + CLUSTER_HOST + ":" - + MASTER_NODE_2_PORT - + " master - 0 1427718161587 2 connected 5461-10922" + "\n" - + MASTER_NODE_2_ID - + " " + CLUSTER_HOST + ":" + MASTER_NODE_3_PORT + " master - 0 1427718161587 3 connected 10923-16383"; + + MASTER_NODE_1_ID + " " + CLUSTER_HOST + ":" + MASTER_NODE_1_PORT + " myself,master - 0 0 1 connected 0-5460" + + "\n" + MASTER_NODE_2_ID + " " + CLUSTER_HOST + ":" + MASTER_NODE_2_PORT + + " master - 0 1427718161587 2 connected 5461-10922" + "\n" + MASTER_NODE_2_ID + " " + CLUSTER_HOST + ":" + + MASTER_NODE_3_PORT + " master - 0 1427718161587 3 connected 10923-16383"; - static final String CLUSTER_INFO_RESPONSE = "cluster_state:ok" + "\n" - + "cluster_slots_assigned:16384" + "\n" + "cluster_slots_ok:16384" - + "\n" + "cluster_slots_pfail:0" + "\n" - + "cluster_slots_fail:0" + "\n" + "cluster_known_nodes:4" - + "\n" + "cluster_size:3" + "\n" - + "cluster_current_epoch:30" + "\n" + "cluster_my_epoch:2" - + "\n" + "cluster_stats_messages_sent:2560260" - + "\n" + "cluster_stats_messages_received:2560086"; + static final String CLUSTER_INFO_RESPONSE = "cluster_state:ok" + "\n" + "cluster_slots_assigned:16384" + "\n" + + "cluster_slots_ok:16384" + "\n" + "cluster_slots_pfail:0" + "\n" + "cluster_slots_fail:0" + "\n" + + "cluster_known_nodes:4" + "\n" + "cluster_size:3" + "\n" + "cluster_current_epoch:30" + "\n" + + "cluster_my_epoch:2" + "\n" + "cluster_stats_messages_sent:2560260" + "\n" + + "cluster_stats_messages_received:2560086"; JedisClusterConnection connection; @@ -277,7 +272,7 @@ public class JedisClusterConnectionUnitTests { nodes.remove(CLUSTER_HOST + ":" + MASTER_NODE_3_PORT); - expectedException.expect(IllegalStateException.class); + expectedException.expect(DataAccessResourceFailureException.class); expectedException.expectMessage("Node " + CLUSTER_HOST + ":" + MASTER_NODE_3_PORT + " is unknown to cluster"); connection.serverCommands().dbSize(new RedisClusterNode(CLUSTER_HOST, MASTER_NODE_3_PORT)); diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnectionTests.java index 7b375a1d8..6b4f09bc6 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnectionTests.java @@ -56,6 +56,7 @@ import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.DefaultSortParameters; import org.springframework.data.redis.connection.DefaultTuple; import org.springframework.data.redis.connection.RedisClusterNode; +import org.springframework.data.redis.connection.RedisClusterNode.SlotRange; import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation; import org.springframework.data.redis.connection.RedisListCommands.Position; import org.springframework.data.redis.connection.RedisNode; @@ -198,7 +199,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - Set keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, null), + Set keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty()), JedisConverters.toBytes("*")); assertThat(keysOnNode, hasItems(KEY_2_BYTES)); @@ -344,9 +345,9 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7379, null)), is(1L)); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7380, null)), is(1L)); - assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7381, null)), is(0L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())), is(1L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7380, SlotRange.empty())), is(1L)); + assertThat(clusterConnection.dbSize(new RedisClusterNode("127.0.0.1", 7381, SlotRange.empty())), is(0L)); } @Test // DATAREDIS-315 @@ -1658,7 +1659,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { @Test // DATAREDIS-315 public void pingShouldRetrunPongForExistingNode() { - assertThat(clusterConnection.ping(new RedisClusterNode("127.0.0.1", 7379, null)), is("PONG")); + assertThat(clusterConnection.ping(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())), is("PONG")); } @Test // DATAREDIS-315 @@ -1668,7 +1669,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { @Test(expected = IllegalArgumentException.class) // DATAREDIS-315 public void pingShouldThrowExceptionWhenNodeNotKnownToCluster() { - clusterConnection.ping(new RedisClusterNode("127.0.0.1", 1234, null)); + clusterConnection.ping(new RedisClusterNode("127.0.0.1", 1234, SlotRange.empty())); } @Test // DATAREDIS-315 @@ -1689,7 +1690,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { nativeConnection.set(KEY_1, VALUE_1); nativeConnection.set(KEY_2, VALUE_2); - clusterConnection.flushDb(new RedisClusterNode("127.0.0.1", 7379, null)); + clusterConnection.flushDb(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty())); assertThat(nativeConnection.get(KEY_1), notNullValue()); assertThat(nativeConnection.get(KEY_2), nullValue()); @@ -1733,7 +1734,8 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests { public void infoShouldCollectionInfoFromAllClusterNodes() { Properties singleNodeInfo = clusterConnection.serverCommands().info(new RedisClusterNode("127.0.0.1", 7380)); - assertThat(Double.valueOf(clusterConnection.serverCommands().info().size()), closeTo(singleNodeInfo.size() * 3, 12d)); + assertThat(Double.valueOf(clusterConnection.serverCommands().info().size()), + closeTo(singleNodeInfo.size() * 3, 12d)); } @Test // DATAREDIS-315 diff --git a/src/test/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListenerUnitTests.java b/src/test/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListenerUnitTests.java index 3e69023d8..28b8fe25f 100644 --- a/src/test/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListenerUnitTests.java +++ b/src/test/java/org/springframework/data/redis/listener/KeyExpirationEventMessageListenerUnitTests.java @@ -73,10 +73,10 @@ public class KeyExpirationEventMessageListenerUnitTests { verifyZeroInteractions(publisherMock); } - @Test // DATAREDIS-425 + @Test // DATAREDIS-425, DATAREDIS-692 public void handleMessageShouldNotRespondToEmptyMessage() { - listener.onMessage(new DefaultMessage(null, null), "*".getBytes()); + listener.onMessage(new DefaultMessage(new byte[] {}, new byte[] {}), "*".getBytes()); verifyZeroInteractions(publisherMock); }