diff --git a/spring-core/src/main/java/org/springframework/util/comparator/package-info.java b/spring-core/src/main/java/org/springframework/util/comparator/package-info.java index 7bcb8576d8..f2213670b9 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/package-info.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/package-info.java @@ -1,3 +1,4 @@ + /** * * Useful generic {@code java.util.Comparator} implementations, diff --git a/spring-core/src/main/java/org/springframework/util/concurrent/package-info.java b/spring-core/src/main/java/org/springframework/util/concurrent/package-info.java index a03788bd27..ce15f2eb7c 100644 --- a/spring-core/src/main/java/org/springframework/util/concurrent/package-info.java +++ b/spring-core/src/main/java/org/springframework/util/concurrent/package-info.java @@ -2,6 +2,7 @@ /** * * Useful generic {@code java.util.concurrent.Future} extension. + * */ package org.springframework.util.concurrent; diff --git a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java index 1cf202c706..581cc68b74 100644 --- a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java @@ -16,11 +16,7 @@ package org.springframework.jms.listener.adapter; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; - import java.lang.reflect.Method; - import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Session; @@ -32,12 +28,15 @@ import org.junit.Test; import org.springframework.context.support.StaticApplicationContext; import org.springframework.jms.StubTextMessage; import org.springframework.jms.config.DefaultJmsHandlerMethodFactory; -import org.springframework.jms.support.converter.JmsHeaders; +import org.springframework.jms.support.JmsHeaders; import org.springframework.messaging.Message; import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.ReflectionUtils; +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; + /** * * @author Stephane Nicoll @@ -48,6 +47,7 @@ public class MessagingMessageListenerAdapterTests { private final SampleBean sample = new SampleBean(); + @Before public void setup() { initializeFactory(factory); @@ -85,12 +85,12 @@ public class MessagingMessageListenerAdapterTests { listener.onMessage(message, session); fail("Should have thrown an exception"); } - catch (JMSException e) { + catch (JMSException ex) { fail("Should not have thrown a JMS exception"); } - catch (ListenerExecutionFailedException e) { - assertEquals(IllegalArgumentException.class, e.getCause().getClass()); - assertEquals("Expected test exception", e.getCause().getMessage()); + catch (ListenerExecutionFailedException ex) { + assertEquals(IllegalArgumentException.class, ex.getCause().getClass()); + assertEquals("Expected test exception", ex.getCause().getMessage()); } } @@ -104,11 +104,11 @@ public class MessagingMessageListenerAdapterTests { listener.onMessage(message, session); fail("Should have thrown an exception"); } - catch (JMSException e) { + catch (JMSException ex) { fail("Should not have thrown a JMS exception"); } - catch (ListenerExecutionFailedException e) { - assertEquals(MessageConversionException.class, e.getCause().getClass()); + catch (ListenerExecutionFailedException ex) { + assertEquals(MessageConversionException.class, ex.getCause().getClass()); } } @@ -145,4 +145,5 @@ public class MessagingMessageListenerAdapterTests { throw new IllegalArgumentException("Should not have been called"); } } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/Message.java b/spring-messaging/src/main/java/org/springframework/messaging/Message.java index b93988e9bd..0aea12d32a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/Message.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/Message.java @@ -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. @@ -27,7 +27,7 @@ package org.springframework.messaging; public interface Message { /** - * Return message headers for the message, never {@code null}. + * Return message headers for the message (never {@code null}). */ MessageHeaders getHeaders(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/MessageHeaders.java b/spring-messaging/src/main/java/org/springframework/messaging/MessageHeaders.java index 552440e2f8..058d22753b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/MessageHeaders.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/MessageHeaders.java @@ -36,18 +36,19 @@ import org.springframework.util.AlternativeJdkIdGenerator; import org.springframework.util.IdGenerator; /** - * The headers for a {@link Message} - *

- * IMPORTANT: This class is immutable. Any mutating operation such as + * The headers for a {@link Message}. + * + *

IMPORTANT: This class is immutable. Any mutating operation such as * {@code put(..)}, {@code putAll(..)} and others will throw * {@link UnsupportedOperationException}. *

Subclasses do have access to the raw headers, however, via {@link #getRawHeaders()}. - *

- * One way to create message headers is to use the + * + *

One way to create message headers is to use the * {@link org.springframework.messaging.support.MessageBuilder MessageBuilder}: *

  * MessageBuilder.withPayload("foo").setHeader("key1", "value1").setHeader("key2", "value2");
  * 
+ * * A second option is to create {@link org.springframework.messaging.support.GenericMessage} * passing a payload as {@link Object} and headers as a {@link Map java.util.Map}: *
@@ -56,6 +57,7 @@ import org.springframework.util.IdGenerator;
  * headers.put("key2", "value2");
  * new GenericMessage("foo", headers);
  * 
+ * * A third option is to use {@link org.springframework.messaging.support.MessageHeaderAccessor} * or one of its sub-classes to create specific categories of headers. * @@ -101,7 +103,6 @@ public class MessageHeaders implements Map, Serializable { /** * Construct a {@link MessageHeaders} with the given headers. An {@link #ID} and * {@link #TIMESTAMP} headers will also be added, overriding any existing values. - * * @param headers a map with headers to add */ public MessageHeaders(Map headers) { @@ -110,14 +111,12 @@ public class MessageHeaders implements Map, Serializable { /** * Constructor providing control over the ID and TIMESTAMP header values. - * * @param headers a map with headers to add * @param id the {@link #ID} header value * @param timestamp the {@link #TIMESTAMP} header value */ protected MessageHeaders(Map headers, UUID id, Long timestamp) { - - this.headers = (headers != null) ? new HashMap(headers) : new HashMap(); + this.headers = (headers != null ? new HashMap(headers) : new HashMap()); if (id == null) { this.headers.put(ID, getIdGenerator().generateId()); @@ -146,7 +145,7 @@ public class MessageHeaders implements Map, Serializable { } protected static IdGenerator getIdGenerator() { - return ((idGenerator != null) ? idGenerator : defaultIdGenerator); + return (idGenerator != null ? idGenerator : defaultIdGenerator); } public UUID getId() { @@ -179,20 +178,14 @@ public class MessageHeaders implements Map, Serializable { } @Override - public int hashCode() { - return this.headers.hashCode(); + public boolean equals(Object other) { + return (this == other || + (other instanceof MessageHeaders && this.headers.equals(((MessageHeaders) other).headers))); } @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object != null && object instanceof MessageHeaders) { - MessageHeaders other = (MessageHeaders) object; - return this.headers.equals(other.headers); - } - return false; + public int hashCode() { + return this.headers.hashCode(); } @Override @@ -200,9 +193,8 @@ public class MessageHeaders implements Map, Serializable { return this.headers.toString(); } - /* - * Map implementation - */ + + // Map implementation public boolean containsKey(Object key) { return this.headers.containsKey(key); @@ -236,7 +228,8 @@ public class MessageHeaders implements Map, Serializable { return Collections.unmodifiableCollection(this.headers.values()); } - // Unsupported operations + + // Unsupported Map operations /** * Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}. @@ -266,6 +259,7 @@ public class MessageHeaders implements Map, Serializable { throw new UnsupportedOperationException("MessageHeaders is immutable"); } + // Serialization methods private void writeObject(ObjectOutputStream out) throws IOException { @@ -277,7 +271,7 @@ public class MessageHeaders implements Map, Serializable { } for (String key : keysToRemove) { if (logger.isInfoEnabled()) { - logger.info("removing non-serializable header: " + key); + logger.info("Removing non-serializable header: " + key); } this.headers.remove(key); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/GenericMessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/GenericMessageConverter.java index fcd38a2981..f9b5f4427a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/GenericMessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/GenericMessageConverter.java @@ -18,8 +18,10 @@ package org.springframework.messaging.converter; import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.messaging.Message; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * An extension of the {@link SimpleMessageConverter} that uses a @@ -37,26 +39,39 @@ public class GenericMessageConverter extends SimpleMessageConverter { private final ConversionService conversionService; + /** - * Create a new instance with the {@link ConversionService} to use. + * Create a new instance with a default {@link ConversionService}. + */ + public GenericMessageConverter() { + this.conversionService = new DefaultConversionService(); + } + + /** + * Create a new instance with the given {@link ConversionService}. */ public GenericMessageConverter(ConversionService conversionService) { Assert.notNull(conversionService, "ConversionService must not be null"); this.conversionService = conversionService; } + @Override public Object fromMessage(Message message, Class targetClass) { Object payload = message.getPayload(); - if (conversionService.canConvert(payload.getClass(), targetClass)) { + if (targetClass == null) { + return payload; + } + if (payload != null && this.conversionService.canConvert(payload.getClass(), targetClass)) { try { - return conversionService.convert(payload, targetClass); + return this.conversionService.convert(payload, targetClass); } - catch (ConversionException e) { - throw new MessageConversionException(message, "Failed to convert message payload '" - + payload + "' to '" + targetClass.getName() + "'", e); + catch (ConversionException ex) { + throw new MessageConversionException(message, "Failed to convert message payload '" + + payload + "' to '" + targetClass.getName() + "'", ex); } } - return null; + return (ClassUtils.isAssignableValue(targetClass, payload) ? payload : null); } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/MessageConverter.java index 89b504995f..89fc91d781 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/MessageConverter.java @@ -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. @@ -38,7 +38,7 @@ public interface MessageConverter { * conversion, it should return {@code null}. * @param message the input message * @param targetClass the target class for the conversion - * @return the result of the conversion or {@code null} if the converter cannot + * @return the result of the conversion, or {@code null} if the converter cannot * perform the conversion */ Object fromMessage(Message message, Class targetClass); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/SimpleMessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/SimpleMessageConverter.java index 59cbf65aea..10e7649dfe 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/SimpleMessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/SimpleMessageConverter.java @@ -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. @@ -40,7 +40,7 @@ public class SimpleMessageConverter implements MessageConverter { if (targetClass == null) { return payload; } - return ClassUtils.isAssignableValue(targetClass, payload) ? payload : null; + return (ClassUtils.isAssignableValue(targetClass, payload) ? payload : null); } @Override diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributes.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributes.java index ef45f1e2f0..f0368476fe 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributes.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributes.java @@ -13,17 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.messaging.simp; +import java.util.Map; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import java.util.Map; - /** * A wrapper class for access to attributes associated with a SiMP session * (e.g. WebSocket session). @@ -62,24 +64,6 @@ public class SimpAttributes { this.attributes = attributes; } - /** - * Extract the SiMP session attributes from the given message, wrap them in - * a {@link SimpAttributes} instance. - * @param message the message to extract session attributes from - */ - public static SimpAttributes fromMessage(Message message) { - Assert.notNull(message); - MessageHeaders headers = message.getHeaders(); - String sessionId = SimpMessageHeaderAccessor.getSessionId(headers); - Map sessionAttributes = SimpMessageHeaderAccessor.getSessionAttributes(headers); - if (sessionId == null) { - throw new IllegalStateException("No session id in " + message); - } - if (sessionAttributes == null) { - throw new IllegalStateException("No session attributes in " + message); - } - return new SimpAttributes(sessionId, sessionAttributes); - } /** * Return the value for the attribute of the given name, if any. @@ -193,4 +177,24 @@ public class SimpAttributes { } } + + /** + * Extract the SiMP session attributes from the given message and + * wrap them in a {@link SimpAttributes} instance. + * @param message the message to extract session attributes from + */ + public static SimpAttributes fromMessage(Message message) { + Assert.notNull(message, "Message must not be null"); + MessageHeaders headers = message.getHeaders(); + String sessionId = SimpMessageHeaderAccessor.getSessionId(headers); + Map sessionAttributes = SimpMessageHeaderAccessor.getSessionAttributes(headers); + if (sessionId == null) { + throw new IllegalStateException("No session id in " + message); + } + if (sessionAttributes == null) { + throw new IllegalStateException("No session attributes in " + message); + } + return new SimpAttributes(sessionId, sessionAttributes); + } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributesContextHolder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributesContextHolder.java index 659f1143ca..4a2aafd1ad 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributesContextHolder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpAttributesContextHolder.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.messaging.simp; import org.springframework.core.NamedThreadLocal; @@ -41,7 +42,6 @@ public abstract class SimpAttributesContextHolder { /** * Bind the given SimpAttributes to the current thread, - * * @param attributes the RequestAttributes to expose */ public static void setAttributes(SimpAttributes attributes) { @@ -56,7 +56,6 @@ public abstract class SimpAttributesContextHolder { /** * Extract the SiMP session attributes from the given message, wrap them in * a {@link SimpAttributes} instance and bind it to the current thread, - * * @param message the message to extract session attributes from */ public static void setAttributesFromMessage(Message message) { @@ -65,7 +64,6 @@ public abstract class SimpAttributesContextHolder { /** * Return the SimpAttributes currently bound to the thread. - * * @return the attributes or {@code null} if not bound */ public static SimpAttributes getAttributes() { @@ -75,7 +73,6 @@ public abstract class SimpAttributesContextHolder { /** * Return the SimpAttributes currently bound to the thread or raise an * {@link java.lang.IllegalStateException} if none are bound.. - * * @return the attributes, never {@code null} * @throws java.lang.IllegalStateException if attributes are not bound */ diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessageHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessageHeaderAccessor.java index 8a437e9194..067cb960b5 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessageHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessageHeaderAccessor.java @@ -20,7 +20,6 @@ import java.security.Principal; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; import org.springframework.messaging.Message; import org.springframework.messaging.support.IdTimestampMessageHeaderInitializer; import org.springframework.messaging.support.MessageHeaderAccessor; @@ -68,7 +67,6 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { /** * For internal use. - * *

The original destination used by a client when subscribing. Such a * destination may have been modified (e.g. user destinations) on the server * side. This header provides a hint so messages sent to clients may have @@ -98,30 +96,6 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { } - /** - * Create an instance with - * {@link org.springframework.messaging.simp.SimpMessageType} {@code MESSAGE}. - */ - public static SimpMessageHeaderAccessor create() { - return new SimpMessageHeaderAccessor(SimpMessageType.MESSAGE, null); - } - - /** - * Create an instance with the given - * {@link org.springframework.messaging.simp.SimpMessageType}. - */ - public static SimpMessageHeaderAccessor create(SimpMessageType messageType) { - return new SimpMessageHeaderAccessor(messageType, null); - } - - /** - * Create an instance from the payload and headers of the given Message. - */ - public static SimpMessageHeaderAccessor wrap(Message message) { - return new SimpMessageHeaderAccessor(message); - } - - @Override protected MessageHeaderAccessor createAccessor(Message message) { return wrap(message); @@ -133,57 +107,27 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { } } - /** - * @return the message type - */ public SimpMessageType getMessageType() { return (SimpMessageType) getHeader(MESSAGE_TYPE_HEADER); } - /** - * A static alternative for access to the message type. - */ - public static SimpMessageType getMessageType(Map headers) { - return (SimpMessageType) headers.get(MESSAGE_TYPE_HEADER); - } - public void setDestination(String destination) { Assert.notNull(destination, "Destination must not be null"); setHeader(DESTINATION_HEADER, destination); } - /** - * @return the message destination - */ public String getDestination() { return (String) getHeader(DESTINATION_HEADER); } - /** - * A static alternative for access to the destination header. - */ - public static String getDestination(Map headers) { - return (String) headers.get(DESTINATION_HEADER); - } - public void setSubscriptionId(String subscriptionId) { setHeader(SUBSCRIPTION_ID_HEADER, subscriptionId); } - /** - * @return the subscription id (if any) of the message - */ public String getSubscriptionId() { return (String) getHeader(SUBSCRIPTION_ID_HEADER); } - /** - * A static alternative for access to the subscription id header. - */ - public static String getSubscriptionId(Map headers) { - return (String) headers.get(SUBSCRIPTION_ID_HEADER); - } - public void setSessionId(String sessionId) { setHeader(SESSION_ID_HEADER, sessionId); } @@ -195,13 +139,6 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { return (String) getHeader(SESSION_ID_HEADER); } - /** - * A static alternative for access to the session id header. - */ - public static String getSessionId(Map headers) { - return (String) headers.get(SESSION_ID_HEADER); - } - /** * A static alternative for access to the session attributes header. */ @@ -210,39 +147,24 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { } /** - * @return attributes associated with the current session. + * Return the attributes associated with the current session. */ @SuppressWarnings("unchecked") public Map getSessionAttributes() { return (Map) getHeader(SESSION_ATTRIBUTES); } - /** - * A static alternative for access to the session attributes header. - */ - @SuppressWarnings("unchecked") - public static Map getSessionAttributes(Map headers) { - return (Map) headers.get(SESSION_ATTRIBUTES); - } - public void setUser(Principal principal) { setHeader(USER_HEADER, principal); } /** - * @return the user associated with the current session. + * Return the user associated with the current session. */ public Principal getUser() { return (Principal) getHeader(USER_HEADER); } - /** - * A static alternative for access to the user header. - */ - public static Principal getUser(Map headers) { - return (Principal) headers.get(USER_HEADER); - } - @Override public String getShortLogMessage(Object payload) { if (getMessageType() == null) { @@ -289,4 +211,55 @@ public class SimpMessageHeaderAccessor extends NativeMessageHeaderAccessor { return sb; } + + // Static factory methods and accessors + + /** + * Create an instance with + * {@link org.springframework.messaging.simp.SimpMessageType} {@code MESSAGE}. + */ + public static SimpMessageHeaderAccessor create() { + return new SimpMessageHeaderAccessor(SimpMessageType.MESSAGE, null); + } + + /** + * Create an instance with the given + * {@link org.springframework.messaging.simp.SimpMessageType}. + */ + public static SimpMessageHeaderAccessor create(SimpMessageType messageType) { + return new SimpMessageHeaderAccessor(messageType, null); + } + + /** + * Create an instance from the payload and headers of the given Message. + */ + public static SimpMessageHeaderAccessor wrap(Message message) { + return new SimpMessageHeaderAccessor(message); + } + + public static SimpMessageType getMessageType(Map headers) { + return (SimpMessageType) headers.get(MESSAGE_TYPE_HEADER); + } + + public static String getDestination(Map headers) { + return (String) headers.get(DESTINATION_HEADER); + } + + public static String getSubscriptionId(Map headers) { + return (String) headers.get(SUBSCRIPTION_ID_HEADER); + } + + public static String getSessionId(Map headers) { + return (String) headers.get(SESSION_ID_HEADER); + } + + @SuppressWarnings("unchecked") + public static Map getSessionAttributes(Map headers) { + return (Map) headers.get(SESSION_ATTRIBUTES); + } + + public static Principal getUser(Map headers) { + return (Principal) headers.get(USER_HEADER); + } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpSessionScope.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpSessionScope.java index 7c919317c0..0e3c0f04a9 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpSessionScope.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpSessionScope.java @@ -24,15 +24,13 @@ import org.springframework.beans.factory.config.Scope; * (e.g. WebSocket session). * *

Relies on a thread-bound {@link SimpAttributes} instance exported by - * {@link org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler - * SimpAnnotationMethodMessageHandler}. + * {@link org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler}. * * @author Rossen Stoyanchev * @since 4.1 */ public class SimpSessionScope implements Scope { - @Override public Object get(String name, ObjectFactory objectFactory) { SimpAttributes simpAttributes = SimpAttributesContextHolder.currentAttributes(); @@ -78,4 +76,5 @@ public class SimpSessionScope implements Scope { public String getConversationId() { return SimpAttributesContextHolder.currentAttributes().getSessionId(); } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java index a45731fd79..e8724c3566 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java @@ -131,6 +131,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { super(SimpMessageType.HEARTBEAT, null); } + void updateSimpMessageHeadersFromStompHeaders() { if (getNativeHeaders() == null) { return; @@ -171,35 +172,6 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { trySetStompHeaderForSubscriptionId(); } - /** - * Create an instance for the given STOMP command. - */ - public static StompHeaderAccessor create(StompCommand command) { - return new StompHeaderAccessor(command, null); - } - - /** - * Create an instance for the given STOMP command and headers. - */ - public static StompHeaderAccessor create(StompCommand command, Map> headers) { - return new StompHeaderAccessor(command, headers); - } - - /** - * Create headers for a heartbeat. While a STOMP heartbeat frame does not - * have headers, a session id is needed for processing purposes at a minimum. - */ - public static StompHeaderAccessor createForHeartbeat() { - return new StompHeaderAccessor(); - } - - /** - * Create an instance from the payload and headers of the given Message. - */ - public static StompHeaderAccessor wrap(Message message) { - return new StompHeaderAccessor(message); - } - @Override protected MessageHeaderAccessor createAccessor(Message message) { @@ -213,23 +185,18 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } public StompCommand updateStompCommandAsClientMessage() { - Assert.state(SimpMessageType.MESSAGE.equals(getMessageType()), "Unexpected message type " + getMessage()); - if (getCommand() == null) { setHeader(COMMAND_HEADER, StompCommand.SEND); } else if (!getCommand().equals(StompCommand.SEND)) { throw new IllegalStateException("Unexpected STOMP command " + getCommand()); } - return getCommand(); } public void updateStompCommandAsServerMessage() { - Assert.state(SimpMessageType.MESSAGE.equals(getMessageType()), "Unexpected message type " + getMessage()); - StompCommand command = getCommand(); if ((command == null) || StompCommand.SEND.equals(command)) { setHeader(COMMAND_HEADER, StompCommand.MESSAGE); @@ -237,9 +204,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { else if (!StompCommand.MESSAGE.equals(command)) { throw new IllegalStateException("Unexpected STOMP command " + command); } - trySetStompHeaderForSubscriptionId(); - if (getMessageId() == null) { String messageId = getSessionId() + "-" + messageIdCounter.getAndIncrement(); setNativeHeader(STOMP_MESSAGE_ID_HEADER, messageId); @@ -247,22 +212,15 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } /** - * @return the STOMP command, or {@code null} if not yet set. + * Return the STOMP command, or {@code null} if not yet set. */ public StompCommand getCommand() { return (StompCommand) getHeader(COMMAND_HEADER); } - /** - * A static alternative for access to the STOMP command. - */ - public static StompCommand getCommand(Map headers) { - return (StompCommand) headers.get(COMMAND_HEADER); - } - public Set getAcceptVersion() { String rawValue = getFirstNativeHeader(STOMP_ACCEPT_VERSION_HEADER); - return (rawValue != null) ? StringUtils.commaDelimitedListToSet(rawValue) : Collections.emptySet(); + return (rawValue != null ? StringUtils.commaDelimitedListToSet(rawValue) : Collections.emptySet()); } public boolean isHeartbeat() { @@ -329,15 +287,6 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { return null; } - public static Integer getContentLength(Map> nativeHeaders) { - if (nativeHeaders.containsKey(STOMP_CONTENT_LENGTH_HEADER)) { - List values = nativeHeaders.get(STOMP_CONTENT_LENGTH_HEADER); - String value = (values != null ? values.get(0) : null); - return Integer.valueOf(value); - } - return null; - } - public void setContentLength(int contentLength) { setNativeHeader(STOMP_CONTENT_LENGTH_HEADER, String.valueOf(contentLength)); } @@ -370,7 +319,6 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { return getFirstNativeHeader(STOMP_LOGIN_HEADER); } - public void setPasscode(String passcode) { setNativeHeader(STOMP_PASSCODE_HEADER, passcode); protectPasscode(); @@ -385,21 +333,13 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } /** - * @return the passcode header value or {@code null}. + * Return the passcode header value, or {@code null} if not set. */ public String getPasscode() { StompPasscode credentials = (StompPasscode) getHeader(CREDENTIALS_HEADER); return (credentials != null ? credentials.passcode : null); } - /** - * A static alternative for access to the passcode header. - */ - public static String getPasscode(Map headers) { - StompPasscode credentials = (StompPasscode) headers.get(CREDENTIALS_HEADER); - return (credentials != null ? credentials.passcode : null); - } - public void setReceiptId(String receiptId) { setNativeHeader(STOMP_RECEIPT_ID_HEADER, receiptId); } @@ -440,6 +380,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { setNativeHeader(STOMP_VERSION_HEADER, version); } + // Logging related @Override @@ -506,6 +447,62 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } + // Static factory methods and accessors + + /** + * Create an instance for the given STOMP command. + */ + public static StompHeaderAccessor create(StompCommand command) { + return new StompHeaderAccessor(command, null); + } + + /** + * Create an instance for the given STOMP command and headers. + */ + public static StompHeaderAccessor create(StompCommand command, Map> headers) { + return new StompHeaderAccessor(command, headers); + } + + /** + * Create headers for a heartbeat. While a STOMP heartbeat frame does not + * have headers, a session id is needed for processing purposes at a minimum. + */ + public static StompHeaderAccessor createForHeartbeat() { + return new StompHeaderAccessor(); + } + + /** + * Create an instance from the payload and headers of the given Message. + */ + public static StompHeaderAccessor wrap(Message message) { + return new StompHeaderAccessor(message); + } + + /** + * Return the STOMP command from the given headers, or {@code null} if not set. + */ + public static StompCommand getCommand(Map headers) { + return (StompCommand) headers.get(COMMAND_HEADER); + } + + /** + * Return the passcode header value, or {@code null} if not set. + */ + public static String getPasscode(Map headers) { + StompPasscode credentials = (StompPasscode) headers.get(CREDENTIALS_HEADER); + return (credentials != null ? credentials.passcode : null); + } + + public static Integer getContentLength(Map> nativeHeaders) { + if (nativeHeaders.containsKey(STOMP_CONTENT_LENGTH_HEADER)) { + List values = nativeHeaders.get(STOMP_CONTENT_LENGTH_HEADER); + String value = (values != null ? values.get(0) : null); + return Integer.valueOf(value); + } + return null; + } + + private static class StompPasscode { private final String passcode; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java b/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java index c256616abe..c5780c19d6 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java @@ -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. @@ -16,11 +16,11 @@ package org.springframework.messaging.support; +import java.util.UUID; + import org.springframework.messaging.MessageHeaders; import org.springframework.util.IdGenerator; -import java.util.UUID; - /** * A {@link org.springframework.messaging.support.MessageHeaderInitializer MessageHeaderInitializer} * to customize the strategy for ID and TIMESTAMP message header generation. @@ -38,10 +38,8 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial /** * Configure the IdGenerator strategy to initialize {@code MessageHeaderAccessor} * instances with. - * *

By default this property is set to {@code null} in which case the default * IdGenerator of {@link org.springframework.messaging.MessageHeaders} is used. - * *

To have no id's generated at all, see {@@link #setDisableIdGeneration()}. */ public void setIdGenerator(IdGenerator idGenerator) { @@ -49,17 +47,15 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial } /** - * A shortcut for calling - * {@link #setIdGenerator(org.springframework.util.IdGenerator)} with an - * id generation strategy to - * + * A shortcut for calling {@link #setIdGenerator(org.springframework.util.IdGenerator)} + * with an id generation strategy to disable id generation completely. */ public void setDisableIdGeneration() { this.idGenerator = ID_VALUE_NONE_GENERATOR; } /** - * @return the configured {@code IdGenerator} if any. + * Return the configured {@code IdGenerator}, if any. */ public IdGenerator getIdGenerator() { return this.idGenerator; @@ -69,7 +65,6 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial * Whether to enable the automatic addition of the * {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header on * {@code MessageHeaderAccessor} instances being initialized. - * *

By default this property is set to false. */ public void setEnableTimestamp(boolean enableTimestamp) { @@ -77,12 +72,13 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial } /** - * @return Whether the timestamp header is enabled or not. + * Return whether the timestamp header is enabled or not. */ public boolean isEnableTimestamp() { return this.enableTimestamp; } + @Override public void initHeaders(MessageHeaderAccessor headerAccessor) { headerAccessor.setIdGenerator(getIdGenerator()); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java index deee2c24d5..39524581c1 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java @@ -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. @@ -24,14 +24,13 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.util.Assert; /** - * A builder for creating a {@link GenericMessage} (or {@link ErrorMessage} if - * the payload is of type {@link Throwable}). + * A builder for creating a {@link GenericMessage} + * (or {@link ErrorMessage} if the payload is of type {@link Throwable}). * * @author Arjen Poutsma * @author Mark Fisher * @author Rossen Stoyanchev * @since 4.0 - * * @see GenericMessage * @see ErrorMessage */ @@ -59,52 +58,9 @@ public final class MessageBuilder { this.originalMessage = null; } - /** - * Create a builder for a new {@link Message} instance pre-populated with all of the - * headers copied from the provided message. The payload of the provided Message will - * also be used as the payload for the new message. - * - * @param message the Message from which the payload and all headers will be copied - */ - public static MessageBuilder fromMessage(Message message) { - return new MessageBuilder(message); - } - - /** - * Create a new builder for a message with the given payload. - * @param payload the payload - */ - public static MessageBuilder withPayload(T payload) { - return new MessageBuilder(payload, new MessageHeaderAccessor()); - } - - /** - * A shortcut factory method for creating a message with the given payload - * and {@code MessageHeaders}. - * - *

Note: the given {@code MessageHeaders} instance is used - * directly in the new message, i.e. it is not copied. - * - * @param payload the payload to use, never {@code null} - * @param messageHeaders the headers to use, never {@code null} - * @return the created message - * @since 4.1 - */ - @SuppressWarnings("unchecked") - public static Message createMessage(T payload, MessageHeaders messageHeaders) { - Assert.notNull(payload, "'payload' must not be null"); - Assert.notNull(messageHeaders, "'messageHeaders' must not be null"); - if (payload instanceof Throwable) { - return (Message) new ErrorMessage((Throwable) payload, messageHeaders); - } - else { - return new GenericMessage(payload, messageHeaders); - } - } /** * Set the message headers to use by providing a {@code MessageHeaderAccessor}. - * * @param accessor the headers to use */ public MessageBuilder setHeaders(MessageHeaderAccessor accessor) { @@ -189,11 +145,9 @@ public final class MessageBuilder { @SuppressWarnings("unchecked") public Message build() { - if (this.originalMessage != null && !this.headerAccessor.isModified()) { return this.originalMessage; } - if (this.payload instanceof Throwable) { return (Message) new ErrorMessage((Throwable) this.payload, this.headerAccessor.toMap()); } @@ -202,4 +156,45 @@ public final class MessageBuilder { } } + + /** + * Create a builder for a new {@link Message} instance pre-populated with all of the + * headers copied from the provided message. The payload of the provided Message will + * also be used as the payload for the new message. + * @param message the Message from which the payload and all headers will be copied + */ + public static MessageBuilder fromMessage(Message message) { + return new MessageBuilder(message); + } + + /** + * Create a new builder for a message with the given payload. + * @param payload the payload + */ + public static MessageBuilder withPayload(T payload) { + return new MessageBuilder(payload, new MessageHeaderAccessor()); + } + + /** + * A shortcut factory method for creating a message with the given payload + * and {@code MessageHeaders}. + *

Note: the given {@code MessageHeaders} instance is used + * directly in the new message, i.e. it is not copied. + * @param payload the payload to use, never {@code null} + * @param messageHeaders the headers to use, never {@code null} + * @return the created message + * @since 4.1 + */ + @SuppressWarnings("unchecked") + public static Message createMessage(T payload, MessageHeaders messageHeaders) { + Assert.notNull(payload, "'payload' must not be null"); + Assert.notNull(messageHeaders, "'messageHeaders' must not be null"); + if (payload instanceof Throwable) { + return (Message) new ErrorMessage((Throwable) payload, messageHeaders); + } + else { + return new GenericMessage(payload, messageHeaders); + } + } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderInitializer.java b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderInitializer.java index e046276329..b81be5f5c7 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderInitializer.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderInitializer.java @@ -17,8 +17,7 @@ package org.springframework.messaging.support; /** - * Callback interface for initializing a - * {@link org.springframework.messaging.support.MessageHeaderAccessor MessageHeaderAccessor}. + * Callback interface for initializing a {@link MessageHeaderAccessor}. * * @author Rossen Stoyanchev * @since 4.1 @@ -27,8 +26,7 @@ public interface MessageHeaderInitializer { /** * Initialize the given {@code MessageHeaderAccessor}. - * - * @param headerAccessor the instance to initialize + * @param headerAccessor the MessageHeaderAccessor to initialize */ void initHeaders(MessageHeaderAccessor headerAccessor); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/core/MessageReceivingTemplateTests.java b/spring-messaging/src/test/java/org/springframework/messaging/core/MessageReceivingTemplateTests.java index b15bc82bda..36b6a3854a 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/core/MessageReceivingTemplateTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/core/MessageReceivingTemplateTests.java @@ -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. @@ -16,28 +16,26 @@ package org.springframework.messaging.core; +import java.io.Writer; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.core.convert.ConversionFailedException; -import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.messaging.Message; import org.springframework.messaging.converter.GenericMessageConverter; import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.support.GenericMessage; -import static org.hamcrest.CoreMatchers.isA; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; -import java.io.Writer; - /** * Unit tests for receiving operations in {@link AbstractMessagingTemplate}. * * @author Rossen Stoyanchev - * * @see MessageRequestReplyTemplateTests */ public class MessageReceivingTemplateTests { @@ -104,7 +102,7 @@ public class MessageReceivingTemplateTests { public void receiveAndConvertFailed() { Message expected = new GenericMessage("not a number test"); this.template.setReceiveMessage(expected); - this.template.setMessageConverter(new GenericMessageConverter(new DefaultConversionService())); + this.template.setMessageConverter(new GenericMessageConverter()); thrown.expect(MessageConversionException.class); thrown.expectCause(isA(ConversionFailedException.class)); @@ -116,13 +114,13 @@ public class MessageReceivingTemplateTests { Message expected = new GenericMessage("payload"); this.template.setDefaultDestination("home"); this.template.setReceiveMessage(expected); - this.template.setMessageConverter(new GenericMessageConverter(new DefaultConversionService())); + this.template.setMessageConverter(new GenericMessageConverter()); try { this.template.receiveAndConvert(Writer.class); } - catch (MessageConversionException e) { - assertTrue("Invalid exception message '"+e.getMessage()+"'", e.getMessage().contains("payload")); - assertSame(expected, e.getFailedMessage()); + catch (MessageConversionException ex) { + assertTrue("Invalid exception message '" + ex.getMessage() + "'", ex.getMessage().contains("payload")); + assertSame(expected, ex.getFailedMessage()); } } @@ -134,7 +132,6 @@ public class MessageReceivingTemplateTests { private Message receiveMessage; - private void setReceiveMessage(Message receiveMessage) { this.receiveMessage = receiveMessage; } @@ -154,7 +151,6 @@ public class MessageReceivingTemplateTests { this.destination = destination; return null; } - } }