Как использовать явно указанный маршаллер в Spring Boot - PullRequest
1 голос
/ 21 сентября 2019

Я пытаюсь создать REST-сервис, способный производить вывод XML (у меня есть собственный класс, который обернут внутри объекта HATEOAS).Сопоставление выглядит так:

@GetMapping("/customclass")
Resource<CustomClass> custom() {
    return new Resource<CustomClass>(new CustomClass());
}

Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not marshal [Resource { content: CustomClass(a=10, string=abc), links: [] }]: null; nested exception is javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: class test.CustomClass nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class test.CustomClass nor any of its super class is known to this context.]]

Я почти уверен, что с моим CustomClass все в порядке.Если вместо этого я использую следующее сопоставление

@GetMapping("/customclass")
CustomClass custom() {
    return (new CustomClass());
}

, то оно работает нормально.

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

Насколько я понимаю, проблема в том, что маршаллер в SpringApplication использует контекст, который просто знает о HATEOAS Resource, и мне нужно кое-какинформировать его о CustomClass.

Я пытался использовать что-то вроде этого (из https://stackoverflow.com/a/40398632)

@Configuration
public class ResponseResolver  {
    @Bean
    public Marshaller marshaller() {
        try {
            System.out.println("getting marshaller");
            JAXBContext context = JAXBContext.newInstance(CustomClass.class, Resource.class);
            return context.createMarshaller();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
}

, но это не сработало (с моей стороны было много догадок), поскольку я не очень много знаю о внутренней работе Spring Boot).

Многообещающий ответ был также в https://stackoverflow.com/a/14073899, но ContextResolver не было в classpath моих проектов.

Я также рассмотрел оборачивание Resource внутри другого класса, а затем использование аннотации XmlSeeAlso, но это могло бы испортить мой XML и было бы несколько уродливым взломом.

Так что возможно определить пользовательский JAXBContext, который SpringApplicationсможет забрать?

1 Ответ

2 голосов
/ 21 сентября 2019

Из документации по загрузке Spring Преобразователи сообщений Spring Message

Spring MVC использует интерфейс HttpMessageConverter для преобразования HTTP-запросов и ответов.Разумные значения по умолчанию включены из коробки.Например, объекты могут быть автоматически преобразованы в JSON (с помощью библиотеки Джексона) или XML (с помощью расширения Jackson XML, если оно доступно, или с помощью JAXB, если расширение XML Jackson недоступно).По умолчанию Jaxb2RootElementHttpMessageConverter - преобразует объекты Java в / из XML (добавляется, только если в пути к классам присутствует JAXB2)

Конфигурация пользовательских преобразователей

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(
      List<HttpMessageConverter<?>> converters) {

        messageConverters.add(createXmlHttpMessageConverter());
        messageConverters.add(new MappingJackson2HttpMessageConverter());
    }
    private HttpMessageConverter<Object> createXmlHttpMessageConverter() {
        MarshallingHttpMessageConverter xmlConverter = 
          new MarshallingHttpMessageConverter();

        XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
        xmlConverter.setMarshaller(xstreamMarshaller);
        xmlConverter.setUnmarshaller(xstreamMarshaller);

        return xmlConverter;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...