Package org.springframework.data.redis.listener

Source Code of org.springframework.data.redis.listener.PubSubResubscribeTests$MessageHandler

/*
* Copyright 2011-2014 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.data.redis.listener;

import static org.hamcrest.core.Is.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.data.redis.ConnectionFactoryTracker;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.SettingsUtils;
import org.springframework.data.redis.connection.ConnectionUtils;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.jredis.JredisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.srp.SrpConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

/**
* @author Costin Leau
* @author Jennifer Hickey
* @author Christoph Strobl
*/
@RunWith(Parameterized.class)
public class PubSubResubscribeTests {

  private static final String CHANNEL = "pubsub::test";

  private final BlockingDeque<String> bag = new LinkedBlockingDeque<String>(99);
  private final Object handler = new MessageHandler("handler1", bag);
  private final MessageListenerAdapter adapter = new MessageListenerAdapter(handler);

  private RedisMessageListenerContainer container;
  private RedisConnectionFactory factory;

  @SuppressWarnings("rawtypes")//
  private RedisTemplate template;

  public PubSubResubscribeTests(RedisConnectionFactory connectionFactory) {

    this.factory = connectionFactory;
    ConnectionFactoryTracker.add(factory);
  }

  @BeforeClass
  public static void shouldRun() {
    assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
  }

  @AfterClass
  public static void cleanUp() {
    ConnectionFactoryTracker.cleanUp();
  }

  @Parameters
  public static Collection<Object[]> testParams() {

    int port = SettingsUtils.getPort();
    String host = SettingsUtils.getHost();
   
    // Jedis
    JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory();
    jedisConnFactory.setUsePool(false);
    jedisConnFactory.setPort(port);
    jedisConnFactory.setHostName(host);
    jedisConnFactory.setDatabase(2);
    jedisConnFactory.afterPropertiesSet();

    // Lettuce
    LettuceConnectionFactory lettuceConnFactory = new LettuceConnectionFactory();
    lettuceConnFactory.setPort(port);
    lettuceConnFactory.setHostName(host);
    lettuceConnFactory.setDatabase(2);
    lettuceConnFactory.setValidateConnection(true);
    lettuceConnFactory.afterPropertiesSet();

    // SRP
    SrpConnectionFactory srpConnFactory = new SrpConnectionFactory();
    srpConnFactory.setPort(port);
    srpConnFactory.setHostName(host);
    srpConnFactory.afterPropertiesSet();

    // JRedis
    JredisConnectionFactory jRedisConnectionFactory = new JredisConnectionFactory();
    jRedisConnectionFactory.setPort(port);
    jRedisConnectionFactory.setHostName(host);
    jRedisConnectionFactory.setDatabase(2);
    jRedisConnectionFactory.afterPropertiesSet();

    return Arrays.asList(new Object[][] { { jedisConnFactory }, { lettuceConnFactory }, { srpConnFactory },
        { jRedisConnectionFactory } });
  }

  @Before
  public void setUp() throws Exception {

    // JredisConnection#publish is currently not supported -> tests would fail
    assumeThat(ConnectionUtils.isJredis(factory), is(false));

    template = new StringRedisTemplate(factory);

    adapter.setSerializer(template.getValueSerializer());
    adapter.afterPropertiesSet();

    container = new RedisMessageListenerContainer();
    container.setConnectionFactory(template.getConnectionFactory());
    container.setBeanName("container");
    container.addMessageListener(adapter, new ChannelTopic(CHANNEL));
    container.setTaskExecutor(new SyncTaskExecutor());
    container.setSubscriptionExecutor(new SimpleAsyncTaskExecutor());
    container.afterPropertiesSet();
    container.start();

    Thread.sleep(1000);
  }

  @After
  public void tearDown() {
    bag.clear();
  }

