@Override
 public Message<?> sendAndReceive(MessageChannel destination, Message<?> requestMessage) {
   if (!this.throwExceptionOnLateReplySet) {
     synchronized (this) {
       if (!this.throwExceptionOnLateReplySet) {
         Properties integrationProperties =
             IntegrationContextUtils.getIntegrationProperties(this.beanFactory);
         Boolean throwExceptionOnLateReply =
             Boolean.valueOf(
                 integrationProperties.getProperty(
                     IntegrationProperties.THROW_EXCEPTION_ON_LATE_REPLY));
         super.setThrowExceptionOnLateReply(throwExceptionOnLateReply);
         this.throwExceptionOnLateReplySet = true;
       }
     }
   }
   return super.sendAndReceive(destination, requestMessage);
 }
  @Test
  @RedisAvailable
  public void testDelayerHandlerRescheduleWithRedisMessageStore() throws Exception {
    AbstractApplicationContext context =
        new ClassPathXmlApplicationContext(
            "DelayerHandlerRescheduleIntegrationTests-context.xml", this.getClass());
    MessageChannel input = context.getBean("input", MessageChannel.class);
    MessageGroupStore messageStore = context.getBean("messageStore", MessageGroupStore.class);

    String delayerMessageGroupId = DELAYER_ID + ".messageGroupId";

    messageStore.removeMessageGroup(delayerMessageGroupId);

    Message<String> message1 = MessageBuilder.withPayload("test1").build();
    input.send(message1);
    input.send(MessageBuilder.withPayload("test2").build());

    // Emulate restart and check DB state before next start
    // Interrupt taskScheduler as quickly as possible
    ThreadPoolTaskScheduler taskScheduler =
        (ThreadPoolTaskScheduler) IntegrationContextUtils.getTaskScheduler(context);
    taskScheduler.shutdown();
    taskScheduler.getScheduledExecutor().awaitTermination(10, TimeUnit.SECONDS);
    context.destroy();

    try {
      context.getBean("input", MessageChannel.class);
      fail("IllegalStateException expected");
    } catch (Exception e) {
      assertTrue(e instanceof IllegalStateException);
      assertTrue(
          e.getMessage()
              .contains("BeanFactory not initialized or already closed - call 'refresh'"));
    }

    assertEquals(1, messageStore.getMessageGroupCount());
    assertEquals(delayerMessageGroupId, messageStore.iterator().next().getGroupId());
    assertEquals(2, messageStore.messageGroupSize(delayerMessageGroupId));
    assertEquals(2, messageStore.getMessageCountForAllMessageGroups());
    MessageGroup messageGroup = messageStore.getMessageGroup(delayerMessageGroupId);
    Message<?> messageInStore = messageGroup.getMessages().iterator().next();
    Object payload = messageInStore.getPayload();

    // INT-3049
    assertTrue(payload instanceof DelayHandler.DelayedMessageWrapper);
    assertEquals(message1, ((DelayHandler.DelayedMessageWrapper) payload).getOriginal());

    context.refresh();

    PollableChannel output = context.getBean("output", PollableChannel.class);

    Message<?> message = output.receive(20000);
    assertNotNull(message);

    Object payload1 = message.getPayload();

    message = output.receive(20000);
    assertNotNull(message);
    Object payload2 = message.getPayload();
    assertNotSame(payload1, payload2);

    assertEquals(1, messageStore.getMessageGroupCount());
    assertEquals(0, messageStore.messageGroupSize(delayerMessageGroupId));

    messageStore.removeMessageGroup(delayerMessageGroupId);
  }