/** * Specifies a SpEL Expression to be used to determine the key for the Redis store. * If an expression is not needed, then a literal value may be passed to the * {@link #setKey(String)} method instead of this one (they are mutually exclusive). * If neither setter is called, the default expression will be 'headers.{@link RedisHeaders#KEY}'. * @param keyExpression The key expression. * @see #setKey(String) * @since 5.0 */ public void setKeyExpressionString(String keyExpression) { Assert.hasText(keyExpression, "'keyExpression' must not be empty"); setKeyExpression(EXPRESSION_PARSER.parseExpression(keyExpression)); }
@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(); }
Assert.hasText(key, () -> "Failed to determine a key for the Redis store based on the message: " + message); RedisStore store = this.createStoreView(key); try { if (this.collectionType == CollectionType.ZSET) { writeToZset((RedisZSet<Object>) store, message); writeToSet((RedisSet<Object>) store, message); writeToList((RedisList<Object>) store, message); writeToMap((RedisMap<Object, Object>) store, message); writeToProperties((RedisProperties) store, message);
private void writeToProperties(final RedisProperties properties, Message<?> message) { final Object payload = message.getPayload(); if (this.extractPayloadElements && payload instanceof Properties) { processInPipeline(() -> properties.putAll((Properties) payload)); } else { Assert.isInstanceOf(String.class, payload, "For property, payload must be a String."); Object key = this.determineMapKey(message, true); properties.put(key, payload); } }
final BoundZSetOperations<String, Object> ops = (BoundZSetOperations<String, Object>) this.redisTemplate.boundZSetOps(zset.getKey()); boolean zsetIncrementHeader = extractZsetIncrementHeader(message); if (this.extractPayloadElements) { if ((payload instanceof Map<?, ?> && this.verifyAllMapValuesOfTypeNumber((Map<?, ?>) payload))) { Map<Object, Number> payloadAsMap = (Map<Object, Number>) payload; processInPipeline(() -> { for (Entry<Object, Number> entry : payloadAsMap.entrySet()) { Number d = entry.getValue(); incrementOrOverwrite(ops, entry.getKey(), d == null ? determineScore(message) : NumberUtils.convertNumberToTargetClass(d, Double.class), zsetIncrementHeader); processInPipeline(() -> { for (Object object : ((Collection<?>) payload)) { incrementOrOverwrite(ops, object, determineScore(message), zsetIncrementHeader); incrementOrOverwrite(ops, payload, this.determineScore(message), zsetIncrementHeader); incrementOrOverwrite(ops, payload, this.determineScore(message), zsetIncrementHeader);
@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"); }
@Bean @ServiceActivator(inputChannel = Sink.INPUT) public MessageHandler redisSinkMessageHandler() { if (this.redisSinkProperties.isKey()) { RedisStoreWritingMessageHandler redisStoreWritingMessageHandler = new RedisStoreWritingMessageHandler( this.redisConnectionFactory); redisStoreWritingMessageHandler.setKeyExpression(this.redisSinkProperties.keyExpression()); return redisStoreWritingMessageHandler; } else if (this.redisSinkProperties.isQueue()) { return new RedisQueueOutboundChannelAdapter(this.redisSinkProperties.queueExpression(), this.redisConnectionFactory); } else { // must be topic RedisPublishingMessageHandler redisPublishingMessageHandler = new RedisPublishingMessageHandler( this.redisConnectionFactory); redisPublishingMessageHandler.setTopicExpression(this.redisSinkProperties.topicExpression()); return redisPublishingMessageHandler; } }
/** * Sets the expression used as the key for Map and Properties entries. * Default is 'headers.{@link RedisHeaders#MAP_KEY}' * @param mapKeyExpression The map key expression. * @since 5.0 */ public void setMapKeyExpressionString(String mapKeyExpression) { Assert.hasText(mapKeyExpression, "'mapKeyExpression' must not be empty"); setMapKeyExpression(EXPRESSION_PARSER.parseExpression(mapKeyExpression)); }
private void incrementOrOverwrite(BoundZSetOperations<String, Object> ops, Object object, Double score, boolean zsetIncrementScore) { if (score != null) { doIncrementOrOverwrite(ops, object, score, zsetIncrementScore); } else { this.logger.debug("Zset Score could not be determined. Using default score of 1"); doIncrementOrOverwrite(ops, object, 1d, zsetIncrementScore); } }
@Override protected void onInit() { this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory()); Assert.state(!this.mapKeyExpressionExplicitlySet || (this.collectionType == CollectionType.MAP || this.collectionType == CollectionType.PROPERTIES), "'mapKeyExpression' can only be set for CollectionType.MAP or CollectionType.PROPERTIES"); if (!this.redisTemplateExplicitlySet) { if (!this.extractPayloadElements) { RedisTemplate<String, Object> template = new RedisTemplate<>(); StringRedisSerializer serializer = new StringRedisSerializer(); template.setKeySerializer(serializer); template.setHashKeySerializer(serializer); this.redisTemplate = template; } this.redisTemplate.setConnectionFactory(this.connectionFactory); this.redisTemplate.afterPropertiesSet(); } this.initialized = true; }
new RedisStoreWritingMessageHandler(jcf); handler.setKey(key); handler.setCollectionType(CollectionType.ZSET); handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); handler.handleMessage(message);
final BoundZSetOperations<String, Object> ops = (BoundZSetOperations<String, Object>) this.redisTemplate.boundZSetOps(zset.getKey()); boolean zsetIncrementHeader = extractZsetIncrementHeader(message); if (this.extractPayloadElements) { if ((payload instanceof Map<?, ?> && this.verifyAllMapValuesOfTypeNumber((Map<?, ?>) payload))) { Map<Object, Number> payloadAsMap = (Map<Object, Number>) payload; processInPipeline(() -> { for (Entry<Object, Number> entry : payloadAsMap.entrySet()) { Number d = entry.getValue(); incrementOrOverwrite(ops, entry.getKey(), d == null ? determineScore(message) : NumberUtils.convertNumberToTargetClass(d, Double.class), zsetIncrementHeader); processInPipeline(() -> { for (Object object : ((Collection<?>) payload)) { incrementOrOverwrite(ops, object, determineScore(message), zsetIncrementHeader); incrementOrOverwrite(ops, payload, this.determineScore(message), zsetIncrementHeader); incrementOrOverwrite(ops, payload, this.determineScore(message), zsetIncrementHeader);
private void writeToMap(final RedisMap<Object, Object> map, Message<?> message) { final Object payload = message.getPayload(); if (this.extractPayloadElements && payload instanceof Map<?, ?>) { processInPipeline(() -> map.putAll((Map<?, ?>) payload)); } else { Object key = this.determineMapKey(message, false); map.put(key, payload); } }
/** * Sets the expression used as the key for Map and Properties entries. * Default is 'headers.{@link RedisHeaders#MAP_KEY}' * @param mapKeyExpression The map key expression. * @since 5.0 */ public void setMapKeyExpressionString(String mapKeyExpression) { Assert.hasText(mapKeyExpression, "'mapKeyExpression' must not be empty"); setMapKeyExpression(EXPRESSION_PARSER.parseExpression(mapKeyExpression)); }
private void incrementOrOverwrite(BoundZSetOperations<String, Object> ops, Object object, Double score, boolean zsetIncrementScore) { if (score != null) { doIncrementOrOverwrite(ops, object, score, zsetIncrementScore); } else { this.logger.debug("Zset Score could not be determined. Using default score of 1"); doIncrementOrOverwrite(ops, object, 1d, zsetIncrementScore); } }
@Override protected void onInit() { this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory()); Assert.state(!this.mapKeyExpressionExplicitlySet || (this.collectionType == CollectionType.MAP || this.collectionType == CollectionType.PROPERTIES), "'mapKeyExpression' can only be set for CollectionType.MAP or CollectionType.PROPERTIES"); if (!this.redisTemplateExplicitlySet) { if (!this.extractPayloadElements) { RedisTemplate<String, Object> template = new RedisTemplate<>(); StringRedisSerializer serializer = new StringRedisSerializer(); template.setKeySerializer(serializer); template.setHashKeySerializer(serializer); this.redisTemplate = template; } this.redisTemplate.setConnectionFactory(this.connectionFactory); this.redisTemplate.afterPropertiesSet(); } this.initialized = true; }
@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 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(); }
Assert.hasText(key, () -> "Failed to determine a key for the Redis store based on the message: " + message); RedisStore store = this.createStoreView(key); try { if (this.collectionType == CollectionType.ZSET) { writeToZset((RedisZSet<Object>) store, message); writeToSet((RedisSet<Object>) store, message); writeToList((RedisList<Object>) store, message); writeToMap((RedisMap<Object, Object>) store, message); writeToProperties((RedisProperties) store, message);
private void writeToMap(final RedisMap<Object, Object> map, Message<?> message) { final Object payload = message.getPayload(); if (this.extractPayloadElements && payload instanceof Map<?, ?>) { processInPipeline(() -> map.putAll((Map<?, ?>) payload)); } else { Object key = this.determineMapKey(message, false); map.put(key, payload); } }