  @Test
  public void testContainerPatternResubscribe() throws Exception {

    String payload1 = "do";
    String payload2 = "re mi";

    final String PATTERN = "p*";
    final String ANOTHER_CHANNEL = "pubsub::test::extra";

    BlockingDeque<String> bag2 = new LinkedBlockingDeque<String>(99);
    MessageListenerAdapter anotherListener = new MessageListenerAdapter(new MessageHandler("handler2", bag2));
    anotherListener.setSerializer(template.getValueSerializer());
    anotherListener.afterPropertiesSet();

    // remove adapter from all channels
    container.addMessageListener(anotherListener, new PatternTopic(PATTERN));
    container.removeMessageListener(adapter);

    // test no messages are sent just to patterns
    template.convertAndSend(CHANNEL, payload1);
    template.convertAndSend(ANOTHER_CHANNEL, payload2);

    // anotherListener receives both messages
    List<String> msgs = new ArrayList<String>();
    msgs.add(bag2.poll(1, TimeUnit.SECONDS));
    msgs.add(bag2.poll(1, TimeUnit.SECONDS));

    assertEquals(2, msgs.size());
    assertTrue(msgs.contains(payload1));
    assertTrue(msgs.contains(payload2));
    msgs.clear();

    // unsubscribed adapter did not receive message
    assertNull(bag.poll(1, TimeUnit.SECONDS));

    // bind original listener on another channel
    container.addMessageListener(adapter, new ChannelTopic(ANOTHER_CHANNEL));

    template.convertAndSend(CHANNEL, payload1);
    template.convertAndSend(ANOTHER_CHANNEL, payload2);

    // original listener received only one message on another channel
    assertEquals(payload2, bag.poll(1, TimeUnit.SECONDS));
    assertNull(bag.poll(1, TimeUnit.SECONDS));

    // another listener receives messages on both channels
    msgs.add(bag2.poll(1, TimeUnit.SECONDS));
    msgs.add(bag2.poll(1, TimeUnit.SECONDS));
    assertEquals(2, msgs.size());
    assertTrue(msgs.contains(payload1));
    assertTrue(msgs.contains(payload2));
  }

  @Test
  public void testContainerChannelResubscribe() throws Exception {

    String payload1 = "do";
    String payload2 = "re mi";

    String anotherPayload1 = "od";
    String anotherPayload2 = "mi er";

    String ANOTHER_CHANNEL = "pubsub::test::extra";

    // bind listener on another channel
    container.addMessageListener(adapter, new ChannelTopic(ANOTHER_CHANNEL));
    container.removeMessageListener(null, new ChannelTopic(CHANNEL));

    // Listener removed from channel
    template.convertAndSend(CHANNEL, payload1);
    template.convertAndSend(CHANNEL, payload2);

    // Listener receives messages on another channel
    template.convertAndSend(ANOTHER_CHANNEL, anotherPayload1);
    template.convertAndSend(ANOTHER_CHANNEL, anotherPayload2);

    Set<String> set = new LinkedHashSet<String>();
    set.add(bag.poll(1, TimeUnit.SECONDS));
    set.add(bag.poll(1, TimeUnit.SECONDS));

    assertFalse(set.contains(payload1));
    assertFalse(set.contains(payload2));

    assertTrue(set.contains(anotherPayload1));
    assertTrue(set.contains(anotherPayload2));
  }

  /**
   * Validates the behavior of {@link RedisMessageListenerContainer} when it needs to spin up a thread executing its
   * PatternSubscriptionTask
   *
   * @throws Exception
   */
  @Test
  public void testInitializeContainerWithMultipleTopicsIncludingPattern() throws Exception {

    container.removeMessageListener(adapter);
    container.stop();
    container.addMessageListener(adapter,
        Arrays.asList(new Topic[] { new ChannelTopic(CHANNEL), new PatternTopic("s*") }));
    container.start();

    // Wait for async subscription tasks to setup
    Thread.sleep(1000);

    template.convertAndSend("somechannel", "HELLO");
    template.convertAndSend(CHANNEL, "WORLD");

    Set<String> set = new LinkedHashSet<String>();
    set.add(bag.poll(1, TimeUnit.SECONDS));
    set.add(bag.poll(1, TimeUnit.SECONDS));

    assertEquals(new HashSet<String>(Arrays.asList(new String[] { "HELLO", "WORLD" })), set);
  }

  private class MessageHandler {

    private final BlockingDeque<String> bag;
    private final String name;

    public MessageHandler(String name, BlockingDeque<String> bag) {

      this.bag = bag;
      this.name = name;
    }

    @SuppressWarnings("unused")
    public void handleMessage(String message) {
      bag.add(message);
    }
  }
}
TOP

Related Classes of org.springframework.data.redis.listener.PubSubResubscribeTests$MessageHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.