Use Lettuce Redis client; Redis module fixes (#2435)

* Use Lettuce Redis client; Redis module fixes

The Lettuce client is based on the Netty and more stable, than Jedis
therefore we get a performance improvement for tests
(it saves us at about 30 seconds).
Also this client doesn't fail for me on Windows sporadically (very often)
 with the `ConnectionClosedException`

* After switching to the Netty-based client, we expose the interrupted
Thread issue in the `LockRegistryLeaderInitiator`.
If we interrupted (expected behavior), we try to unlock calling
`RedisLockRegistry`, but Netty client reject our request because the
thread is interrupted, therefore we never delete the lock when we yield
our leadership.
Fix the issue with shifting a `RedisTemplate.delete()` operation to the
`ExecutorService` when the current thread is interrupted
* Allow to configure such an `ExecutorService` and timeout to wait for
the `submit()` result
* Refactor `RedisAvailableRule` and all the Redis tests do not expose
the target `RedisConnectionFactory` implementation.
* Make all the test-cases based on the `connectionFactory` created by
the `RedisAvailableTests.setupConnectionFactory()`
* Tweak some unnecessary timeouts and sleeps for better tests task
throughput

* Add a `Log4j2LevelAdjuster` into the `RedisLockRegistryLeaderInitiatorTests`
This commit is contained in:
Artem Bilan
2018-05-04 14:13:51 -04:00
committed by Gary Russell
parent 664d67f9bb
commit b8d4e6b0de
36 changed files with 390 additions and 317 deletions

View File

@@ -108,7 +108,6 @@ subprojects { subproject ->
jackson2Version = '2.9.5'
javaxActivationVersion = '1.1.1'
javaxMailVersion = '1.6.1'
jedisVersion = '2.9.0'
jmsApiVersion = '2.0.1'
jpa21ApiVersion = '1.0.0.Final'
jpaApiVersion = '2.1.1'
@@ -120,6 +119,7 @@ subprojects { subproject ->
junitPlatformVersion = '1.1.1'
jythonVersion = '2.5.3'
kryoShadedVersion = '3.0.3'
lettuceVersion = '5.0.3.RELEASE'
log4jVersion = '2.11.0'
micrometerVersion = '1.0.3'
mockitoVersion = '2.18.0'
@@ -364,7 +364,7 @@ project('spring-integration-file') {
testCompile project(":spring-integration-gemfire")
testCompile project(":spring-integration-jdbc")
testCompile "com.h2database:h2:$h2Version"
testCompile "redis.clients:jedis:$jedisVersion"
testCompile "io.lettuce:lettuce-core:$lettuceVersion"
testCompile "io.projectreactor:reactor-test:$reactorVersion"
}
}
@@ -542,7 +542,7 @@ project('spring-integration-redis') {
compile project(":spring-integration-core")
compile ("org.springframework.data:spring-data-redis:$springDataRedisVersion")
testCompile "redis.clients:jedis:$jedisVersion"
testCompile "io.lettuce:lettuce-core:$lettuceVersion"
}
}
@@ -642,7 +642,7 @@ project('spring-integration-twitter') {
compile("javax.activation:activation:$javaxActivationVersion", optional)
testCompile project(":spring-integration-redis")
testCompile project(":spring-integration-redis").sourceSets.test.output
testCompile "redis.clients:jedis:$jedisVersion"
testCompile "io.lettuce:lettuce-core:$lettuceVersion"
}
}

View File

