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 bad421b27..7bf7806b3 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 @@ -17,10 +17,12 @@ package org.springframework.data.redis.core.script; import java.io.IOException; +import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import org.springframework.scripting.ScriptSource; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.scripting.support.StaticScriptSource; +import org.springframework.util.Assert; /** * Default implementation of {@link RedisScript}. Delegates to an underlying {@link ScriptSource} to @@ -34,7 +36,7 @@ import org.springframework.scripting.support.StaticScriptSource; * The script result type. Should be one of Long, Boolean, List, or deserialized value * type. Can be null if the script returns a throw-away status (i.e "OK") */ -public class DefaultRedisScript implements RedisScript { +public class DefaultRedisScript implements RedisScript, InitializingBean { private ScriptSource scriptSource; @@ -44,38 +46,9 @@ public class DefaultRedisScript implements RedisScript { private final Object shaModifiedMonitor = new Object(); - /** - * - * @param scriptLocation - * The location of the script - * @param resultType - * The Script result type - */ - public DefaultRedisScript(Resource scriptLocation, Class resultType) { - this(new ResourceScriptSource(scriptLocation), resultType); - } - - /** - * - * @param script - * The script - * @param resultType - * The Script result type - */ - public DefaultRedisScript(String script, Class resultType) { - this(new StaticScriptSource(script), resultType); - } - - /** - * - * @param scriptSource - * The {@link ScriptSource} of the script - * @param resultType - * The Script result type - */ - public DefaultRedisScript(ScriptSource scriptSource, Class resultType) { - this.scriptSource = scriptSource; - this.resultType = resultType; + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.scriptSource, "Either script, script location," + + " or script source is required"); } public String getSha1() { @@ -98,4 +71,41 @@ public class DefaultRedisScript implements RedisScript { throw new ScriptingException("Error reading script text", e); } } + + /** + * + * @param resultType + * The script result type. Should be one of Long, Boolean, List, or deserialized + * value type. Can be null if the script returns a throw-away status (i.e "OK") + */ + public void setResultType(Class resultType) { + this.resultType = resultType; + } + + /** + * + * @param script + * The script text + */ + public void setScriptText(String scriptText) { + this.scriptSource = new StaticScriptSource(scriptText); + } + + /** + * + * @param scriptLocation + * The location of the script + */ + public void setLocation(Resource scriptLocation) { + this.scriptSource = new ResourceScriptSource(scriptLocation); + } + + /** + * + * @param scriptSource + * A @{link {@link ScriptSource} pointing to the script + */ + public void setScriptSource(ScriptSource scriptSource) { + this.scriptSource = scriptSource; + } } diff --git a/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java b/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java index 4e9c24c4e..504ec1ca6 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java @@ -57,11 +57,9 @@ import org.springframework.data.redis.connection.srp.SrpConnectionFactory; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.core.query.SortQueryBuilder; import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.data.redis.core.script.RedisScript; import org.springframework.data.redis.serializer.GenericToStringSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; -import org.springframework.scripting.support.StaticScriptSource; /** * @@ -616,8 +614,9 @@ public class RedisTemplateTests { public void testExecuteScriptCustomSerializers() { assumeTrue(RedisTestProfileValueSource.matches("redisVersion", "2.6")); K key1 = keyFactory.instance(); - final RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return 'Hey'"), String.class); + final DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return 'Hey'"); + script.setResultType(String.class); assertEquals("Hey", redisTemplate.execute(script, redisTemplate.getValueSerializer(), new StringRedisSerializer(), Collections.singletonList(key1))); } diff --git a/src/test/java/org/springframework/data/redis/core/script/DefaultRedisScriptTests.java b/src/test/java/org/springframework/data/redis/core/script/DefaultRedisScriptTests.java index 7e5c9cc9c..79cb43128 100644 --- a/src/test/java/org/springframework/data/redis/core/script/DefaultRedisScriptTests.java +++ b/src/test/java/org/springframework/data/redis/core/script/DefaultRedisScriptTests.java @@ -34,7 +34,9 @@ public class DefaultRedisScriptTests { @Test public void testGetSha1() { StaticScriptSource script = new StaticScriptSource("return KEYS[1]"); - RedisScript redisScript = new DefaultRedisScript(script, String.class); + DefaultRedisScript redisScript = new DefaultRedisScript(); + redisScript.setScriptSource(script); + redisScript.setResultType(String.class); String sha1 = redisScript.getSha1(); // Ensure multiple calls return same sha assertEquals(sha1, redisScript.getSha1()); @@ -45,15 +47,23 @@ public class DefaultRedisScriptTests { @Test public void testGetScriptAsString() { - RedisScript redisScript = new DefaultRedisScript("return ARGS[1]", - String.class); + DefaultRedisScript redisScript = new DefaultRedisScript(); + redisScript.setScriptText("return ARGS[1]"); + redisScript.setResultType(String.class); assertEquals("return ARGS[1]", redisScript.getScriptAsString()); } @Test(expected = ScriptingException.class) public void testGetScriptAsStringError() { - RedisScript redisScript = new DefaultRedisScript(new ResourceScriptSource( - new ClassPathResource("nonexistent")), Long.class); + DefaultRedisScript redisScript = new DefaultRedisScript(); + redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("nonexistent"))); + redisScript.setResultType(Long.class); redisScript.getScriptAsString(); } + + @Test(expected = IllegalArgumentException.class) + public void initializeWithNoScript() throws Exception { + DefaultRedisScript redisScript = new DefaultRedisScript(); + redisScript.afterPropertiesSet(); + } } diff --git a/src/test/java/org/springframework/data/redis/core/script/DefaultScriptExecutorTests.java b/src/test/java/org/springframework/data/redis/core/script/DefaultScriptExecutorTests.java index 0f04baea1..a857d0db7 100644 --- a/src/test/java/org/springframework/data/redis/core/script/DefaultScriptExecutorTests.java +++ b/src/test/java/org/springframework/data/redis/core/script/DefaultScriptExecutorTests.java @@ -84,8 +84,10 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript script = new DefaultRedisScript(new ClassPathResource( - "org/springframework/data/redis/core/script/increment.lua"), Long.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setLocation(new ClassPathResource( + "org/springframework/data/redis/core/script/increment.lua")); + script.setResultType(Long.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); Long result = scriptExecutor.execute(script, Collections.singletonList("mykey")); assertNull(result); @@ -102,8 +104,10 @@ public class DefaultScriptExecutorTests { template.setValueSerializer(new GenericToStringSerializer(Long.class)); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript script = new DefaultRedisScript(new ClassPathResource( - "org/springframework/data/redis/core/script/cas.lua"), Boolean.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setLocation(new ClassPathResource( + "org/springframework/data/redis/core/script/cas.lua")); + script.setResultType(Boolean.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); template.boundValueOps("counter").set(0l); Boolean valueSet = scriptExecutor.execute(script, Collections.singletonList("counter"), 0, @@ -119,8 +123,10 @@ public class DefaultScriptExecutorTests { template.setConnectionFactory(connFactory); template.afterPropertiesSet(); template.boundListOps("mylist").leftPushAll("a", "b", "c", "d"); - RedisScript> script = new DefaultRedisScript(new ClassPathResource( - "org/springframework/data/redis/core/script/bulkpop.lua"), List.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setLocation(new ClassPathResource( + "org/springframework/data/redis/core/script/bulkpop.lua")); + script.setResultType(List.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); List result = scriptExecutor .execute(script, new GenericToStringSerializer(Long.class), @@ -134,8 +140,9 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript> script = new DefaultRedisScript(new ClassPathResource( - "org/springframework/data/redis/core/script/popandlength.lua"), List.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setLocation(new ClassPathResource("org/springframework/data/redis/core/script/popandlength.lua")); + script.setResultType(List.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); List results = scriptExecutor.execute(script, Collections.singletonList("mylist")); assertEquals(Arrays.asList(new Object[] { null, 0l }), results); @@ -150,8 +157,9 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return redis.call('GET',KEYS[1])"), String.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return redis.call('GET',KEYS[1])"); + script.setResultType(String.class); template.opsForValue().set("foo", "bar"); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); assertEquals("bar", scriptExecutor.execute(script, Collections.singletonList("foo"))); @@ -165,8 +173,8 @@ public class DefaultScriptExecutorTests { template.setValueSerializer(new GenericToStringSerializer(Long.class)); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return redis.call('SET',KEYS[1], ARGV[1])"), null); + DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return redis.call('SET',KEYS[1], ARGV[1])"); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); assertNull(scriptExecutor.execute(script, Collections.singletonList("foo"), 3l)); assertEquals(Long.valueOf(3), template.opsForValue().get("foo")); @@ -182,8 +190,10 @@ public class DefaultScriptExecutorTests { template.setValueSerializer(personSerializer); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "redis.call('SET',KEYS[1], ARGV[1])\nreturn 'FOO'"), String.class); + DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptSource(new StaticScriptSource( + "redis.call('SET',KEYS[1], ARGV[1])\nreturn 'FOO'")); + script.setResultType(String.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); Person joe = new Person("Joe", "Schmoe", 23); String result = scriptExecutor.execute(script, personSerializer, @@ -198,8 +208,9 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - final RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return KEYS[1]"), String.class); + final DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return KEYS[1]"); + script.setResultType(String.class); List results = template.executePipelined(new SessionCallback() { @SuppressWarnings("rawtypes") public String execute(RedisOperations operations) throws DataAccessException { @@ -217,8 +228,9 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - final RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return 'bar'..KEYS[1]"), String.class); + final DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return 'bar'..KEYS[1]"); + script.setResultType(String.class); List results = (List) template.execute(new SessionCallback>() { @SuppressWarnings("rawtypes") public List execute(RedisOperations operations) throws DataAccessException { @@ -238,8 +250,9 @@ public class DefaultScriptExecutorTests { this.template = new StringRedisTemplate(); template.setConnectionFactory(connFactory); template.afterPropertiesSet(); - final RedisScript script = new DefaultRedisScript(new StaticScriptSource( - "return 'HELLO'"), String.class); + final DefaultRedisScript script = new DefaultRedisScript(); + script.setScriptText("return 'HELLO'"); + script.setResultType(String.class); ScriptExecutor scriptExecutor = new DefaultScriptExecutor(template); // Execute script twice, second time should be from cache assertEquals("HELLO", scriptExecutor.execute(script, null));