Refine "." separator support for STOMP messaging

After this commit DefaultUserDestinationResolves no longer looks at
whether AntPathMatcher is configured with "." as separator and rather
expects to be explicitly told whether to keep the leading slash in
translated destinations which actually depends on what the message
broker supports (e.g. RabbitMQ "/", Artemis ".") or how it is
configured (simple broker could be either way).

There is also a minor improvement in SimpMessagingTemplate to ensure
user destinations are correctly formed based on what the
DefaultUserDestinationResolver expects. When using "." as separtor it
allows sending messages to "queue.q1" rather than "/queue.q1".

Issue: SPR-16275
This commit is contained in:
Rossen Stoyanchev
2018-01-19 15:32:38 -05:00
parent 238e9ae59f
commit ef4b62caa0
5 changed files with 173 additions and 21 deletions

View File

@@ -221,6 +221,7 @@ public class SimpMessagingTemplate extends AbstractMessageSendingTemplate<String
Assert.notNull(user, "User must not be null");
user = StringUtils.replace(user, "/", "%2F");
destination = destination.startsWith("/") ? destination : "/" + destination;
super.convertAndSend(this.destinationPrefix + user + destination, payload, headers, postProcessor);
}

View File

@@ -17,6 +17,7 @@
package org.springframework.messaging.simp.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -284,7 +285,18 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
@Bean
public AbstractBrokerMessageHandler simpleBrokerMessageHandler() {
SimpleBrokerMessageHandler handler = getBrokerRegistry().getSimpleBroker(brokerChannel());
return (handler != null ? handler : new NoOpBrokerMessageHandler());
if (handler == null) {
return new NoOpBrokerMessageHandler();
}
updateUserDestinationResolver(handler);
return handler;
}
private void updateUserDestinationResolver(AbstractBrokerMessageHandler handler) {
Collection<String> prefixes = handler.getDestinationPrefixes();
if (!prefixes.isEmpty() && !prefixes.iterator().next().startsWith("/")) {
((DefaultUserDestinationResolver) userDestinationResolver()).setRemoveLeadingSlash(true);
}
}
@Bean
@@ -303,6 +315,7 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
subscriptions.put(destination, userRegistryMessageHandler());
}
handler.setSystemSubscriptions(subscriptions);
updateUserDestinationResolver(handler);
return handler;
}
@@ -387,7 +400,6 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
if (prefix != null) {
resolver.setUserDestinationPrefix(prefix);
}
resolver.setPathMatcher(getBrokerRegistry().getPathMatcher());
return resolver;
}

View File

@@ -58,7 +58,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
private String prefix = "/user/";
private boolean keepLeadingSlash = true;
private boolean removeLeadingSlash = false;
/**
@@ -97,6 +97,29 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
return this.prefix;
}
/**
* Use this property to indicate whether the leading slash from translated
* user destinations should be removed or not. This depends on the
* destination prefixes the message broker is configured with.
* <p>By default this is set to {@code false}, i.e. "do not change the
* target destination", although
* {@link org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration
* AbstractMessageBrokerConfiguration} may change that to {@code true} if
* the configured destinations do not have a leading slash.
* @param remove whether to remove the leading slash
* @since 4.3.14
*/
public void setRemoveLeadingSlash(boolean remove) {
this.removeLeadingSlash = remove;
}
/**
* Whether to remove the leading slash from target destinations.
*/
public boolean isRemoveLeadingSlash() {
return this.removeLeadingSlash;
}
/**
* Provide the {@code PathMatcher} in use for working with destinations
* which in turn helps to determine whether the leading slash should be
@@ -110,11 +133,14 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
* jms.queue.position-updates}.
* @param pathMatcher the PathMatcher used to work with destinations
* @since 4.3
* @deprecated as of 4.3.14 this property is no longer used and is replaced
* by {@link #setRemoveLeadingSlash(boolean)} that indicates more explicitly
* whether to keep the leading slash which may or may not be the case
* regardless of how the {@code PathMatcher} is configured.
*/
@Deprecated
public void setPathMatcher(PathMatcher pathMatcher) {
if (pathMatcher != null) {
this.keepLeadingSlash = pathMatcher.combine("1", "2").equals("1/2");
}
// Do nothing
}
@@ -166,7 +192,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
}
int prefixEnd = this.prefix.length() - 1;
String actualDestination = sourceDestination.substring(prefixEnd);
if (!this.keepLeadingSlash) {
if (isRemoveLeadingSlash()) {
actualDestination = actualDestination.substring(1);
}
Principal principal = SimpMessageHeaderAccessor.getUser(headers);
@@ -193,7 +219,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
else {
sessionIds = getSessionIdsByUser(userName, sessionId);
}
if (!this.keepLeadingSlash) {
if (isRemoveLeadingSlash()) {
actualDestination = actualDestination.substring(1);
}
return new ParseResult(sourceDestination, actualDestination, subscribeDestination,