DATAREDIS-692 - Introduce usage of nullable annotations for API validation.

Mark all packages with Spring Frameworks @NonNullApi. Add Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fix Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances.

Resolve some of the inherited null invariants, align Converters to null contract.

Original pull request: #277.
This commit is contained in:
Christoph Strobl
2017-09-13 10:36:38 +02:00
committed by Mark Paluch
parent ddb5ca7c28
commit 1b2e74c82f
189 changed files with 2285 additions and 1396 deletions

View File

@@ -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<Object> 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<Object> result = getResults();
assertThat(result.get(0), is(Boolean.TRUE));
assertThat(((Long) result.get(1)).doubleValue(), is(closeTo(-1, 0)));
}
@Test // DATAREDIS-316

View File

@@ -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;

View File

@@ -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<byte[]> keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, null),
Set<byte[]> 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());

View File

@@ -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));

View File

@@ -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<byte[]> keysOnNode = clusterConnection.keys(new RedisClusterNode("127.0.0.1", 7379, null),
Set<byte[]> 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

View File

@@ -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);
}