Refine BrokerAvailabilityEvent behavior

Add accessor for brokerAvailable in AbstractBrokerMessageHandler
Ensure brokerAvailable is set even if eventPublisher is not
Add tests BrokerMessageHandlerTests

Turn off brokerAvailable when StompBrokerRelayMessageHandler stops
Actually stop message handling when brokerAvailable=false
Improve log messages

Issue: SPR-11563
This commit is contained in:
Rossen Stoyanchev
2014-03-16 14:16:34 -04:00
parent 14a8f19670
commit 6bcbb94aba
10 changed files with 275 additions and 54 deletions

View File

@@ -0,0 +1,157 @@
/*
* Copyright 2002-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.messaging.simp.broker;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Unit tests for {@link org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler}.
*
* @author Rossen Stoyanchev
*/
public class BrokerMessageHandlerTests {
private TestBrokerMesageHandler handler;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.handler = new TestBrokerMesageHandler();
}
@Test
public void startShouldUpdateIsRunning() {
assertFalse(this.handler.isRunning());
this.handler.start();
assertTrue(this.handler.isRunning());
}
@Test
public void stopShouldUpdateIsRunning() {
this.handler.start();
assertTrue(this.handler.isRunning());
this.handler.stop();
assertFalse(this.handler.isRunning());
}
@Test
public void stopShouldPublishBrokerAvailabilityEvent() {
this.handler.start();
this.handler.stop();
assertEquals(Arrays.asList(true, false), this.handler.availabilityEvents);
}
@Test
public void handleMessageWhenBrokerNotRunning() {
this.handler.handleMessage(new GenericMessage<Object>("payload"));
assertEquals(Collections.emptyList(), this.handler.messages);
}
@Test
public void publishBrokerAvailableEvent() {
assertFalse(this.handler.isBrokerAvailable());
assertEquals(Collections.emptyList(), this.handler.availabilityEvents);
this.handler.publishBrokerAvailableEvent();
assertTrue(this.handler.isBrokerAvailable());
assertEquals(Arrays.asList(true), this.handler.availabilityEvents);
}
@Test
public void publishBrokerAvailableEventWhenAlreadyAvailable() {
this.handler.publishBrokerAvailableEvent();
this.handler.publishBrokerAvailableEvent();
assertEquals(Arrays.asList(true), this.handler.availabilityEvents);
}
@Test
public void publishBrokerUnavailableEvent() {
this.handler.publishBrokerAvailableEvent();
assertTrue(this.handler.isBrokerAvailable());
this.handler.publishBrokerUnavailableEvent();
assertFalse(this.handler.isBrokerAvailable());
assertEquals(Arrays.asList(true, false), this.handler.availabilityEvents);
}
@Test
public void publishBrokerUnavailableEventWhenAlreadyUnvailable() {
this.handler.publishBrokerAvailableEvent();
this.handler.publishBrokerUnavailableEvent();
this.handler.publishBrokerUnavailableEvent();
assertEquals(Arrays.asList(true, false), this.handler.availabilityEvents);
}
private static class TestBrokerMesageHandler extends AbstractBrokerMessageHandler
implements ApplicationEventPublisher {
private final List<Message<?>> messages = new ArrayList<>();
private final List<Boolean> availabilityEvents = new ArrayList<>();
private TestBrokerMesageHandler() {
setApplicationEventPublisher(this);
}
@Override
protected void startInternal() {
publishBrokerAvailableEvent();
}
@Override
protected void handleMessageInternal(Message<?> message) {
this.messages.add(message);
}
@Override
public void publishEvent(ApplicationEvent event) {
if (event instanceof BrokerAvailabilityEvent) {
this.availabilityEvents.add(((BrokerAvailabilityEvent) event).isBrokerAvailable());
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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.
@@ -36,6 +36,7 @@ import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* Unit tests for SimpleBrokerMessageHandler.
*
* @author Rossen Stoyanchev
* @since 4.0

View File

@@ -23,6 +23,7 @@ import org.springframework.messaging.StubMessageChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler;
import java.util.ArrayList;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
@@ -57,7 +58,9 @@ public class StompBrokerRelayRegistrationTests {
StompBrokerRelayMessageHandler relayMessageHandler = registration.getMessageHandler(brokerChannel);
assertEquals(Arrays.asList(destinationPrefixes), relayMessageHandler.getDestinationPrefixes());
assertEquals(Arrays.asList(destinationPrefixes),
new ArrayList<String>(relayMessageHandler.getDestinationPrefixes()));
assertEquals("clientlogin", relayMessageHandler.getClientLogin());
assertEquals("clientpasscode", relayMessageHandler.getClientPasscode());
assertEquals("syslogin", relayMessageHandler.getSystemLogin());

View File

@@ -164,18 +164,6 @@ public class StompBrokerRelayMessageHandlerIntegrationTests {
this.responseHandler.awaitAndAssert();
}
@Test
public void brokerUnvailableErrorFrameOnConnect() throws Exception {
stopActiveMqBrokerAndAwait();
MessageExchange connect = MessageExchangeBuilder.connectWithError("sess1").build();
this.responseHandler.expect(connect);
this.relay.handleMessage(connect.message);
this.responseHandler.awaitAndAssert();
}
@Test(expected=MessageDeliveryException.class)
public void messageDeliverExceptionIfSystemSessionForwardFails() throws Exception {
stopActiveMqBrokerAndAwait();

View File

@@ -19,13 +19,18 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.messaging.Message;
import org.springframework.messaging.StubMessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.messaging.tcp.ReconnectStrategy;
import org.springframework.messaging.tcp.TcpConnection;
@@ -50,24 +55,33 @@ public class StompBrokerRelayMessageHandlerTests {
@Before
public void setup() {
this.tcpClient = new StubTcpOperations();
this.brokerRelay = new StompBrokerRelayMessageHandler(new StubMessageChannel(),
new StubMessageChannel(), new StubMessageChannel(), Arrays.asList("/topic"));
new StubMessageChannel(), new StubMessageChannel(), Arrays.asList("/topic")) {
@Override
protected void startInternal() {
publishBrokerAvailableEvent(); // Force this, since we'll never actually connect
super.startInternal();
}
};
this.brokerRelay.setTcpClient(this.tcpClient);
}
@Test
public void testVirtualHostHeader() {
public void testVirtualHostHeader() throws Exception {
String virtualHost = "ABC";
String sessionId = "sess1";
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT);
headers.setSessionId(sessionId);
this.brokerRelay.setVirtualHost(virtualHost);
this.brokerRelay.start();
String sessionId = "sess1";
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT);
headers.setSessionId(sessionId);
this.brokerRelay.handleMessage(MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build());
List<Message<byte[]>> sent = this.tcpClient.connection.messages;
@@ -82,12 +96,7 @@ public class StompBrokerRelayMessageHandlerTests {
}
@Test
public void testLoginPasscode() {
String sessionId = "sess1";
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT);
headers.setSessionId(sessionId);
public void testLoginPasscode() throws Exception {
this.brokerRelay.setClientLogin("clientlogin");
this.brokerRelay.setClientPasscode("clientpasscode");
@@ -96,6 +105,10 @@ public class StompBrokerRelayMessageHandlerTests {
this.brokerRelay.setSystemPasscode("syspasscode");
this.brokerRelay.start();
String sessionId = "sess1";
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT);
headers.setSessionId(sessionId);
this.brokerRelay.handleMessage(MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build());
List<Message<byte[]>> sent = this.tcpClient.connection.messages;
@@ -111,13 +124,13 @@ public class StompBrokerRelayMessageHandlerTests {
}
@Test
public void testDestinationExcluded() {
public void testDestinationExcluded() throws Exception {
this.brokerRelay.start();
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headers.setSessionId("sess1");
headers.setDestination("/user/daisy/foo");
this.brokerRelay.start();
this.brokerRelay.handleMessage(MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build());
List<Message<byte[]>> sent = this.tcpClient.connection.messages;