Skip to content

Commit

Permalink
Update Javadoc, add tests and polish spring-messaging
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoyanchev committed Dec 6, 2013
1 parent 3e0b0f1 commit 947f3d4
Show file tree
Hide file tree
Showing 41 changed files with 1,533 additions and 254 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@
* @author Mark Fisher
* @author Arjen Poutsma
* @since 4.0
*
* @see org.springframework.messaging.support.MessageBuilder
*/
public interface Message<T> {

/**
* Returns message headers for the message (never {@code null}).
* Return message headers for the message, never {@code null}.
*/
MessageHeaders getHeaders();

/**
* Returns the message payload.
* Return the message payload.
*/
T getPayload();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.springframework.messaging;

/**
* Base channel interface defining common behavior for sending messages.
* Defines methods for sending messages.
*
* @author Mark Fisher
* @since 4.0
Expand All @@ -31,24 +31,27 @@ public interface MessageChannel {


/**
* Send a {@link Message} to this channel. May throw a RuntimeException for
* non-recoverable errors. Otherwise, if the Message cannot be sent for a non-fatal
* reason this method will return 'false', and if the Message is sent successfully, it
* will return 'true'.
* <p>Depending on the implementation, this method may block indefinitely. To provide a
* maximum wait time, use {@link #send(Message, long)}.
* @param message the {@link Message} to send
* @return whether or not the Message has been sent successfully
* Send a {@link Message} to this channel. If the message is sent successfully,
* the method returns {@code true}. If the message cannot be sent due to a
* non-fatal reason, the method returns {@code false}. The method may also
* throw a RuntimeException in case of non-recoverable errors.
* <p>
* This method may block indefinitely, depending on the implementation.
* To provide a maximum wait time, use {@link #send(Message, long)}.
*
* @param message the message to send
* @return whether or not the message was sent
*/
boolean send(Message<?> message);

/**
* Send a message, blocking until either the message is accepted or the specified
* timeout period elapses.
* @param message the {@link Message} to send
* @param timeout the timeout in milliseconds or #INDEFINITE_TIMEOUT
* @return {@code true} if the message is sent successfully, {@code false} if the
* specified timeout period elapses or the send is interrupted
* Send a message, blocking until either the message is accepted or the
* specified timeout period elapses.
*
* @param message the message to send
* @param timeout the timeout in milliseconds or {@link #INDEFINITE_TIMEOUT}
* @return {@code true} if the message is sent, {@code false} if not including
* a timeout of an interrupt of the send
*/
boolean send(Message<?> message, long timeout);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@SuppressWarnings("serial")
public class MessageDeliveryException extends MessagingException {


public MessageDeliveryException(String description) {
super(description);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.springframework.messaging;

/**
* Base interface for any component that handles Messages.
* Contract for handling a {@link Message}.
*
* @author Mark Fisher
* @author Iwein Fuld
Expand All @@ -26,17 +26,9 @@
public interface MessageHandler {

/**
* Handles the message if possible. If the handler cannot deal with the
* message this will result in a {@code MessageRejectedException} e.g.
* in case of a Selective Consumer. When a consumer tries to handle a
* message, but fails to do so, a {@code MessageHandlingException} is
* thrown. In the last case it is recommended to treat the message as tainted
* and go into an error scenario.
* <p>When the handling results in a failure of another message being sent
* (e.g. a "reply" message), that failure will trigger a
* {@code MessageDeliveryException}.
* Handle the given message.
*
* @param message the message to be handled
* reply related to the handling of the message
*/
void handleMessage(Message<?> message) throws MessagingException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@
* limitations under the License.
*/

package org.springframework.messaging.handler.annotation.support;
package org.springframework.messaging;

import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;

/**
* Thrown when the handling of a message results in an unrecoverable exception.
* Exception that indicates an error occurred during message handling.
*
* @author Rossen Stoyanchev
* @author Mark Fisher
* @since 4.0
*/
public class MessageHandlingException extends MessagingException {

private static final long serialVersionUID = 690969923668400297L;


public MessageHandlingException(Message<?> message, String description, Throwable cause) {
super(message, description, cause);
}

public MessageHandlingException(Message<?> message, String description) {
super(message, description);
}

public MessageHandlingException(Message<?> message, String description, Throwable cause) {
super(message, description, cause);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,34 @@

/**
* The headers for a {@link Message}
*
* <p><b>IMPORTANT</b>: This class is immutable. Any mutating operation
* (e.g., put(..), putAll(..) etc.) will throw {@link UnsupportedOperationException}.
*
* <p>To create MessageHeaders instance use fluent
* {@link org.springframework.messaging.support.MessageBuilder MessageBuilder} API
* <p>
* <b>IMPORTANT</b>: This class is immutable. Any mutating operation such as
* {@code put(..)}, {@code putAll(..)} and others will throw
* {@link UnsupportedOperationException}.
* <p>
* One way to create message headers is to use the
* {@link org.springframework.messaging.support.MessageBuilder MessageBuilder}:
* <pre class="code">
* MessageBuilder.withPayload("foo").setHeader("key1", "value1").setHeader("key2", "value2");
* </pre>
* or create an instance of GenericMessage passing payload as {@link Object} and headers as a regular {@link Map}
* 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}:
* <pre class="code">
* Map headers = new HashMap();
* headers.put("key1", "value1");
* headers.put("key2", "value2");
* new GenericMessage("foo", headers);
* </pre>
* A third option is to use {@link org.springframework.messaging.support.MessageHeaderAccessor}
* or one of its sub-classes to create specific categories of headers.
*
* @author Arjen Poutsma
* @author Mark Fisher
* @author Gary Russell
* @author Rossen Stoyanchev
* @since 4.0
*
* @see org.springframework.messaging.support.MessageBuilder
* @see org.springframework.messaging.support.MessageHeaderAccessor
*/
public final class MessageHeaders implements Map<String, Object>, Serializable {

Expand Down Expand Up @@ -124,8 +129,8 @@ public <T> T get(Object key, Class<T> type) {
return null;
}
if (!type.isAssignableFrom(value.getClass())) {
throw new IllegalArgumentException("Incorrect type specified for header '" + key + "'. Expected [" + type
+ "] but actual type is [" + value.getClass() + "]");
throw new IllegalArgumentException("Incorrect type specified for header '" +
key + "'. Expected [" + type + "] but actual type is [" + value.getClass() + "]");
}
return (T) value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
package org.springframework.messaging;

/**
* Interface for Message Channels from which Messages may be actively received through
* polling.
* A {@link MessageChannel} from which messages may be actively received through polling.
*
* @author Mark Fisher
* @since 4.0
Expand All @@ -27,17 +26,18 @@ public interface PollableChannel extends MessageChannel {

/**
* Receive a message from this channel, blocking indefinitely if necessary.
*
* @return the next available {@link Message} or {@code null} if interrupted
*/
Message<?> receive();

/**
* Receive a message from this channel, blocking until either a message is available
* or the specified timeout period elapses.
* @param timeout the timeout in milliseconds or
* {@link MessageChannel#INDEFINITE_TIMEOUT}.
*
* @param timeout the timeout in milliseconds or {@link MessageChannel#INDEFINITE_TIMEOUT}.
* @return the next available {@link Message} or {@code null} if the specified timeout
* period elapses or the message reception is interrupted
* period elapses or the message reception is interrupted
*/
Message<?> receive(long timeout);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,28 @@
package org.springframework.messaging;

/**
* Interface for any MessageChannel implementation that accepts subscribers.
* The subscribers must implement the {@link MessageHandler} interface and
* will be invoked when a Message is available.
* A {@link MessageChannel} that maintains a registry of subscribers and invokes
* them to handle messages sent through this channel.
*
* @author Mark Fisher
* @since 4.0
*/
public interface SubscribableChannel extends MessageChannel {


/**
* Register a {@link MessageHandler} as a subscriber to this channel.
* @return {@code true} if the channel was not already subscribed to the specified
* handler
* Register a message handler.
*
* @return {@code true} if the handler was subscribed or {@code false} if it
* was already subscribed.
*/
boolean subscribe(MessageHandler handler);

/**
* Remove a {@link MessageHandler} from the subscribers of this channel.
* @return {@code true} if the channel was previously subscribed to the specified
* handler
* Un-register a message handler.
*
* @return {@code true} if the handler was un-registered, or {@code false}
* if was not registered.
*/
boolean unsubscribe(MessageHandler handler);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,57 @@
import org.springframework.util.Assert;

/**
* Base class for a messaging template that can resolve String-based destinations.
* An extension of {@link AbstractMessagingTemplate} that adds operations for sending
* messages to a resolvable destination name as defined by the following interfaces:
* <ul>
* <li>{@link DestinationResolvingMessageSendingOperations}</li>
* <li>{@link DestinationResolvingMessageReceivingOperations}</li>
* <li>{@link DestinationResolvingMessageRequestReplyOperations}</li>
* </ul>
*
* @author Mark Fisher
* @author Rossen Stoyanchev
* @since 4.0
*/
public abstract class AbstractDestinationResolvingMessagingTemplate<D> extends
AbstractMessagingTemplate<D> implements
public abstract class AbstractDestinationResolvingMessagingTemplate<D> extends AbstractMessagingTemplate<D>
implements
DestinationResolvingMessageSendingOperations<D>,
DestinationResolvingMessageReceivingOperations<D>,
DestinationResolvingMessageRequestReplyOperations<D> {

private volatile DestinationResolver<D> destinationResolver;


/**
* Configure the {@link DestinationResolver} to use to resolve String destination
* names into actual destinations of type {@code <D>}.
* <p>
* This field does not have a default setting. If not configured, methods that
* require resolving a destination name will raise an {@link IllegalArgumentException}.
*
* @param destinationResolver the destination resolver to use
*/
public void setDestinationResolver(DestinationResolver<D> destinationResolver) {
Assert.notNull(destinationResolver, "'destinationResolver' is required");
this.destinationResolver = destinationResolver;
}

/**
* Return the configured destination resolver.
*/
public DestinationResolver<D> getDestinationResolver() {
return this.destinationResolver;
}


@Override
public <P> void send(String destinationName, Message<P> message) {
public void send(String destinationName, Message<?> message) {
D destination = resolveDestination(destinationName);
this.doSend(destination, message);
}

protected final D resolveDestination(String destinationName) {
Assert.notNull(destinationResolver, "destinationResolver is required when passing a name only");
Assert.state(this.destinationResolver != null, "destinationResolver is required to resolve destination names");
return this.destinationResolver.resolveDestination(destinationName);
}

Expand Down Expand Up @@ -79,7 +102,7 @@ public <T> void convertAndSend(String destinationName, T payload, Map<String, Ob
}

@Override
public <P> Message<P> receive(String destinationName) {
public Message<?> receive(String destinationName) {
D destination = resolveDestination(destinationName);
return super.receive(destination);
}
Expand Down
Loading

0 comments on commit 947f3d4

Please sign in to comment.