From d3bb2c2024bc88278fee656cd9f2374ed3d7b441 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 28 Apr 2014 08:14:07 +0200 Subject: [PATCH 1/2] DATAREDIS-226 - Syntax exceptions using lettuce should be reported immediately. Prepare issue branch. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f09fb8eb53..6d66de3d88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ jredisVersion=06052013 jedisVersion=2.4.1 springVersion=3.2.8.RELEASE log4jVersion=1.2.17 -version=1.3.0.BUILD-SNAPSHOT +version=1.3.0.DATAREDIS-226-SNAPSHOT srpVersion=0.7 jacksonVersion=1.8.8 fasterXmlJacksonVersion=2.2.0 From b8f7dd88d970bef8e9e1f47549ae4f0e56111057 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 28 Apr 2014 09:07:21 +0200 Subject: [PATCH 2/2] DATAREDIS-226 - Syntax exceptions using lettuce should be reported immediately. If running in transaction mode we now do a rudimentary check if the provided number of arguments matches the ones defined for the RedisCommand to execute. If the command passes this first check and causes an error on redis server one has to check results for Command.getOutput().hasError(). Original Pull Request: #66. --- .../connection/lettuce/LettuceConnection.java | 28 +++++++++++++++++-- .../data/redis/core/RedisCommand.java | 2 +- ...ConnectionTransactionIntegrationTests.java | 5 ---- 3 files changed, 27 insertions(+), 8 deletions(-) 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 046b5cff28..9fb72fe7a5 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 @@ -49,6 +49,7 @@ import org.springframework.data.redis.connection.Subscription; import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.connection.convert.TransactionResultConverter; +import org.springframework.data.redis.core.RedisCommand; import org.springframework.data.redis.core.types.RedisClientInfo; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -294,18 +295,22 @@ public Object execute(String command, CommandOutput commandOutputTypeHint, byte[ try { String name = command.trim().toUpperCase(); CommandType cmd = CommandType.valueOf(name); - CommandArgs cmdArg = new CommandArgs(CODEC); + validateCommandIfRunningInTransactionMode(cmd, args); + + CommandArgs cmdArg = new CommandArgs(CODEC); if (!ObjectUtils.isEmpty(args)) { cmdArg.addKeys(args); } CommandOutput expectedOutput = commandOutputTypeHint != null ? commandOutputTypeHint : typeHints.getTypeHint(cmd); if (isPipelined()) { + pipeline(new LettuceResult(getAsyncConnection().dispatch(cmd, expectedOutput, cmdArg))); return null; } else if (isQueueing()) { - transaction(new LettuceResult(getAsyncConnection().dispatch(cmd, expectedOutput, cmdArg))); + + transaction(new LettuceTxResult(getAsyncConnection().dispatch(cmd, expectedOutput, cmdArg))); return null; } else { return await(getAsyncConnection().dispatch(cmd, expectedOutput, cmdArg)); @@ -3168,6 +3173,25 @@ private ZStoreArgs zStoreArgs(Aggregate aggregate, int[] weights) { return args; } + private void validateCommandIfRunningInTransactionMode(CommandType cmd, byte[]... args) { + + if (this.isQueueing()) { + validateCommand(cmd, args); + } + } + + private void validateCommand(CommandType cmd, byte[]... args) { + + RedisCommand redisCommand = RedisCommand.failsafeCommandLookup(cmd.name()); + if (!RedisCommand.UNKNOWN.equals(redisCommand) && redisCommand.requiresArguments()) { + try { + redisCommand.validateArgumentCount(args != null ? args.length : 0); + } catch (IllegalArgumentException e) { + throw new InvalidDataAccessApiUsageException(String.format("Validation failed for %s command.", cmd), e); + } + } + } + /** * {@link TypeHints} provide {@link CommandOutput} information for a given {@link CommandType}. * diff --git a/src/main/java/org/springframework/data/redis/core/RedisCommand.java b/src/main/java/org/springframework/data/redis/core/RedisCommand.java index be629b33ea..4115bc8c54 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisCommand.java +++ b/src/main/java/org/springframework/data/redis/core/RedisCommand.java @@ -32,7 +32,7 @@ * @see Redis command list: * https://github.com/antirez/redis/blob/93e7a130fc9594e41ccfc996b5eca7626ae5356a/src/redis.c#L119 */ -enum RedisCommand { +public enum RedisCommand { // -- A APPEND("rw", 2, 2), // AUTH("rw", 1, 1), // diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java index 56b460f69c..e269d60065 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java @@ -19,7 +19,6 @@ import java.util.Arrays; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.redis.connection.AbstractConnectionTransactionIntegrationTests; @@ -40,10 +39,6 @@ @ContextConfiguration("LettuceConnectionIntegrationTests-context.xml") public class LettuceConnectionTransactionIntegrationTests extends AbstractConnectionTransactionIntegrationTests { - @Test - @Ignore("DATAREDIS-226 Exceptions on native execute are swallowed in tx") - public void exceptionExecuteNative() throws Exception {} - @Test(expected = UnsupportedOperationException.class) @IfProfileValue(name = "redisVersion", value = "2.6") public void testSRandMemberCountNegative() {