提交 04840166 编写于 作者: R Rossen Stoyanchev

DefaultSubscriptionRegistry returns safe to iterate Map

Prior to this change when adding subscriptions
DefaultSubscriptionRegistry (incorrectly) made a copy of the given map
for its "access" cache rather than for its "update" cache.

Issue: SPR-12665
上级 6fce6d46
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
......@@ -32,6 +32,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.PathMatcher;
/**
* A default, simple in-memory implementation of {@link SubscriptionRegistry}.
*
......@@ -165,8 +166,8 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
public void addSubscriptions(String destination, MultiValueMap<String, String> subscriptions) {
synchronized (this.updateCache) {
this.updateCache.put(destination, subscriptions);
this.accessCache.put(destination, new LinkedMultiValueMap<String, String>(subscriptions));
this.updateCache.put(destination, new LinkedMultiValueMap<String, String>(subscriptions));
this.accessCache.put(destination, subscriptions);
}
}
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
......@@ -45,9 +45,11 @@ public interface SubscriptionRegistry {
void unregisterAllSubscriptions(String sessionId);
/**
* Find all subscriptions that should receive the given message.
* Find all subscriptions that should receive the given message. The map
* returned is safe to iterate and will never be modified.
* @param message the message
* @return a {@link MultiValueMap} from sessionId to subscriptionId's, possibly empty.
* @return a {@code MultiValueMap} with sessionId-subscriptionId pairs,
* possibly empty.
*/
MultiValueMap<String, String> findSubscriptions(Message<?> message);
......
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
......@@ -18,6 +18,7 @@ package org.springframework.messaging.simp.broker;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.junit.Before;
......@@ -31,6 +32,7 @@ import org.springframework.util.MultiValueMap;
import static org.junit.Assert.*;
/**
* Test fixture for {@link org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry}.
*
......@@ -326,6 +328,23 @@ public class DefaultSubscriptionRegistryTests {
assertEquals("Expected no elements " + actual, 0, actual.size());
}
// SPR-12665
@Test
public void findSubscriptionsReturnsMapSafeToIterate() throws Exception {
this.registry.registerSubscription(subscribeMessage("sess1", "1", "/foo"));
this.registry.registerSubscription(subscribeMessage("sess2", "1", "/foo"));
MultiValueMap<String, String> subscriptions = this.registry.findSubscriptions(message("/foo"));
assertEquals(2, subscriptions.size());
Iterator iterator = subscriptions.entrySet().iterator();
iterator.next();
this.registry.registerSubscription(subscribeMessage("sess3", "1", "/foo"));
iterator.next();
// no ConcurrentModificationException
}
private Message<?> subscribeMessage(String sessionId, String subscriptionId, String destination) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.SUBSCRIBE);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册