Используя Spring MVC, у меня есть контроллер с конечной точкой, возвращающей SseEmitter.
@GetMapping(path = "/accept/{amount}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "409", description = "BUSY", content = @Content(schema = @Schema(implementation = MyErrorClass.class))),
@ApiResponse(responseCode = "500", description = "UNEXPECTED_ERROR", content = @Content(schema = @Schema(implementation = MyErrorClass.class)))
})
public SseEmitter accept(@Parameter(description = "Amount to accept") @PathVariable double amount) throws MyException {
ExecutorService service = Executors.newCachedThreadPool();
SseEmitter emitter = new SseEmitter();
myService.accept(amount);
service.execute(() -> {
while(myService.inAcceptanceState()) {
try {
emitter.send(myService.getCurrentAmount());
Thread.sleep(1000);
} catch (InterruptedException | IOException ex) {
emitter.completeWithError(ex);
}
}
try {
emitter.send(myService.getCurrentAmount());
emitter.complete();
} catch (IOException e) {
emitter.completeWithError(e);
}
});
service.shutdown();
return emitter;
}
В случае приведенного выше кода ожидается, что метод accept() выдаст ошибку 400, когда он вызывается во второй раз до завершения первого вызова. На данный момент я получаю следующее:
2020-09-03 15:22:14.105 WARN 480 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Failure in @ExceptionHandler com.mydomain.common.ExceptionController#handleMyException(Exception)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
Это не приводит к сбою моей службы Springboot, но вызов не завершается, поэтому вызывает очевидную проблему. Я заметил, что это прекрасно работает, если я перехожу на produces = MediaType.APPLICATION_JSON_STREAM_VALUE
. Он возвращает исключение и сообщение об ошибке, связанное с этим исключением, как я и ожидал, но нам нужно использовать TEXT_STREAM для SseEmitter, и наши потребители ожидают возврата такого типа. По моему (ограниченному) пониманию, в Spring есть какая-то магия HttpConversion, происходящая с телами ответа, так что мне нужно сделать, чтобы вернуть исключение, используя produces = MediaType.APPLICATION_JSON_STREAM_VALUE
? Нужно ли мне писать свой собственный преобразователь ответов, как бы это ни выглядело...?