Add "simple" broker and SessionSubscriptionRegistry

SimpleBrokerWebMessageHandler can be used as an alternative to the
StompRelayWebMessageHandler.
This commit is contained in:
Rossen Stoyanchev
2013-07-03 20:40:56 -04:00
parent e694cc16c7
commit 0a68c9930f
13 changed files with 963 additions and 205 deletions

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2002-2013 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.web.messaging.service;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.messaging.MessageType;
import org.springframework.web.messaging.support.WebMessageHeaderAccesssor;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class SimpleBrokerWebMessageHandlerTests {
private AbstractWebMessageHandler messageHandler;
@Mock
private MessageChannel clientChannel;
@Captor
ArgumentCaptor<Message<?>> messageCaptor;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.messageHandler = new SimpleBrokerWebMessageHandler(this.clientChannel);
}
@Test
public void getSupportedMessageTypes() {
assertEquals(Arrays.asList(MessageType.MESSAGE, MessageType.SUBSCRIBE, MessageType.UNSUBSCRIBE),
this.messageHandler.getSupportedMessageTypes());
}
@Test
public void subcribePublish() {
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub1", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub2", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub3", "/bar"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub1", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub2", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub3", "/bar"));
this.messageHandler.handlePublish(createMessage("/foo", "message1"));
this.messageHandler.handlePublish(createMessage("/bar", "message2"));
verify(this.clientChannel, times(6)).send(this.messageCaptor.capture());
assertCapturedMessage(this.messageCaptor.getAllValues().get(0), "sess1", "sub1", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(1), "sess1", "sub2", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(2), "sess2", "sub1", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(3), "sess2", "sub2", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(4), "sess1", "sub3", "/bar");
assertCapturedMessage(this.messageCaptor.getAllValues().get(5), "sess2", "sub3", "/bar");
}
@Test
public void subcribeDisconnectPublish() {
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub1", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub2", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess1", "sub3", "/bar"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub1", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub2", "/foo"));
this.messageHandler.handleSubscribe(createSubscriptionMessage("sess2", "sub3", "/bar"));
WebMessageHeaderAccesssor headers = WebMessageHeaderAccesssor.create(MessageType.DISCONNECT);
headers.setSessionId("sess1");
Message<byte[]> message = MessageBuilder.withPayload(new byte[0]).copyHeaders(headers.toMap()).build();
this.messageHandler.handleDisconnect(message);
this.messageHandler.handlePublish(createMessage("/foo", "message1"));
this.messageHandler.handlePublish(createMessage("/bar", "message2"));
verify(this.clientChannel, times(3)).send(this.messageCaptor.capture());
assertCapturedMessage(this.messageCaptor.getAllValues().get(0), "sess2", "sub1", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(1), "sess2", "sub2", "/foo");
assertCapturedMessage(this.messageCaptor.getAllValues().get(2), "sess2", "sub3", "/bar");
}
protected Message<String> createSubscriptionMessage(String sessionId, String subcriptionId, String destination) {
WebMessageHeaderAccesssor headers = WebMessageHeaderAccesssor.create(MessageType.SUBSCRIBE);
headers.setSubscriptionId(subcriptionId);
headers.setDestination(destination);
headers.setSessionId(sessionId);
return MessageBuilder.withPayload("").copyHeaders(headers.toMap()).build();
}
protected Message<String> createMessage(String destination, String payload) {
WebMessageHeaderAccesssor headers = WebMessageHeaderAccesssor.create(MessageType.MESSAGE);
headers.setDestination(destination);
return MessageBuilder.withPayload(payload).copyHeaders(headers.toMap()).build();
}
protected void assertCapturedMessage(Message<?> message, String sessionId,
String subcriptionId, String destination) {
WebMessageHeaderAccesssor headers = WebMessageHeaderAccesssor.wrap(message);
assertEquals(sessionId, headers.getSessionId());
assertEquals(subcriptionId, headers.getSubscriptionId());
assertEquals(destination, headers.getDestination());
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2002-2013 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.web.messaging.support;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.web.messaging.SessionSubscriptionRegistration;
import org.springframework.web.messaging.SessionSubscriptionRegistry;
import static org.junit.Assert.*;
/**
* Test fixture for {@link CachingSessionSubscriptionRegistry}.
*
* @author Rossen Stoyanchev
*/
public class CachingSessionSubscriptionRegistryTests {
private CachingSessionSubscriptionRegistry registry;
@Before
public void setup() {
SessionSubscriptionRegistry delegate = new DefaultSessionSubscriptionRegistry();
this.registry = new CachingSessionSubscriptionRegistry(delegate);
}
@Test
public void getRegistrationsByDestination() {
SessionSubscriptionRegistration reg1 = this.registry.getOrCreateRegistration("sess1");
reg1.addSubscription("/foo", "sub1");
reg1.addSubscription("/foo", "sub1");
SessionSubscriptionRegistration reg2 = this.registry.getOrCreateRegistration("sess2");
reg2.addSubscription("/foo", "sub1");
reg2.addSubscription("/foo", "sub1");
Set<SessionSubscriptionRegistration> actual = this.registry.getRegistrationsByDestination("/foo");
assertEquals(2, actual.size());
assertTrue(actual.contains(reg1));
assertTrue(actual.contains(reg2));
reg1.removeSubscription("sub1");
reg1.removeSubscription("sub2");
actual = this.registry.getRegistrationsByDestination("/foo");
assertEquals("Invalid set of registrations " + actual, 1, actual.size());
assertTrue(actual.contains(reg2));
reg2.removeSubscription("sub1");
reg2.removeSubscription("sub2");
actual = this.registry.getRegistrationsByDestination("/foo");
assertNull("Unexpected registrations " + actual, actual);
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2002-2013 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.web.messaging.support;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Test fixture for {@link DefaultSessionSubscriptionRegistration}.
*
* @author Rossen Stoyanchev
*/
public class DefaultSessionSubscriptionRegistrationTests {
private DefaultSessionSubscriptionRegistration registration;
@Before
public void setup() {
this.registration = new DefaultSessionSubscriptionRegistration("sess1");
}
@Test
public void addSubscriptions() {
this.registration.addSubscription("/foo", "sub1");
this.registration.addSubscription("/foo", "sub2");
this.registration.addSubscription("/bar", "sub3");
this.registration.addSubscription("/bar", "sub4");
assertSet(this.registration.getSubscriptionsByDestination("/foo"), 2, "sub1", "sub2");
assertSet(this.registration.getSubscriptionsByDestination("/bar"), 2, "sub3", "sub4");
assertSet(this.registration.getDestinations(), 2, "/foo", "/bar");
}
@Test
public void removeSubscriptions() {
this.registration.addSubscription("/foo", "sub1");
this.registration.addSubscription("/foo", "sub2");
this.registration.addSubscription("/bar", "sub3");
this.registration.addSubscription("/bar", "sub4");
assertEquals("/foo", this.registration.removeSubscription("sub1"));
assertEquals("/foo", this.registration.removeSubscription("sub2"));
assertNull(this.registration.getSubscriptionsByDestination("/foo"));
assertSet(this.registration.getDestinations(), 1, "/bar");
assertEquals("/bar", this.registration.removeSubscription("sub3"));
assertEquals("/bar", this.registration.removeSubscription("sub4"));
assertNull(this.registration.getSubscriptionsByDestination("/bar"));
assertSet(this.registration.getDestinations(), 0);
}
private void assertSet(Set<String> set, int size, String... elements) {
assertEquals("Wrong number of elements in " + set, size, set.size());
for (String element : elements) {
assertTrue("Set does not contain element " + element, set.contains(element));
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2002-2013 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.web.messaging.support;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.web.messaging.SessionSubscriptionRegistration;
import static org.junit.Assert.*;
/**
* Test fixture for {@link DefaultSessionSubscriptionRegistry}.
*
* @author Rossen Stoyanchev
*/
public class DefaultSessionSubscriptionRegistryTests {
private DefaultSessionSubscriptionRegistry registry;
@Before
public void setup() {
this.registry = new DefaultSessionSubscriptionRegistry();
}
@Test
public void getRegistration() {
String sessionId = "sess1";
assertNull(this.registry.getRegistration(sessionId));
this.registry.getOrCreateRegistration(sessionId);
assertNotNull(this.registry.getRegistration(sessionId));
assertEquals(sessionId, this.registry.getRegistration(sessionId).getSessionId());
}
@Test
public void getOrCreateRegistration() {
String sessionId = "sess1";
assertNull(this.registry.getRegistration(sessionId));
SessionSubscriptionRegistration registration = this.registry.getOrCreateRegistration(sessionId);
assertSame(registration, this.registry.getOrCreateRegistration(sessionId));
}
@Test
public void removeRegistration() {
String sessionId = "sess1";
this.registry.getOrCreateRegistration(sessionId);
assertNotNull(this.registry.getRegistration(sessionId));
assertEquals(sessionId, this.registry.getRegistration(sessionId).getSessionId());
this.registry.removeRegistration(sessionId);
assertNull(this.registry.getRegistration(sessionId));
}
@Test
public void getSessionSubscriptions() {
String sessionId = "sess1";
SessionSubscriptionRegistration registration = this.registry.getOrCreateRegistration(sessionId);
registration.addSubscription("/foo", "sub1");
registration.addSubscription("/foo", "sub2");
Set<String> subscriptions = this.registry.getSessionSubscriptions(sessionId, "/foo");
assertEquals("Wrong number of subscriptions " + subscriptions, 2, subscriptions.size());
assertTrue(subscriptions.contains("sub1"));
assertTrue(subscriptions.contains("sub2"));
}
}