diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitter.java index b28dba8c0be..a4536a4b9ca 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitter.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.web.servlet.mvc.method.annotation; import java.io.IOException; @@ -23,7 +24,6 @@ import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpResponse; import org.springframework.util.Assert; - /** * A controller method return value type for asynchronous request processing * where one or more objects are written to the response. While @@ -53,15 +53,12 @@ import org.springframework.util.Assert; * emitter.complete(); * * - *

Note: this class is not thread-safe. Callers must ensure - * that use from multiple threads is synchronized. - * * @author Rossen Stoyanchev * @since 4.2 */ public class ResponseBodyEmitter { - private Handler handler; + private volatile Handler handler; /* Cache for objects sent before handler is set. */ private final Map initHandlerCache = new LinkedHashMap(10); @@ -124,7 +121,7 @@ public class ResponseBodyEmitter { * @throws java.lang.IllegalStateException wraps any other errors */ public void send(Object object, MediaType mediaType) throws IOException { - Assert.state(!this.complete, "ResponseBodyEmitter is already set complete."); + Assert.state(!this.complete, "ResponseBodyEmitter is already set complete"); sendInternal(object, mediaType); } @@ -132,9 +129,9 @@ public class ResponseBodyEmitter { if (object == null) { return; } - if (handler == null) { + if (this.handler == null) { synchronized (this) { - if (handler == null) { + if (this.handler == null) { this.initHandlerCache.put(object, mediaType); return; } @@ -143,11 +140,11 @@ public class ResponseBodyEmitter { try { this.handler.send(object, mediaType); } - catch(IOException ex){ + catch (IOException ex){ this.handler.completeWithError(ex); throw ex; } - catch(Throwable ex){ + catch (Throwable ex){ this.handler.completeWithError(ex); throw new IllegalStateException("Failed to send " + object, ex); } @@ -161,7 +158,7 @@ public class ResponseBodyEmitter { public void complete() { synchronized (this) { this.complete = true; - if (handler != null) { + if (this.handler != null) { this.handler.complete(); } } @@ -176,7 +173,7 @@ public class ResponseBodyEmitter { synchronized (this) { this.complete = true; this.failure = ex; - if (handler != null) { + if (this.handler != null) { this.handler.completeWithError(ex); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java index 5ed597d0e20..ef7f925d89e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java @@ -13,18 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.web.servlet.mvc.method.annotation; import java.io.IOException; import java.io.OutputStream; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.List; - import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.http.HttpHeaders; @@ -41,7 +40,6 @@ import org.springframework.web.context.request.async.WebAsyncUtils; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; - /** * Supports return values of type {@link ResponseBodyEmitter} and also * {@code ResponseEntity}. @@ -61,6 +59,7 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur this.messageConverters = messageConverters; } + @Override public boolean supportsReturnType(MethodParameter returnType) { if (ResponseBodyEmitter.class.isAssignableFrom(returnType.getParameterType())) { @@ -121,13 +120,11 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur private final DeferredResult deferredResult; - public HttpMessageConvertingHandler(ServerHttpResponse outputMessage, DeferredResult deferredResult) { this.outputMessage = outputMessage; this.deferredResult = deferredResult; } - @Override public void send(Object data, MediaType mediaType) throws IOException { sendInternal(data, mediaType); @@ -145,7 +142,7 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur return; } } - throw new IllegalArgumentException("No suitable converter for " + data); + throw new IllegalArgumentException("No suitable converter for " + data.getClass()); } @Override @@ -170,13 +167,11 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur private final HttpHeaders mutableHeaders = new HttpHeaders(); - public StreamingServletServerHttpResponse(ServerHttpResponse delegate) { this.delegate = delegate; this.mutableHeaders.putAll(delegate.getHeaders()); } - @Override public void setStatusCode(HttpStatus status) { this.delegate.setStatusCode(status); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java index 874af6c9526..6f3981d228e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.web.servlet.mvc.method.annotation; import java.io.IOException; @@ -26,9 +27,7 @@ import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpResponse; /** - * A specialization of - * {@link org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter - * ResponseBodyEmitter} for sending + * A specialization of {@link ResponseBodyEmitter} for sending * Server-Sent Events. * * @author Rossen Stoyanchev @@ -36,7 +35,7 @@ import org.springframework.http.server.ServerHttpResponse; */ public class SseEmitter extends ResponseBodyEmitter { - public static final MediaType TEXT_PLAIN = new MediaType("text", "plain", Charset.forName("UTF-8")); + static final MediaType TEXT_PLAIN = new MediaType("text", "plain", Charset.forName("UTF-8")); @Override @@ -51,7 +50,6 @@ public class SseEmitter extends ResponseBodyEmitter { /** * Send the object formatted as a single SSE "data" line. It's equivalent to: *

-	 *
 	 * // static import of SseEmitter.*
 	 *
 	 * SseEmitter emitter = new SseEmitter();
@@ -69,7 +67,6 @@ public class SseEmitter extends ResponseBodyEmitter {
 	/**
 	 * Send the object formatted as a single SSE "data" line. It's equivalent to:
 	 * 
-	 *
 	 * // static import of SseEmitter.*
 	 *
 	 * SseEmitter emitter = new SseEmitter();
@@ -91,7 +88,6 @@ public class SseEmitter extends ResponseBodyEmitter {
 	/**
 	 * Send an SSE event prepared with the given builder. For example:
 	 * 
-	 *
 	 * // static import of SseEmitter
 	 *
 	 * SseEmitter emitter = new SseEmitter();
@@ -108,6 +104,7 @@ public class SseEmitter extends ResponseBodyEmitter {
 		}
 	}
 
+
 	public static SseEventBuilder event() {
 		return new DefaultSseEventBuilder();
 	}
@@ -156,6 +153,7 @@ public class SseEmitter extends ResponseBodyEmitter {
 		Map build();
 	}
 
+
 	/**
 	 * Default implementation of SseEventBuilder.
 	 */
@@ -165,7 +163,6 @@ public class SseEmitter extends ResponseBodyEmitter {
 
 		private StringBuilder sb;
 
-
 		@Override
 		public SseEventBuilder comment(String comment) {
 			append(":").append(comment != null ? comment : "").append("\n");