|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2023 the original author or authors. |
| 2 | + * Copyright 2002-2024 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
17 | 17 | package org.springframework.web.servlet.mvc.method.annotation;
|
18 | 18 |
|
19 | 19 | import java.io.IOException;
|
| 20 | +import java.util.ArrayList; |
20 | 21 | import java.util.LinkedHashSet;
|
| 22 | +import java.util.List; |
21 | 23 | import java.util.Set;
|
22 | 24 | import java.util.function.Consumer;
|
23 | 25 |
|
|
59 | 61 | *
|
60 | 62 | * @author Rossen Stoyanchev
|
61 | 63 | * @author Juergen Hoeller
|
| 64 | + * @author Brian Clozel |
62 | 65 | * @since 4.2
|
63 | 66 | */
|
64 | 67 | public class ResponseBodyEmitter {
|
@@ -271,29 +274,32 @@ public synchronized void completeWithError(Throwable ex) {
|
271 | 274 | /**
|
272 | 275 | * Register code to invoke when the async request times out. This method is
|
273 | 276 | * called from a container thread when an async request times out.
|
| 277 | + * <p>As of 6.2, one can register multiple callbacks for this event. |
274 | 278 | */
|
275 | 279 | public synchronized void onTimeout(Runnable callback) {
|
276 |
| - this.timeoutCallback.setDelegate(callback); |
| 280 | + this.timeoutCallback.addDelegate(callback); |
277 | 281 | }
|
278 | 282 |
|
279 | 283 | /**
|
280 | 284 | * Register code to invoke for an error during async request processing.
|
281 | 285 | * This method is called from a container thread when an error occurred
|
282 | 286 | * while processing an async request.
|
| 287 | + * <p>As of 6.2, one can register multiple callbacks for this event. |
283 | 288 | * @since 5.0
|
284 | 289 | */
|
285 | 290 | public synchronized void onError(Consumer<Throwable> callback) {
|
286 |
| - this.errorCallback.setDelegate(callback); |
| 291 | + this.errorCallback.addDelegate(callback); |
287 | 292 | }
|
288 | 293 |
|
289 | 294 | /**
|
290 | 295 | * Register code to invoke when the async request completes. This method is
|
291 | 296 | * called from a container thread when an async request completed for any
|
292 | 297 | * reason including timeout and network error. This method is useful for
|
293 | 298 | * detecting that a {@code ResponseBodyEmitter} instance is no longer usable.
|
| 299 | + * <p>As of 6.2, one can register multiple callbacks for this event. |
294 | 300 | */
|
295 | 301 | public synchronized void onCompletion(Runnable callback) {
|
296 |
| - this.completionCallback.setDelegate(callback); |
| 302 | + this.completionCallback.addDelegate(callback); |
297 | 303 | }
|
298 | 304 |
|
299 | 305 |
|
@@ -363,37 +369,35 @@ public MediaType getMediaType() {
|
363 | 369 |
|
364 | 370 | private class DefaultCallback implements Runnable {
|
365 | 371 |
|
366 |
| - @Nullable |
367 |
| - private Runnable delegate; |
| 372 | + private List<Runnable> delegates = new ArrayList<>(1); |
368 | 373 |
|
369 |
| - public void setDelegate(Runnable delegate) { |
370 |
| - this.delegate = delegate; |
| 374 | + public void addDelegate(Runnable delegate) { |
| 375 | + this.delegates.add(delegate); |
371 | 376 | }
|
372 | 377 |
|
373 | 378 | @Override
|
374 | 379 | public void run() {
|
375 | 380 | ResponseBodyEmitter.this.complete = true;
|
376 |
| - if (this.delegate != null) { |
377 |
| - this.delegate.run(); |
| 381 | + for (Runnable delegate : this.delegates) { |
| 382 | + delegate.run(); |
378 | 383 | }
|
379 | 384 | }
|
380 | 385 | }
|
381 | 386 |
|
382 | 387 |
|
383 | 388 | private class ErrorCallback implements Consumer<Throwable> {
|
384 | 389 |
|
385 |
| - @Nullable |
386 |
| - private Consumer<Throwable> delegate; |
| 390 | + private List<Consumer<Throwable>> delegates = new ArrayList<>(1); |
387 | 391 |
|
388 |
| - public void setDelegate(Consumer<Throwable> callback) { |
389 |
| - this.delegate = callback; |
| 392 | + public void addDelegate(Consumer<Throwable> callback) { |
| 393 | + this.delegates.add(callback); |
390 | 394 | }
|
391 | 395 |
|
392 | 396 | @Override
|
393 | 397 | public void accept(Throwable t) {
|
394 | 398 | ResponseBodyEmitter.this.complete = true;
|
395 |
| - if (this.delegate != null) { |
396 |
| - this.delegate.accept(t); |
| 399 | + for(Consumer<Throwable> delegate : this.delegates) { |
| 400 | + delegate.accept(t); |
397 | 401 | }
|
398 | 402 | }
|
399 | 403 | }
|
|
0 commit comments