Polishing
This commit is contained in:
@@ -26,14 +26,14 @@ package org.springframework.messaging;
|
||||
*/
|
||||
public interface Message<T> {
|
||||
|
||||
/**
|
||||
* Return message headers for the message (never {@code null}).
|
||||
*/
|
||||
MessageHeaders getHeaders();
|
||||
|
||||
/**
|
||||
* Return the message payload.
|
||||
*/
|
||||
T getPayload();
|
||||
|
||||
/**
|
||||
* Return message headers for the message (never {@code null} but may be empty).
|
||||
*/
|
||||
MessageHeaders getHeaders();
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ import org.springframework.util.IdGenerator;
|
||||
* </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.
|
||||
* or one of its subclasses to create specific categories of headers.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Mark Fisher
|
||||
@@ -135,6 +135,7 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (this == other ||
|
||||
@@ -193,28 +194,32 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
// Unsupported Map operations
|
||||
|
||||
/**
|
||||
* Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}.
|
||||
* Since MessageHeaders are immutable, the call to this method
|
||||
* will result in {@link UnsupportedOperationException}.
|
||||
*/
|
||||
public Object put(String key, Object value) {
|
||||
throw new UnsupportedOperationException("MessageHeaders is immutable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}.
|
||||
* Since MessageHeaders are immutable, the call to this method
|
||||
* will result in {@link UnsupportedOperationException}.
|
||||
*/
|
||||
public void putAll(Map<? extends String, ? extends Object> t) {
|
||||
public void putAll(Map<? extends String, ? extends Object> map) {
|
||||
throw new UnsupportedOperationException("MessageHeaders is immutable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}.
|
||||
* Since MessageHeaders are immutable, the call to this method
|
||||
* will result in {@link UnsupportedOperationException}.
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
throw new UnsupportedOperationException("MessageHeaders is immutable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}.
|
||||
* Since MessageHeaders are immutable, the call to this method
|
||||
* will result in {@link UnsupportedOperationException}.
|
||||
*/
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException("MessageHeaders is immutable");
|
||||
|
||||
@@ -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,7 +24,6 @@ import java.util.Map;
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 4.0
|
||||
*
|
||||
* @see MessageBuilder
|
||||
*/
|
||||
public class ErrorMessage extends GenericMessage<Throwable> {
|
||||
@@ -34,8 +33,7 @@ public class ErrorMessage extends GenericMessage<Throwable> {
|
||||
|
||||
/**
|
||||
* Create a new message with the given payload.
|
||||
*
|
||||
* @param payload the message payload, never {@code null}
|
||||
* @param payload the message payload (never {@code null})
|
||||
*/
|
||||
public ErrorMessage(Throwable payload) {
|
||||
super(payload);
|
||||
@@ -43,8 +41,7 @@ public class ErrorMessage extends GenericMessage<Throwable> {
|
||||
|
||||
/**
|
||||
* Create a new message with the given payload and headers.
|
||||
*
|
||||
* @param payload the message payload, never {@code null}
|
||||
* @param payload the message payload (never {@code null})
|
||||
* @param headers message headers
|
||||
*/
|
||||
public ErrorMessage(Throwable payload, Map<String, Object> headers) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.util.ObjectUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 4.0
|
||||
*
|
||||
* @see MessageBuilder
|
||||
*/
|
||||
public class GenericMessage<T> implements Message<T>, Serializable {
|
||||
@@ -45,32 +44,47 @@ public class GenericMessage<T> implements Message<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Create a new message with the given payload.
|
||||
*
|
||||
* @param payload the message payload, never {@code null}
|
||||
* @param payload the message payload (never {@code null})
|
||||
*/
|
||||
public GenericMessage(T payload) {
|
||||
this(payload, null);
|
||||
this(payload, new MessageHeaders(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new message with the given payload and headers.
|
||||
*
|
||||
* @param payload the message payload, never {@code null}
|
||||
* @param payload the message payload (never {@code null})
|
||||
* @param headers message headers
|
||||
*/
|
||||
public GenericMessage(T payload, Map<String, Object> headers) {
|
||||
Assert.notNull(payload, "payload must not be null");
|
||||
Assert.notNull(payload, "Payload must not be null");
|
||||
this.headers = new MessageHeaders(headers);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
|
||||
public T getPayload() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
public MessageHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public T getPayload() {
|
||||
return this.payload;
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof GenericMessage<?>) {
|
||||
GenericMessage<?> other = (GenericMessage<?>) obj;
|
||||
return (ObjectUtils.nullSafeEquals(this.headers.getId(), other.headers.getId()) &&
|
||||
this.headers.equals(other.headers) && this.payload.equals(other.payload));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (this.headers.hashCode() * 23 + ObjectUtils.nullSafeHashCode(this.payload));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -86,20 +100,4 @@ public class GenericMessage<T> implements Message<T>, Serializable {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.headers.hashCode() * 23 + ObjectUtils.nullSafeHashCode(this.payload);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof GenericMessage<?>) {
|
||||
GenericMessage<?> other = (GenericMessage<?>) obj;
|
||||
return (this.headers.getId().equals(other.headers.getId()) &&
|
||||
this.headers.equals(other.headers) && this.payload.equals(other.payload));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public class MessageHeaderAccessor {
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return (!this.headers.isEmpty());
|
||||
return !this.headers.isEmpty();
|
||||
}
|
||||
|
||||
public Object getHeader(String headerName) {
|
||||
@@ -132,10 +132,6 @@ public class MessageHeaderAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isReadOnly(String headerName) {
|
||||
return MessageHeaders.ID.equals(headerName) || MessageHeaders.TIMESTAMP.equals(headerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for the given header name only if the header name is not
|
||||
* already associated with a value.
|
||||
@@ -146,6 +142,15 @@ public class MessageHeaderAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the value for the given header name.
|
||||
*/
|
||||
public void removeHeader(String headerName) {
|
||||
if (StringUtils.hasLength(headerName) && !isReadOnly(headerName)) {
|
||||
setHeader(headerName, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all headers provided via array of 'headerPatterns'.
|
||||
* <p>As the name suggests, array may contain simple matching patterns for header
|
||||
@@ -181,15 +186,6 @@ public class MessageHeaderAccessor {
|
||||
return matchingHeaderNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the value for the given header name.
|
||||
*/
|
||||
public void removeHeader(String headerName) {
|
||||
if (StringUtils.hasLength(headerName) && !isReadOnly(headerName)) {
|
||||
setHeader(headerName, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the name-value pairs from the provided Map.
|
||||
* <p>This operation will overwrite any existing values. Use
|
||||
@@ -214,13 +210,18 @@ public class MessageHeaderAccessor {
|
||||
if (headersToCopy != null) {
|
||||
Set<String> keys = headersToCopy.keySet();
|
||||
for (String key : keys) {
|
||||
if (!this.isReadOnly(key)) {
|
||||
if (!isReadOnly(key)) {
|
||||
setHeaderIfAbsent(key, headersToCopy.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isReadOnly(String headerName) {
|
||||
return (MessageHeaders.ID.equals(headerName) || MessageHeaders.TIMESTAMP.equals(headerName));
|
||||
}
|
||||
|
||||
|
||||
public UUID getId() {
|
||||
return (UUID) getHeader(MessageHeaders.ID);
|
||||
}
|
||||
@@ -229,6 +230,10 @@ public class MessageHeaderAccessor {
|
||||
return (Long) getHeader(MessageHeaders.TIMESTAMP);
|
||||
}
|
||||
|
||||
public void setReplyChannelName(String replyChannelName) {
|
||||
setHeader(MessageHeaders.REPLY_CHANNEL, replyChannelName);
|
||||
}
|
||||
|
||||
public void setReplyChannel(MessageChannel replyChannel) {
|
||||
setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel);
|
||||
}
|
||||
@@ -237,8 +242,8 @@ public class MessageHeaderAccessor {
|
||||
return getHeader(MessageHeaders.REPLY_CHANNEL);
|
||||
}
|
||||
|
||||
public void setReplyChannelName(String replyChannelName) {
|
||||
setHeader(MessageHeaders.REPLY_CHANNEL, replyChannelName);
|
||||
public void setErrorChannelName(String errorChannelName) {
|
||||
setHeader(MessageHeaders.ERROR_CHANNEL, errorChannelName);
|
||||
}
|
||||
|
||||
public void setErrorChannel(MessageChannel errorChannel) {
|
||||
@@ -249,18 +254,14 @@ public class MessageHeaderAccessor {
|
||||
return getHeader(MessageHeaders.ERROR_CHANNEL);
|
||||
}
|
||||
|
||||
public void setErrorChannelName(String errorChannelName) {
|
||||
setHeader(MessageHeaders.ERROR_CHANNEL, errorChannelName);
|
||||
}
|
||||
|
||||
public MimeType getContentType() {
|
||||
return (MimeType) getHeader(MessageHeaders.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
public void setContentType(MimeType contentType) {
|
||||
setHeader(MessageHeaders.CONTENT_TYPE, contentType);
|
||||
}
|
||||
|
||||
public MimeType getContentType() {
|
||||
return (MimeType) getHeader(MessageHeaders.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -21,15 +21,19 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Extension of {@link HttpEntity} that adds a {@link HttpStatus} status code.
|
||||
* Used in {@code RestTemplate} as well {@code @Controller} methods.
|
||||
*
|
||||
* <p>Returned by {@link org.springframework.web.client.RestTemplate#getForEntity}:
|
||||
* <p>In {@code RestTemplate}, this class is returned by
|
||||
* {@link org.springframework.web.client.RestTemplate#getForEntity getForEntity()} and
|
||||
* {@link org.springframework.web.client.RestTemplate#exchange exchange()}:
|
||||
* <pre class="code">
|
||||
* ResponseEntity<String> entity = template.getForEntity("http://example.com", String.class);
|
||||
* String body = entity.getBody();
|
||||
* MediaType contentType = entity.getHeaders().getContentType();
|
||||
* HttpStatus statusCode = entity.getStatusCode();
|
||||
* </pre>
|
||||
* <p>Can also be used in Spring MVC, as a return value from a @Controller method:
|
||||
*
|
||||
* <p>Can also be used in Spring MVC, as the return value from a @Controller method:
|
||||
* <pre class="code">
|
||||
* @RequestMapping("/handle")
|
||||
* public ResponseEntity<String> handle() {
|
||||
|
||||
@@ -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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.http.server;
|
||||
|
||||
/**
|
||||
@@ -39,17 +40,17 @@ public interface ServerHttpAsyncRequestControl {
|
||||
void start(long timeout);
|
||||
|
||||
/**
|
||||
* Whether asynchronous request processing has been started.
|
||||
* Return whether asynchronous request processing has been started.
|
||||
*/
|
||||
boolean isStarted();
|
||||
|
||||
/**
|
||||
* Causes asynchronous request processing to be completed.
|
||||
* Mark asynchronous request processing as completed.
|
||||
*/
|
||||
void complete();
|
||||
|
||||
/**
|
||||
* Whether asynchronous request processing has been completed.
|
||||
* Return whether asynchronous request processing has been completed.
|
||||
*/
|
||||
boolean isCompleted();
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -37,6 +37,7 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
|
||||
private static long NO_TIMEOUT_VALUE = Long.MIN_VALUE;
|
||||
|
||||
|
||||
private final ServletServerHttpRequest request;
|
||||
|
||||
private final ServletServerHttpResponse response;
|
||||
@@ -52,7 +53,6 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
* respectively.
|
||||
*/
|
||||
public ServletServerHttpAsyncRequestControl(ServletServerHttpRequest request, ServletServerHttpResponse response) {
|
||||
|
||||
Assert.notNull(request, "request is required");
|
||||
Assert.notNull(response, "response is required");
|
||||
|
||||
@@ -69,7 +69,7 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
return ((this.asyncContext != null) && this.request.getServletRequest().isAsyncStarted());
|
||||
return (this.asyncContext != null && this.request.getServletRequest().isAsyncStarted());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,9 +84,7 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
|
||||
@Override
|
||||
public void start(long timeout) {
|
||||
|
||||
Assert.state(!isCompleted(), "Async processing has already completed");
|
||||
|
||||
if (isStarted()) {
|
||||
return;
|
||||
}
|
||||
@@ -109,6 +107,7 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Implementation of AsyncListener methods
|
||||
// ---------------------------------------------------------------------
|
||||
@@ -120,12 +119,15 @@ public class ServletServerHttpAsyncRequestControl implements ServerHttpAsyncRequ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartAsync(AsyncEvent event) throws IOException { }
|
||||
public void onStartAsync(AsyncEvent event) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(AsyncEvent event) throws IOException { }
|
||||
public void onError(AsyncEvent event) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent event) throws IOException { }
|
||||
public void onTimeout(AsyncEvent event) throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* {@link ServerHttpRequest} implementation that is based on a {@link HttpServletRequest}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ServletServerHttpRequest implements ServerHttpRequest {
|
||||
|
||||
@@ -177,13 +177,11 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
/**
|
||||
* Handle the first request for receiving messages on a SockJS HTTP transport
|
||||
* based session.
|
||||
*
|
||||
* <p>Long polling-based transports (e.g. "xhr", "jsonp") complete the request
|
||||
* after writing the open frame. Streaming-based transports ("xhr_streaming",
|
||||
* "eventsource", and "htmlfile") leave the response open longer for further
|
||||
* streaming of message frames but will also close it eventually after some
|
||||
* amount of data has been sent.
|
||||
*
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @param frameFormat the transport-specific SocksJS frame format to use
|
||||
@@ -235,19 +233,17 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
/**
|
||||
* Handle all requests, except the first one, to receive messages on a SockJS
|
||||
* HTTP transport based session.
|
||||
*
|
||||
* <p>Long polling-based transports (e.g. "xhr", "jsonp") complete the request
|
||||
* after writing any buffered message frames (or the next one). Streaming-based
|
||||
* transports ("xhr_streaming", "eventsource", and "htmlfile") leave the
|
||||
* response open longer for further streaming of message frames but will also
|
||||
* close it eventually after some amount of data has been sent.
|
||||
*
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @param frameFormat the transport-specific SocksJS frame format to use
|
||||
*/
|
||||
public void handleSuccessiveRequest(ServerHttpRequest request,
|
||||
ServerHttpResponse response, SockJsFrameFormat frameFormat) throws SockJsException {
|
||||
public void handleSuccessiveRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
SockJsFrameFormat frameFormat) throws SockJsException {
|
||||
|
||||
synchronized (this.responseLock) {
|
||||
try {
|
||||
@@ -302,7 +298,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
|
||||
/**
|
||||
* Called when the connection is active and ready to write to the response.
|
||||
* Sub-classes should implement but never call this method directly.
|
||||
* Subclasses should implement but never call this method directly.
|
||||
*/
|
||||
protected abstract void flushCache() throws SockJsTransportFailureException;
|
||||
|
||||
@@ -324,7 +320,6 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||
if (control != null && !control.isCompleted()) {
|
||||
if (control.isStarted()) {
|
||||
try {
|
||||
logger.debug("Completing asynchronous request");
|
||||
control.complete();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
Reference in New Issue
Block a user