java.lang.ClassCastException: класс java.util.HashMap не может быть приведен: SpringBoot

#java #spring-boot

#java #весенняя загрузка

Вопрос:

Мы выполняем миграцию с версии Spring 5.0 на версию Spring Boot 2.4. Мой код контроллера выглядит следующим образом

 @RequestMapping(value = "/getTreeNodesByFilter.action", method = RequestMethod.GET)
    public @ResponseBody Map<String, ? extends Object> getTreeNodesByFilter(@RequestParam("type") String type,
            @RequestParam("id") Long id, @RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize,
            @RequestParam("filterBy") String filterBy) {
        Map<String, Object> responseMap = commonService.getTreeNodesByFilter(type, id, pageNo, pageSize, filterBy);
        return ResponseUtil.getMap(responseMap);
    }
 

Тело ответа представляет собой хэш-карту, как показано выше. Этот код отлично работает в обычном веб-приложении spring.
Тот же код, когда мы устали от SpringBoot, мы получаем следующую ошибку

 java.lang.ClassCastException: class java.util.HashMap cannot be cast to class com.scriptless.web.security.exceptions.JsonError (java.util.HashMap is in module java.base of loader 'bootstrap'; com.scriptless.web.security.exceptions.JsonError is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @5f00ac7a)
 

Эта ошибка выдается из AbstractMessageConverterMethodProcessor.class из Spring-webmvc.jar во время выполнения кода

 ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
 

Может кто-нибудь, пожалуйста, подсказать, что нужно сделать для решения этой проблемы?

Комментарии:

1. Кажется, есть ошибка безопасности, и она пытается сериализовать в неправильный класс. Попробуйте определить исходное исключение, а затем использовать для него обработку ошибок. Посмотрите здесь для обработки ошибок: baeldung.com/exception-handling-for-rest-with-spring

2. Вам нужно добавить полиморфный параметр проверки типов, чтобы разрешить подтипы HashMap, такие как allowIfSubType(«java.util.») в вашем ObjectMapper. Тогда, надеюсь, это должно сработать.

Ответ №1:

Попробуйте этот ObjectMapper,

 public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                .configure(MapperFeature.USE_GETTERS_AS_SETTERS, false);
        SimpleModule module = new SimpleModule();

        objectMapper.registerModule(module);
        objectMapper.registerModule(new JavaTimeModule());
        PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
            .allowIfSubType("java.util.") //$NON-NLS-1$
                .build();

        objectMapper.setPolymorphicTypeValidator(ptv);
        objectMapper.activateDefaultTyping(ptv, DefaultTyping.NON_FINAL);
        return objectMapper;
    }
 

Это позволило бы десериализовать все подтипы пакета java.util.*.