@@ -386,8 +386,8 @@ public class LockRegistryLeaderInitiator implements SmartLifecycle, DisposableBe
this.lock.unlock();
}
catch (Exception e1) {
logger.debug("Could not unlock - treat as broken. " +
"Revoking " + (isRunning() ? " and retrying..." : "..."), e);
logger.debug("Could not unlock - treat as broken: " + this.context +
". Revoking " + (isRunning() ? " and retrying..." : "..."), e);
}
// The lock was broken and we are no longer leader

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 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.
@@ -23,6 +23,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -31,6 +33,7 @@ import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -38,7 +41,9 @@ import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.integration.support.locks.ExpirableLockRegistry;
import org.springframework.integration.support.locks.LockRegistry;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of {@link LockRegistry} providing a distributed lock using Redis.
@@ -68,11 +73,13 @@ import org.springframework.util.Assert;
* @since 4.0
*
*/
public final class RedisLockRegistry implements ExpirableLockRegistry {
public final class RedisLockRegistry implements ExpirableLockRegistry, DisposableBean {
private static final Log logger = LogFactory.getLog(RedisLockRegistry.class);
private static final long DEFAULT_EXPIRE_AFTER = 60000;
private static final long DEFAULT_EXPIRE_AFTER = 60000L;
public static final long DEFAULT_DELETE_TIMEOUT = 10000L;
private static final String OBTAIN_LOCK_SCRIPT =
"local lockClientId = redis.call('GET', KEYS[1])\n" +
@@ -85,6 +92,27 @@ public final class RedisLockRegistry implements ExpirableLockRegistry {
"end\n" +
"return false";
/**
* An {@link ExecutorService} to call {@link StringRedisTemplate#delete(Object)} in
* the separate thread when the current one is interrupted.
*/
private ExecutorService executorService =
Executors.newCachedThreadPool(new CustomizableThreadFactory("redis-lock-registry-"));
/**
* Flag to denote whether the {@link ExecutorService} was provided via the setter and
* thus should not be shutdown when {@link #destroy()} is called
*/
private boolean executorServiceExplicitlySet;
/**
* Time in milliseconds to wait for the {@link StringRedisTemplate#delete(Object)} in
* the background thread.
*/
private long deleteTimeoutMillis = DEFAULT_DELETE_TIMEOUT;
private final Map<String, RedisLock> locks = new ConcurrentHashMap<>();
private final String clientId = UUID.randomUUID().toString();
@@ -141,6 +169,13 @@ public final class RedisLockRegistry implements ExpirableLockRegistry {
}
}
@Override
public void destroy() {
if (!this.executorServiceExplicitlySet) {
this.executorService.shutdown();
}
}
private final class RedisLock implements Lock {
private final String lockKey;
@@ -172,11 +207,11 @@ public final class RedisLockRegistry implements ExpirableLockRegistry {
break;
}
catch (InterruptedException e) {
/*
* This method must be uninterruptible so catch and ignore
* interrupts and only break out of the while loop when
* we get the lock.
*/
/*
* This method must be uninterruptible so catch and ignore
* interrupts and only break out of the while loop when
* we get the lock.
*/
}
catch (Exception e) {
this.localLock.unlock();
@@ -263,11 +298,23 @@ public final class RedisLockRegistry implements ExpirableLockRegistry {
return;
}
try {
RedisLockRegistry.this.redisTemplate.delete(this.lockKey);
if (Thread.currentThread().isInterrupted()) {
RedisLockRegistry.this.executorService.submit(() ->
RedisLockRegistry.this.redisTemplate.delete(this.lockKey))
.get(RedisLockRegistry.this.deleteTimeoutMillis, TimeUnit.MILLISECONDS);
}
else {
RedisLockRegistry.this.redisTemplate.delete(this.lockKey);
}
if (logger.isDebugEnabled()) {
logger.debug("Released lock; " + this);
}
}
catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e);
}
finally {
this.localLock.unlock();
}

View File

@@ -2,16 +2,17 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int-redis:publish-subscribe-channel id="redisChannel" topic-name="si.test.topic.parser"
serializer="redisSerializer"/>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="redisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<int-redis:publish-subscribe-channel id="redisChannelWithSubLimit" topic-name="si.test.topic"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 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.
@@ -23,19 +23,25 @@ import static org.junit.Assert.assertTrue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.integration.redis.channel.SubscribableRedisChannel;
import org.springframework.integration.redis.rules.RedisAvailable;
import org.springframework.integration.redis.rules.RedisAvailableTests;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Oleg Zhurakousky
@@ -43,50 +49,65 @@ import org.springframework.messaging.support.GenericMessage;
* @author Gunnar Hillert
* @author Artem Bilan
*/
@RunWith(SpringRunner.class)
@DirtiesContext
public class RedisChannelParserTests extends RedisAvailableTests {
@Autowired
private SubscribableRedisChannel redisChannel;
@Autowired
private SubscribableRedisChannel redisChannelWithSubLimit;
@Autowired
private ApplicationContext context;
@Before
public void setup() {
this.redisChannel.start();
this.redisChannelWithSubLimit.start();
}
@After
public void tearDown() {
this.redisChannel.stop();
this.redisChannelWithSubLimit.stop();
}
@Test
@RedisAvailable
public void testPubSubChannelConfig() {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("RedisChannelParserTests-context.xml", this.getClass());
SubscribableChannel redisChannel = context.getBean("redisChannel", SubscribableChannel.class);
RedisConnectionFactory connectionFactory =
TestUtils.getPropertyValue(redisChannel, "connectionFactory", RedisConnectionFactory.class);
TestUtils.getPropertyValue(this.redisChannel, "connectionFactory", RedisConnectionFactory.class);
RedisSerializer<?> redisSerializer = TestUtils.getPropertyValue(redisChannel, "serializer", RedisSerializer.class);
assertEquals(connectionFactory, context.getBean("redisConnectionFactory"));
assertEquals(redisSerializer, context.getBean("redisSerializer"));
assertEquals(connectionFactory, this.context.getBean("redisConnectionFactory"));
assertEquals(redisSerializer, this.context.getBean("redisSerializer"));
assertEquals("si.test.topic.parser", TestUtils.getPropertyValue(redisChannel, "topicName"));
assertEquals(Integer.MAX_VALUE, TestUtils.getPropertyValue(
TestUtils.getPropertyValue(redisChannel, "dispatcher"), "maxSubscribers", Integer.class).intValue());
redisChannel = context.getBean("redisChannelWithSubLimit", SubscribableChannel.class);
assertEquals(1, TestUtils.getPropertyValue(redisChannel, "dispatcher.maxSubscribers", Integer.class).intValue());
Object mbf = context.getBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME);
assertSame(mbf, TestUtils.getPropertyValue(redisChannel, "messageBuilderFactory"));
context.close();
TestUtils.getPropertyValue(this.redisChannel, "dispatcher"), "maxSubscribers", Integer.class).intValue());
assertEquals(1,
TestUtils.getPropertyValue(this.redisChannelWithSubLimit, "dispatcher.maxSubscribers", Integer.class).intValue());
Object mbf = this.context.getBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME);
assertSame(mbf, TestUtils.getPropertyValue(this.redisChannelWithSubLimit, "messageBuilderFactory"));
}
@Test
@RedisAvailable
public void testPubSubChannelUsage() throws Exception {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("RedisChannelParserTests-context.xml", this.getClass());
SubscribableChannel redisChannel = context.getBean("redisChannel", SubscribableChannel.class);
this.awaitContainerSubscribed(TestUtils.getPropertyValue(redisChannel, "container",
this.awaitContainerSubscribed(TestUtils.getPropertyValue(this.redisChannel, "container",
RedisMessageListenerContainer.class));
final Message<?> m = new GenericMessage<String>("Hello Redis");
final Message<?> m = new GenericMessage<>("Hello Redis");
final CountDownLatch latch = new CountDownLatch(1);
redisChannel.subscribe(message -> {
this.redisChannel.subscribe(message -> {
assertEquals(m.getPayload(), message.getPayload());
latch.countDown();
});
redisChannel.send(m);
assertTrue(latch.await(5, TimeUnit.SECONDS));
context.close();
this.redisChannel.send(m);
assertTrue(latch.await(10, TimeUnit.SECONDS));
}
}

View File

@@ -1,39 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int-redis:inbound-channel-adapter
id="adapter" topics="foo" topic-patterns="f*, b*" channel="receiveChannel" error-channel="testErrorChannel"
message-converter="testConverter"
serializer="serializer"
task-executor="executor" />
id="adapter" topics="foo" topic-patterns="f*, b*" channel="receiveChannel" error-channel="testErrorChannel"
message-converter="testConverter"
serializer="serializer"
task-executor="executor"/>
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="25" />
<property name="corePoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="queueCapacity" value="25"/>
</bean>
<int:channel id="receiveChannel">
<int:queue />
<int:queue/>
</int:channel>
<int:channel id="testErrorChannel" />
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<int:channel id="testErrorChannel"/>
<bean id="testConverter"
class="org.springframework.integration.redis.config.RedisInboundChannelAdapterParserTests$TestMessageConverter" />
class="org.springframework.integration.redis.config.RedisInboundChannelAdapterParserTests$TestMessageConverter"/>
<int-redis:inbound-channel-adapter
id="autoChannel" topics="foo1, bar1" error-channel="testErrorChannel"
message-converter="testConverter" auto-startup="false"/>
id="autoChannel" topics="foo1, bar1" error-channel="testErrorChannel"
message-converter="testConverter" auto-startup="false"/>
<bean id="serializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

View File

@@ -111,6 +111,7 @@ public class RedisInboundChannelAdapterParserTests extends RedisAvailableTests {
assertThat(receive.getPayload(), Matchers.<Object>isOneOf("Hello Redis from foo", "Hello Redis from bar"));
}
adapter.stop();
}
@Test

View File

@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:channel id="sendChannel"/>
@@ -25,19 +30,15 @@
<int:queue/>
</int:channel>
<int-redis:inbound-channel-adapter channel="barChannel" topics="bar"/>
<int-redis:inbound-channel-adapter id="barInbound" channel="barChannel" topics="bar"/>
<int:channel id="barChannel">
<int:queue/>
</int:channel>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="testConverter" class="org.springframework.integration.redis.config.RedisOutboundChannelAdapterParserTests$TestMessageConverter"/>
<int:chain input-channel="redisOutboudChain">
<int:chain input-channel="redisOutboundChain">
<int-redis:outbound-channel-adapter topic="foo"/>
</int:chain>

View File

@@ -22,6 +22,8 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,6 +67,21 @@ public class RedisOutboundChannelAdapterParserTests extends RedisAvailableTests
@Autowired
private RedisInboundChannelAdapter fooInbound;
@Autowired
private RedisInboundChannelAdapter barInbound;
@Before
public void setup() {
this.fooInbound.start();
this.barInbound.start();
}
@After
public void tearDown() {
this.fooInbound.stop();
this.barInbound.stop();
}
@Test
@RedisAvailable
public void validateConfiguration() {
@@ -94,16 +111,16 @@ public class RedisOutboundChannelAdapterParserTests extends RedisAvailableTests
MessageChannel sendChannel = context.getBean("sendChannel", MessageChannel.class);
this.awaitContainerSubscribed(TestUtils.getPropertyValue(fooInbound, "container",
RedisMessageListenerContainer.class));
sendChannel.send(new GenericMessage<String>("Hello Redis"));
sendChannel.send(new GenericMessage<>("Hello Redis"));
QueueChannel receiveChannel = context.getBean("receiveChannel", QueueChannel.class);
Message<?> message = receiveChannel.receive(5000);
Message<?> message = receiveChannel.receive(10000);
assertNotNull(message);
assertEquals("Hello Redis", message.getPayload());
sendChannel = context.getBean("sendChannel", MessageChannel.class);
sendChannel.send(MessageBuilder.withPayload("Hello Redis").setHeader("topic", "bar").build());
receiveChannel = context.getBean("barChannel", QueueChannel.class);
message = receiveChannel.receive(5000);
message = receiveChannel.receive(10000);
assertNotNull(message);
assertEquals("Hello Redis", message.getPayload());
}
@@ -111,12 +128,12 @@ public class RedisOutboundChannelAdapterParserTests extends RedisAvailableTests
@Test //INT-2275
@RedisAvailable
public void testOutboundChannelAdapterWithinChain() throws Exception {
MessageChannel sendChannel = context.getBean("redisOutboudChain", MessageChannel.class);
MessageChannel sendChannel = context.getBean("redisOutboundChain", MessageChannel.class);
this.awaitContainerSubscribed(TestUtils.getPropertyValue(fooInbound, "container",
RedisMessageListenerContainer.class));
sendChannel.send(new GenericMessage<String>("Hello Redis from chain"));
sendChannel.send(new GenericMessage<>("Hello Redis from chain"));
QueueChannel receiveChannel = context.getBean("receiveChannel", QueueChannel.class);
Message<?> message = receiveChannel.receive(5000);
Message<?> message = receiveChannel.receive(10000);
assertNotNull(message);
assertEquals("Hello Redis from chain", message.getPayload());
}

View File

@@ -3,15 +3,14 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:channel id="sendChannel"/>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 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.
@@ -20,6 +20,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -68,15 +70,22 @@ public class RedisQueueGatewayIntegrationTests extends RedisAvailableTests {
@Autowired
private RedisQueueOutboundGateway outboundGateway;
@Before
public void setup() {
RedisConnectionFactory jcf = getConnectionFactoryForTest();
jcf.getConnection().del(this.queueName);
this.inboundGateway.start();
}
@After
public void tearDown() {
this.inboundGateway.stop();
}
@Test
@RedisAvailable
public void testRequestWithReply() throws Exception {
this.sendChannel.send(new GenericMessage<Integer>(1));
public void testRequestWithReply() {
this.sendChannel.send(new GenericMessage<>(1));
Message<?> receive = this.outputChannel.receive(10000);
assertNotNull(receive);
assertEquals(2, receive.getPayload());
@@ -84,45 +93,47 @@ public class RedisQueueGatewayIntegrationTests extends RedisAvailableTests {
@Test
@RedisAvailable
public void testInboundGatewayStop() throws Exception {
Long receiveTimeout = TestUtils.getPropertyValue(this.inboundGateway, "receiveTimeout", Long.class);
this.inboundGateway.setReceiveTimeout(1);
public void testInboundGatewayStop() {
Integer receiveTimeout = TestUtils.getPropertyValue(this.outboundGateway, "receiveTimeout", Integer.class);
this.outboundGateway.setReceiveTimeout(1);
this.inboundGateway.stop();
try {
this.sendChannel.send(new GenericMessage<String>("test1"));
this.sendChannel.send(new GenericMessage<>("test1"));
}
catch (Exception e) {
assertTrue(e.getMessage().contains("No reply produced"));
}
finally {
this.inboundGateway.setReceiveTimeout(receiveTimeout);
this.inboundGateway.start();
this.outboundGateway.setReceiveTimeout(receiveTimeout);
}
}
@Test
@RedisAvailable
public void testNullSerializer() throws Exception {
public void testNullSerializer() {
Integer receiveTimeout = TestUtils.getPropertyValue(this.outboundGateway, "receiveTimeout", Integer.class);
this.outboundGateway.setReceiveTimeout(1);
this.inboundGateway.setSerializer(null);
try {
this.sendChannel.send(new GenericMessage<String>("test1"));
this.sendChannel.send(new GenericMessage<>("test1"));
}
catch (Exception e) {
assertTrue(e.getMessage().contains("No reply produced"));
}
finally {
this.inboundGateway.setSerializer(new StringRedisSerializer());
this.outboundGateway.setReceiveTimeout(receiveTimeout);
}
}
@Test
@RedisAvailable
public void testRequestReplyWithMessage() throws Exception {
public void testRequestReplyWithMessage() {
this.inboundGateway.setSerializer(new JdkSerializationRedisSerializer());
this.inboundGateway.setExtractPayload(false);
this.outboundGateway.setSerializer(new JdkSerializationRedisSerializer());
this.outboundGateway.setExtractPayload(false);
this.sendChannel.send(new GenericMessage<Integer>(2));
this.sendChannel.send(new GenericMessage<>(2));
Message<?> receive = this.outputChannel.receive(10000);
assertNotNull(receive);
assertEquals(3, receive.getPayload());

View File

@@ -9,10 +9,8 @@
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port"
value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
<bean id="redisConnectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.data.redis.connection.RedisConnectionFactory"/>
</bean>
<bean id="customRedisConnectionFactory" parent="redisConnectionFactory"/>

View File

@@ -35,9 +35,7 @@
</int:channel>
<bean id="redisConnectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg
value="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
</constructor-arg>
<constructor-arg value="org.springframework.data.redis.connection.RedisConnectionFactory"/>
</bean>
<bean id="serializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
@@ -47,6 +45,7 @@
<int-redis:queue-inbound-gateway id="zeroReceiveTimeoutGateway"
request-channel="requestChannel"
receive-timeout="0"
auto-startup="false"
queue="si.test.queue"/>
</beans>

View File

@@ -7,9 +7,8 @@
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
<bean id="redisConnectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.data.redis.connection.RedisConnectionFactory"/>
</bean>
<bean id="customRedisConnectionFactory" parent="redisConnectionFactory"/>

View File

@@ -40,8 +40,7 @@
</int:channel>
<bean id="redisConnectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
</constructor-arg>
<constructor-arg value="org.springframework.data.redis.connection.RedisConnectionFactory"/>
</bean>
<bean id="serializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

View File

@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int-redis:store-inbound-channel-adapter id="listAdapterWithSynchronizationAndRedisTemplate"
redis-template="redisTemplate"
@@ -16,8 +20,4 @@
<int:poller fixed-rate="2000" max-messages-per-poll="10"/>
</int-redis:store-inbound-channel-adapter>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
</beans>

View File

@@ -3,25 +3,23 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:channel id="fromChannel">
<int:queue/>
</int:channel>
<int-redis:queue-inbound-channel-adapter queue="si.test.Int3017IntegrationInbound"
channel="fromChannel"
expect-message="true"
serializer="testSerializer"/>
channel="fromChannel"
expect-message="true"
serializer="testSerializer"/>
<bean id="testSerializer" class="org.springframework.integration.redis.util.CustomJsonSerializer"/>
@@ -31,11 +29,12 @@
</int:chain>
<int-redis:queue-inbound-channel-adapter queue="si.test.Int3017IntegrationSymmetrical"
channel="symmetricalRedisChannel"
serializer=""/>
channel="symmetricalRedisChannel"
serializer=""/>
<int:payload-deserializing-transformer input-channel="symmetricalRedisChannel" output-channel="symmetricalOutputChannel"/>
<int:payload-deserializing-transformer input-channel="symmetricalRedisChannel"
output-channel="symmetricalOutputChannel"/>
<int:channel id="symmetricalOutputChannel">
<int:queue/>

View File

@@ -279,7 +279,7 @@ public class RedisQueueMessageDrivenEndpointTests extends RedisAvailableTests {
@Test
@RedisAvailable
@Ignore("JedisConnectionFactory doesn't support proper 'destroy()' and allows to create new fresh Redis connection")
@Ignore("LettuceConnectionFactory doesn't support proper reinitialization after 'destroy()'")
public void testInt3196Recovery() throws Exception {
String queueName = "test.si.Int3196Recovery";
QueueChannel channel = new QueueChannel();

View File

@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int-redis:store-inbound-channel-adapter id="listAdapter"
connection-factory="redisConnectionFactory"
@@ -87,10 +92,6 @@
<int:queue/>
</int:channel>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager"/>
</beans>

View File

@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int-redis:store-inbound-channel-adapter id="zsetAdapterNoScore"
connection-factory="redisConnectionFactory"
@@ -13,7 +18,7 @@
channel="redisChannel"
auto-startup="false"
collection-type="ZSET">
<int:poller fixed-rate="1000"/>
<int:poller fixed-rate="100"/>
</int-redis:store-inbound-channel-adapter>
<int-redis:store-inbound-channel-adapter id="zsetAdapterWithScoreRange"
@@ -22,7 +27,7 @@
channel="redisChannel"
auto-startup="false"
collection-type="ZSET">
<int:poller fixed-rate="1000" max-messages-per-poll="2"/>
<int:poller fixed-rate="100" max-messages-per-poll="2"/>
</int-redis:store-inbound-channel-adapter>
<int-redis:store-inbound-channel-adapter id="zsetAdapterWithSingleScore"
@@ -31,7 +36,7 @@
channel="redisChannel"
auto-startup="false"
collection-type="ZSET">
<int:poller fixed-rate="1000"/>
<int:poller fixed-rate="100"/>
</int-redis:store-inbound-channel-adapter>
<int-redis:store-inbound-channel-adapter id="zsetAdapterWithSingleScoreAndSynchronization"
@@ -40,7 +45,7 @@
channel="transformChannel"
auto-startup="false"
collection-type="ZSET">
<int:poller fixed-rate="1000">
<int:poller fixed-rate="100">
<int:transactional synchronization-factory="syncFactory"/>
</int:poller>
</int-redis:store-inbound-channel-adapter>
@@ -60,11 +65,6 @@
<int:queue/>
</int:channel>
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager"/>
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 the original author or authors.
* Copyright 2016-2018 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.
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.integration.leader.Context;
@@ -34,6 +35,7 @@ import org.springframework.integration.redis.rules.RedisAvailable;
import org.springframework.integration.redis.rules.RedisAvailableTests;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.integration.support.leader.LockRegistryLeaderInitiator;
import org.springframework.integration.test.rule.Log4j2LevelAdjuster;
/**
* @author Artem Bilan
@@ -44,16 +46,22 @@ import org.springframework.integration.support.leader.LockRegistryLeaderInitiato
*/
public class RedisLockRegistryLeaderInitiatorTests extends RedisAvailableTests {
@Rule
public Log4j2LevelAdjuster adjuster =
Log4j2LevelAdjuster.trace()
.categories(true, "org.springframework.data.redis");
@Test
@RedisAvailable
public void testDistributedLeaderElection() throws Exception {
RedisLockRegistry registry = new RedisLockRegistry(getConnectionFactoryForTest(), "LeaderInitiator");
registry.expireUnusedOlderThan(-1);
CountDownLatch granted = new CountDownLatch(1);
CountingPublisher countingPublisher = new CountingPublisher(granted);
List<LockRegistryLeaderInitiator> initiators = new ArrayList<>();
for (int i = 0; i < 2; i++) {
RedisLockRegistry registry = new RedisLockRegistry(getConnectionFactoryForTest(), "LeaderInitiator");
LockRegistryLeaderInitiator initiator =
new LockRegistryLeaderInitiator(registry, new DefaultCandidate("foo", "bar"));
new LockRegistryLeaderInitiator(registry, new DefaultCandidate("foo:" + i, "bar"));
initiator.setLeaderEventPublisher(countingPublisher);
initiators.add(initiator);
}

View File

@@ -3,12 +3,17 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis
http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:channel id="replyChannel">
<int:queue/>
@@ -48,12 +53,6 @@
<int-redis:outbound-gateway request-channel="mgetCommandChannel" reply-channel="replyChannel"
command-expression="'MGET'"/>
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<constructor-arg ref="redisConnectionFactory"/>
</bean>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2018 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.
@@ -40,16 +40,19 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Artem Bilan
* @author Gary Russell
*
* @since 4.0
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class RedisOutboundGatewayTests extends RedisAvailableTests {
@Autowired
@@ -131,7 +134,7 @@ public class RedisOutboundGatewayTests extends RedisAvailableTests {
.setHeader(RedisHeaders.COMMAND, "SET").build());
Message<?> receive = this.replyChannel.receive(1000);
assertNotNull(receive);
assertTrue(Arrays.equals("OK".getBytes(), (byte[]) receive.getPayload()));
assertEquals("OK", receive.getPayload());
this.getCommandChannel.send(MessageBuilder.withPayload("foo").build());
receive = this.replyChannel.receive(1000);

View File

@@ -3,14 +3,14 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd">
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:chain input-channel="toRedisQueueChannel">
<int-redis:queue-outbound-channel-adapter queue-expression="payload"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2018 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.
@@ -43,6 +43,7 @@ import org.springframework.integration.support.json.JsonInboundMessageMapper;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -50,10 +51,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Gunnar Hillert
* @author Artem Bilan
* @author Rainer Frey
*
* @since 3.0
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class RedisQueueOutboundChannelAdapterTests extends RedisAvailableTests {
@Autowired

View File

@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-redis="http://www.springframework.org/schema/integration/redis"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/redis http://www.springframework.org/schema/integration/redis/spring-integration-redis.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:channel id="someChannel"/>
@@ -56,8 +57,4 @@
map-key-expression="headers['baz']"
collection-type="PROPERTIES"/>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
</beans>

View File

@@ -24,8 +24,11 @@ import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;
/**
* @author Oleg Zhurakousky
@@ -36,67 +39,50 @@ public final class RedisAvailableRule implements MethodRule {
public static final int REDIS_PORT = 6379;
static ThreadLocal<JedisConnectionFactory> connectionFactoryResource = new ThreadLocal<JedisConnectionFactory>();
public static LettuceConnectionFactory connectionFactory;
protected static void setupConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setPort(REDIS_PORT);
LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
.clientOptions(
ClientOptions.builder()
.socketOptions(
SocketOptions.builder()
.connectTimeout(Duration.ofMillis(10000))
.build())
.build())
.commandTimeout(Duration.ofSeconds(10000))
.build();
connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfiguration);
connectionFactory.afterPropertiesSet();
}
public static void cleanUpConnectionFactoryIfAny() {
if (connectionFactory != null) {
connectionFactory.destroy();
}
}
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
RedisAvailable redisAvailable = method.getAnnotation(RedisAvailable.class);
if (redisAvailable != null) {
JedisConnectionFactory connectionFactory = null;
try {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setPort(REDIS_PORT);
JedisClientConfiguration clientConfiguration = JedisClientConfiguration.builder()
.connectTimeout(Duration.ofSeconds(20))
.readTimeout(Duration.ofSeconds(20))
.build();
connectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration, clientConfiguration);
connectionFactory.afterPropertiesSet();
connectionFactory.getConnection();
connectionFactoryResource.set(connectionFactory);
}
catch (Exception e) {
if (connectionFactory != null) {
connectionFactory.destroy();
if (connectionFactory != null) {
try {
connectionFactory.getConnection();
}
return new Statement() {
catch (Exception e) {
Assume.assumeTrue("Skipping test due to Redis not being available on port: " + REDIS_PORT + ": " + e, false);
@Override
public void evaluate() throws Throwable {
Assume.assumeTrue("Skipping test due to Redis not being available on port: " + REDIS_PORT, false);
}
};
}
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
base.evaluate();
}
finally {
JedisConnectionFactory connectionFactory = connectionFactoryResource.get();
connectionFactoryResource.remove();
if (connectionFactory != null) {
connectionFactory.destroy();
}
}
}
};
}
}
return new Statement() {
@Override
public void evaluate() throws Throwable {
base.evaluate();
}
};
return base;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 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.
@@ -19,6 +19,8 @@ package org.springframework.integration.redis.rules;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.springframework.data.redis.connection.RedisConnection;
@@ -38,26 +40,27 @@ import org.springframework.messaging.Message;
* @author Artem Bilan
*
*/
public class RedisAvailableTests {
public abstract class RedisAvailableTests {
@Rule
public RedisAvailableRule redisAvailableRule = new RedisAvailableRule();
private RedisConnectionFactory connectionFactory;
@BeforeClass
public static void setupConnectionFactory() {
RedisAvailableRule.setupConnectionFactory();
}
@AfterClass
public static void cleanUpConnectionFactoryIfAny() {
RedisAvailableRule.cleanUpConnectionFactoryIfAny();
}
protected RedisConnectionFactory getConnectionFactoryForTest() {
if (this.connectionFactory != null) {
return this.connectionFactory;
}
RedisConnectionFactory connectionFactory = RedisAvailableRule.connectionFactoryResource.get();
this.connectionFactory = connectionFactory;
return connectionFactory;
return RedisAvailableRule.connectionFactory;
}
protected void awaitContainerSubscribed(RedisMessageListenerContainer container) throws Exception {
awaitContainerSubscribedNoWait(container);
// wait another second because of race condition
Thread.sleep(1000);
}
private void awaitContainerSubscribedNoWait(RedisMessageListenerContainer container) throws InterruptedException {
@@ -66,7 +69,7 @@ public class RedisAvailableTests {
int n = 0;
while (n++ < 300 &&
(connection =
TestUtils.getPropertyValue(container, "subscriptionTask.connection", RedisConnection .class)) == null) {
TestUtils.getPropertyValue(container, "subscriptionTask.connection", RedisConnection.class)) == null) {
Thread.sleep(100);
}
assertNotNull("RedisMessageListenerContainer Failed to Connect", connection);

View File

@@ -6,11 +6,7 @@
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<beans:bean id="messageStore" class="org.springframework.integration.redis.store.RedisMessageStore">
<beans:constructor-arg>
<beans:bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<beans:property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg value="#{T (org.springframework.integration.redis.rules.RedisAvailableRule).connectionFactory}"/>
</beans:bean>
<channel id="output">

View File

@@ -37,7 +37,6 @@ import org.springframework.integration.redis.rules.RedisAvailableTests;
import org.springframework.integration.store.MessageGroup;
import org.springframework.integration.store.MessageGroupStore;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.rule.Log4j2LevelAdjuster;
import org.springframework.integration.test.support.LongRunningIntegrationTest;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -57,11 +56,6 @@ public class DelayerHandlerRescheduleIntegrationTests extends RedisAvailableTest
@Rule
public LongRunningIntegrationTest longTests = new LongRunningIntegrationTest();
@Rule
public Log4j2LevelAdjuster adjuster =
Log4j2LevelAdjuster.trace()
.categories(true, "org.springframework.data.redis");
@Test
@RedisAvailable
public void testDelayerHandlerRescheduleWithRedisMessageStore() throws Exception {

View File

@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<bean id="cms" class="org.springframework.integration.redis.store.RedisChannelMessageStore">
<constructor-arg>
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
</constructor-arg>
<constructor-arg ref="redisConnectionFactory"/>
</bean>
<int:channel id="testChannel1">
@@ -22,11 +23,7 @@
</int:channel>
<bean id="priorityCms" class="org.springframework.integration.redis.store.RedisChannelPriorityMessageStore">
<constructor-arg>
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
</constructor-arg>
<constructor-arg ref="redisConnectionFactory"/>
</bean>
<int:channel id="testChannel3">

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2018 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.
@@ -36,16 +36,20 @@ import org.springframework.integration.support.MutableMessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
*
* @since 4.0
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class RedisChannelMessageStoreTests extends RedisAvailableTests {
@Autowired

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="redisStore"/>
@@ -12,11 +12,7 @@
</int:channel>
<bean id="redisStore" class="org.springframework.integration.redis.store.RedisMessageStore">
<constructor-arg ref="redisConnectionFactory"/>
</bean>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
<constructor-arg value="#{T (org.springframework.integration.redis.rules.RedisAvailableRule).connectionFactory}"/>
</bean>
</beans>

View File

@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="redisConnectionFactory"
static-field="org.springframework.integration.redis.rules.RedisAvailableRule.connectionFactory"/>
<int:aggregator input-channel="in" release-strategy="latching" output-channel="out"
message-store="sms"
@@ -11,13 +16,8 @@
<bean id="latching" class="org.springframework.integration.redis.util.AggregatorWithRedisLocksTests$LatchingReleaseStrategy" />
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
</bean>
<bean id="redisLockRegistry" class="org.springframework.integration.redis.util.RedisLockRegistry">
<constructor-arg ref="connectionFactory"/>
<constructor-arg ref="redisConnectionFactory"/>
<constructor-arg value="aggregatorWithRedisLocksTests" />
</bean>
@@ -28,7 +28,7 @@
expire-groups-upon-completion="true" lock-registry="redisLockRegistry2" />
<bean id="redisLockRegistry2" class="org.springframework.integration.redis.util.RedisLockRegistry">
<constructor-arg ref="connectionFactory"/>
<constructor-arg ref="redisConnectionFactory"/>
<constructor-arg value="aggregatorWithRedisLocksTests" />
</bean>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 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.
@@ -47,7 +47,6 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.integration.redis.rules.RedisAvailable;
import org.springframework.integration.redis.rules.RedisAvailableTests;
import org.springframework.integration.test.rule.Log4j2LevelAdjuster;
import org.springframework.integration.test.util.TestUtils;
/**
@@ -55,6 +54,7 @@ import org.springframework.integration.test.util.TestUtils;
* @author Konstantin Yakimov
* @author Artem Bilan
* @author Vedran Pavic
*
* @since 4.0
*
*/
@@ -66,11 +66,6 @@ public class RedisLockRegistryTests extends RedisAvailableTests {
private final String registryKey2 = UUID.randomUUID().toString();
@Rule
public Log4j2LevelAdjuster adjuster =
Log4j2LevelAdjuster.trace()
.categories("org.springframework.data.redis");
@Rule
public ExpectedException thrown = ExpectedException.none();

View File

@@ -17,20 +17,17 @@
</int:channel>
<int-twitter:search-inbound-channel-adapter id="twitterSearchAdapter"
query="springintegration"
twitter-template="twitterTemplate"
channel="inbound_twitter"
metadata-store="redisMetadataStore"
auto-startup="false">
query="springintegration"
twitter-template="twitterTemplate"
channel="inbound_twitter"
metadata-store="redisMetadataStore"
auto-startup="false">
<int:poller fixed-delay="100" max-messages-per-poll="3"/>
</int-twitter:search-inbound-channel-adapter>
<bean id="redisMetadataStore" class="org.springframework.integration.redis.metadata.RedisMetadataStore">
<constructor-arg name="connectionFactory" ref="redisConnectionFactory"/>
</bean>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="#{T(org.springframework.integration.redis.rules.RedisAvailableRule).REDIS_PORT}"/>
<constructor-arg name="connectionFactory"
value="#{T (org.springframework.integration.redis.rules.RedisAvailableRule).connectionFactory}"/>
</bean>
</beans>