/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.redis.outbound; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.support.collections.DefaultRedisList; import org.springframework.data.redis.support.collections.DefaultRedisZSet; import org.springframework.data.redis.support.collections.RedisCollectionFactoryBean.CollectionType; import org.springframework.data.redis.support.collections.RedisList; import org.springframework.data.redis.support.collections.RedisZSet; import org.springframework.expression.common.LiteralExpression; import org.springframework.integration.redis.rules.RedisAvailable; import org.springframework.integration.redis.rules.RedisAvailableTests; import org.springframework.integration.redis.support.RedisHeaders; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.support.GenericMessage; /** * @author Oleg Zhurakousky * @author Gunnar Hillert * @author Mark Fisher * @author Gary Russell * @author Artem Bilan */ public class RedisStoreWritingMessageHandlerTests extends RedisAvailableTests { @Test @RedisAvailable public void testListWithListPayloadParsedAndProvidedKey() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisList<String> redisList = new DefaultRedisList<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisList.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = new GenericMessage<List<String>>(list); handler.handleMessage(message); assertEquals(3, redisList.size()); assertEquals("Manny", redisList.get(0)); assertEquals("Moe", redisList.get(1)); assertEquals("Jack", redisList.get(2)); this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testListWithListPayloadParsedAndProvidedKeyAsHeader() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisList<String> redisList = new DefaultRedisList<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisList.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list).setHeader("redis_key", key).build(); handler.handleMessage(message); assertEquals(3, redisList.size()); assertEquals("Manny", redisList.get(0)); assertEquals("Moe", redisList.get(1)); assertEquals("Jack", redisList.get(2)); this.deleteKey(jcf, "foo"); } @RedisAvailable @Test(expected = MessageHandlingException.class) public void testListWithListPayloadParsedAndNoKey() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisList<String> redisList = new DefaultRedisList<String>(key, this.initTemplate(jcf, new RedisTemplate<String, String>())); assertEquals(0, redisList.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list).build(); handler.handleMessage(message); this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testListWithListPayloadAsSingleEntry() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisList<List<String>> redisList = new DefaultRedisList<List<String>>(key, this.initTemplate(jcf, new RedisTemplate<String, List<String>>())); assertEquals(0, redisList.size()); RedisTemplate<String, List<String>> template = this.initTemplate(jcf, new RedisTemplate<String, List<String>>()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(template); handler.setKey(key); handler.setExtractPayloadElements(false); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = new GenericMessage<List<String>>(list); handler.handleMessage(message); assertEquals(1, redisList.size()); List<String> resultList = redisList.get(0); assertEquals("Manny", resultList.get(0)); assertEquals("Moe", resultList.get(1)); assertEquals("Jack", resultList.get(2)); this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testZsetWithListPayloadParsedAndProvidedKeyDefault() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisZSet<String> redisZset = new DefaultRedisZSet<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisZset.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list) .setHeader(RedisHeaders.ZSET_INCREMENT_SCORE, true) .build(); handler.handleMessage(message); assertEquals(3, redisZset.size()); Set<TypedTuple<String>> pepboys = redisZset.rangeByScoreWithScores(1, 1); for (TypedTuple<String> pepboy : pepboys) { assertTrue(pepboy.getScore() == 1); } handler.handleMessage(message); assertEquals(3, redisZset.size()); pepboys = redisZset.rangeByScoreWithScores(1, 2); // should have incremented by 1 for (TypedTuple<String> pepboy : pepboys) { assertEquals(Double.valueOf(2), pepboy.getScore()); } this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testZsetWithListPayloadParsedAndProvidedKeyScoreIncrement() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisZSet<String> redisZset = new DefaultRedisZSet<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisZset.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list) .setHeader(RedisHeaders.ZSET_INCREMENT_SCORE, Boolean.TRUE) .build(); handler.handleMessage(message); assertEquals(3, redisZset.size()); Set<TypedTuple<String>> pepboys = redisZset.rangeByScoreWithScores(1, 1); for (TypedTuple<String> pepboy : pepboys) { assertTrue(pepboy.getScore() == 1); } handler.handleMessage(message); assertEquals(3, redisZset.size()); pepboys = redisZset.rangeByScoreWithScores(1, 2); // should have incremented for (TypedTuple<String> pepboy : pepboys) { assertTrue(pepboy.getScore() == 2); } this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testZsetWithListPayloadParsedAndProvidedKeyScoreIncrementAsStringHeader() { // see INT-2775 RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisZSet<String> redisZset = new DefaultRedisZSet<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisZset.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list) .setHeader(RedisHeaders.ZSET_INCREMENT_SCORE, "true") .build(); handler.handleMessage(message); assertEquals(3, redisZset.size()); Set<TypedTuple<String>> pepboys = redisZset.rangeByScoreWithScores(1, 1); for (TypedTuple<String> pepboy : pepboys) { assertTrue(pepboy.getScore() == 1); } handler.handleMessage(message); assertEquals(3, redisZset.size()); pepboys = redisZset.rangeByScoreWithScores(1, 2); // should have incremented for (TypedTuple<String> pepboy : pepboys) { assertTrue(pepboy.getScore() == 2); } this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testZsetWithListPayloadAsSingleEntryAndHeaderKeyHeaderScore() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisZSet<List<String>> redisZset = new DefaultRedisZSet<List<String>>(key, this.initTemplate(jcf, new RedisTemplate<String, List<String>>())); assertEquals(0, redisZset.size()); RedisTemplate<String, List<String>> template = this.initTemplate(jcf, new RedisTemplate<String, List<String>>()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(template); handler.setCollectionType(CollectionType.ZSET); handler.setExtractPayloadElements(false); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); List<String> list = new ArrayList<String>(); list.add("Manny"); list.add("Moe"); list.add("Jack"); Message<List<String>> message = MessageBuilder.withPayload(list).setHeader("redis_key", key). setHeader("redis_zsetScore", 4).build(); handler.handleMessage(message); assertEquals(1, redisZset.size()); Set<TypedTuple<List<String>>> entries = redisZset.rangeByScoreWithScores(1, 4); for (TypedTuple<List<String>> pepboys : entries) { assertTrue(pepboys.getScore() == 4); } this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testZsetWithMapPayloadParsedHeaderKey() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deletePresidents(jcf); String key = "presidents"; RedisZSet<String> redisZset = new DefaultRedisZSet<String>(key, this.initTemplate(jcf, new StringRedisTemplate())); assertEquals(0, redisZset.size()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); Map<String, Double> presidents = new HashMap<String, Double>(); presidents.put("John Adams", 18D); presidents.put("Barack Obama", 21D); presidents.put("Thomas Jefferson", 19D); presidents.put("John Quincy Adams", 19D); presidents.put("Zachary Taylor", 19D); presidents.put("Theodore Roosevelt", 20D); presidents.put("Woodrow Wilson", 20D); presidents.put("George W. Bush", 21D); presidents.put("Franklin D. Roosevelt", 20D); presidents.put("Ronald Reagan", 20D); presidents.put("William J. Clinton", 20D); presidents.put("Abraham Lincoln", 19D); presidents.put("George Washington", 18D); Message<Map<String, Double>> message = MessageBuilder.withPayload(presidents).setHeader("redis_key", key).build(); handler.handleMessage(message); assertEquals(13, redisZset.size()); Set<TypedTuple<String>> entries = redisZset.rangeByScoreWithScores(18, 19); assertEquals(6, entries.size()); this.deletePresidents(jcf); } @Test @RedisAvailable public void testZsetWithMapPayloadPojoParsedHeaderKey() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deletePresidents(jcf); String key = "presidents"; RedisZSet<President> redisZset = new DefaultRedisZSet<President>(key, this.initTemplate(jcf, new RedisTemplate<String, President>())); assertEquals(0, redisZset.size()); RedisTemplate<String, President> template = this.initTemplate(jcf, new RedisTemplate<String, President>()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(template); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); Map<President, Double> presidents = new HashMap<President, Double>(); presidents.put(new President("John Adams"), 18D); presidents.put(new President("Barack Obama"), 21D); presidents.put(new President("Thomas Jefferson"), 19D); presidents.put(new President("John Quincy Adams"), 19D); presidents.put(new President("Zachary Taylor"), 19D); presidents.put(new President("Theodore Roosevelt"), 20D); presidents.put(new President("Woodrow Wilson"), 20D); presidents.put(new President("George W. Bush"), 21D); presidents.put(new President("Franklin D. Roosevelt"), 20D); presidents.put(new President("Ronald Reagan"), 20D); presidents.put(new President("William J. Clinton"), 20D); presidents.put(new President("Abraham Lincoln"), 19D); presidents.put(new President("George Washington"), 18D); Message<Map<President, Double>> message = MessageBuilder.withPayload(presidents).setHeader("redis_key", key).build(); handler.handleMessage(message); assertEquals(13, redisZset.size()); Set<TypedTuple<President>> entries = redisZset.rangeByScoreWithScores(18, 19); assertEquals(6, entries.size()); this.deletePresidents(jcf); } @Test @RedisAvailable public void testZsetWithMapPayloadPojoAsSingleEntryHeaderKey() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deletePresidents(jcf); String key = "presidents"; RedisZSet<Map<President, Double>> redisZset = new DefaultRedisZSet<Map<President, Double>>(key, this.initTemplate(jcf, new RedisTemplate<String, Map<President, Double>>())); assertEquals(0, redisZset.size()); RedisTemplate<String, Map<President, Double>> template = this.initTemplate(jcf, new RedisTemplate<String, Map<President, Double>>()); RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(template); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setExtractPayloadElements(false); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); Map<President, Double> presidents = new HashMap<President, Double>(); presidents.put(new President("John Adams"), 18D); presidents.put(new President("Barack Obama"), 21D); presidents.put(new President("Thomas Jefferson"), 19D); Message<Map<President, Double>> message = MessageBuilder.withPayload(presidents).setHeader("redis_key", key).build(); handler.handleMessage(message); assertEquals(1, redisZset.size()); this.deletePresidents(jcf); } @Test(expected = IllegalStateException.class) @RedisAvailable public void testListWithMapKeyExpression() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); String key = "foo"; RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setMapKeyExpression(new LiteralExpression(key)); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); } @Test(expected = IllegalStateException.class) @RedisAvailable public void testSetWithMapKeyExpression() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); String key = "foo"; RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.SET); handler.setMapKeyExpression(new LiteralExpression(key)); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); } @Test(expected = IllegalStateException.class) @RedisAvailable public void testZsetWithMapKeyExpression() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); String key = "foo"; RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setMapKeyExpression(new LiteralExpression(key)); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); } @Test @RedisAvailable public void testMapWithMapKeyExpression() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.MAP); handler.setMapKeyExpression(new LiteralExpression(key)); handler.setBeanFactory(mock(BeanFactory.class)); try { handler.afterPropertiesSet(); } catch (Exception e) { fail("No exception expected:" + e.getMessage()); } this.deleteKey(jcf, "foo"); } @Test @RedisAvailable public void testPropertiesWithMapKeyExpression() { RedisConnectionFactory jcf = this.getConnectionFactoryForTest(); this.deleteKey(jcf, "foo"); String key = "foo"; RedisStoreWritingMessageHandler handler = new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.PROPERTIES); handler.setMapKeyExpression(new LiteralExpression(key)); handler.setBeanFactory(mock(BeanFactory.class)); try { handler.afterPropertiesSet(); } catch (Exception e) { fail("No exception expected:" + e.getMessage()); } this.deleteKey(jcf, "foo"); } private <K, V> RedisTemplate<K, V> initTemplate(RedisConnectionFactory rcf, RedisTemplate<K, V> redisTemplate) { redisTemplate.setConnectionFactory(rcf); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } private static class President implements Serializable { private static final long serialVersionUID = 1L; private String name; President(String name) { this.name = name; } @SuppressWarnings("unused") public String getName() { return name; } @SuppressWarnings("unused") public void setName(String name) { this.name = name; } } }