Spring boot makes warning log HttpMessageNotWritableException from the reason that might come from WebSocket

290 Views Asked by At

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.

0

There are 0 best solutions below