I made a message system using Spring-Websocket. There was no errors and warnings in dev. However, it made some warnings in prod.
2022-10-17 13:24:32.894 WARN 1 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved[org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type 'application/javascript;charset=UTF-8']
I don't know where, what, when, how this warning made from so I researched on google and found only one person asked simillar question
Spring boot stomp server gives warning for resolved org.springframework.http.converter.HttpMessageNotWritableException
The answer is not really helpful for me so I decided to change log level to trace and found all most same logs with the logs in the above post.
I noticed that this warnings might come from the send event. If the message is sent to closed session, DispatcherServlet
gets a INCLUDE
type dispatch for post request "/error".
As far as I know, Spring has a BasicErrorController
bean that takes "/error" request and that controller handles two types of mapping that one for html, the other for others. The error goes not html one, and that makes a response body using DefaultErrorAttributes
which returns LinkedHashMap
.
To confirm, I extended BasicErrorController
, overrided the error method and added log.
@Slf4j
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class DefaultErrorController extends BasicErrorController {
public DefaultErrorController(ErrorAttributes errorAttributes,
ServerProperties serverProperties,
List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, serverProperties.getError(), errorViewResolvers);
}
@Override
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
log.error(request.getRequestURI());
log.error(request.getDispatcherType().name());
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status);
}
Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
return new ResponseEntity<>(body, status);
}
}
I got logs.
2022-10-18 15:35:51.400 TRACE 1 --- [io-8080-exec-19] o.s.web.servlet.DispatcherServlet : "INCLUDE" dispatch for POST "/error?t=1666074896571", parameters={t:[1666074896571]}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2022-10-18 15:35:51.400 TRACE 1 --- [io-8080-exec-19] s.w.s.m.m.a.RequestMappingHandlerMapping : 2 matching mappings: [{ [/error]}, { [/error], produces [text/html]}]
2022-10-18 15:35:51.400 TRACE 1 --- [io-8080-exec-19] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to c.b.w.c.exception.DefaultErrorController#error(HttpServletRequest)
2022-10-18 15:35:51.400 ERROR 1 --- [io-8080-exec-19] c.b.w.c.e.DefaultErrorController : /socket/works/endpoint/694/ksn1ppli/xhr_streaming
2022-10-18 15:35:51.400 ERROR 1 --- [io-8080-exec-19] c.b.w.c.e.DefaultErrorController : INCLUDE
2022-10-18 15:35:51.401 WARN 1 --- [io-8080-exec-19] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type 'application/javascript;charset=UTF-8']
2022-10-18 15:35:51.401 TRACE 1 --- [io-8080-exec-19] o.s.web.servlet.DispatcherServlet : No view rendering, null ModelAndView returned.
2022-10-18 15:35:51.401 DEBUG 1 --- [io-8080-exec-19] o.s.web.servlet.DispatcherServlet : Exiting from "INCLUDE" dispatch, status 200, headers={masked}
My guess is that the socket error somehow has to response application/javascript;charset=UTF-8
.
The Spring's default converter MappingJackson2HttpMessageConverter
does not have application/javascript;charset=UTF-8
mime type to convert that response. That's why the warning is made.
I tried to solve it by adding some codes to BasicErrorController.
@Slf4j
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class DefaultErrorController extends BasicErrorController {
public static final String SOCKET_ERROR = "xhr_streaming";
public DefaultErrorController(ErrorAttributes errorAttributes,
ServerProperties serverProperties,
List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, serverProperties.getError(), errorViewResolvers);
}
@Override
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
//added
if(request.getDispatcherType().equals(DispatcherType.INCLUDE)
&& request.getRequestURI().endsWith(SOCKET_ERROR)) {
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status);
}
Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
return new ResponseEntity<>(body, status);
}
}
The warning disappeared.. but next day, I checked logs and surprisingly found another warning
2022-10-19 09:32:36.485 WARN 1 --- [io-8080-exec-18] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type 'text/event-stream;charset=UTF-8']
I want to know which class decides the content type for response from send event error and how to solve it.