Я работаю с Spring 4 вместе с Spring MVC.
У меня есть следующий класс POJO
@XmlRootElement(name="person")
@XmlType(propOrder = {"id",...})
public class Person implements Serializable {
…
@Id
@XmlElement
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
…
}
Если я хочу вернуть список Person через Spring MVC в формате XML, у меня есть следующий обработчик
@RequestMapping(value="/getxmlpersons/generic",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public JaxbGenericList<Person> getXMLPersonsGeneric(){
logger.info("getXMLPersonsGeneric - getxmlpersonsgeneric");
List<Person> persons = new ArrayList<>();
persons.add(...);
…more
JaxbGenericList<Person> jaxbGenericList = new JaxbGenericList<>(persons);
return jaxbGenericList;
}
Где находится JaxbGenericList (объявление класса на основе Generics)
@XmlRootElement(name="list")
public class JaxbGenericList<T> {
private List<T> list;
public JaxbGenericList(){}
public JaxbGenericList(List<T> list){
this.list=list;
}
@XmlElement(name="item")
public List<T> getList(){
return list;
}
}
Когда я выполняю URL-адрес, я получаю следующую трассировку стека ошибок
org.springframework.http.converter.HttpMessageNotWritableException: Could not marshal [com.manuel.jordan.jaxb.support.JaxbGenericList@31f8809e]: null; nested exception is javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: class com.manuel.jordan.domain.Person nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class com.manuel.jordan.domain.Person nor any of its super class is known to this context.]
Но Если у меня есть это (объявление класса не основано на Generics):
@XmlRootElement(name="list")
public class JaxbPersonList {
private List<Person> list;
public JaxbPersonList(){}
public JaxbPersonList(List<Person> list){
this.list=list;
}
@XmlElement(name="item")
public List<Person> getList(){
return list;
}
}
и другой метод handler, конечно, следующим образом
@RequestMapping(value="/getxmlpersons/specific",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public JaxbPersonList getXMLPersons(){
logger.info("getXMLPersonsSpecific - getxmlpersonsspecific");
List<Person> persons = new ArrayList<>();
persons.add(...);
…more
JaxbPersonList jaxbPersonList = new JaxbPersonList(persons);
return jaxbPersonList;
}
Все работает нормально:
Вопрос, какие дополнительные настройки мне нужны, чтобы спокойно работать только с JaxbGenericList
Дополнение 1
Я не настраивал bean-компонент marshaller
, поэтому я думаю, что Spring за кулисами предоставил его. Теперь, согласно вашему ответу, я добавил следующее:
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(JaxbGenericList.class, Person.class);
Map<String, Object> props = new HashMap<>();
props.put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setMarshallerProperties(props);
return marshaller;
}
Кажется, чего-то не хватает, потому что я получаю «снова»:
org.springframework.http.converter.HttpMessageNotWritableException: Could not marshal [com.manuel.jordan.jaxb.support.JaxbGenericList@6f763e89]: null; nested exception is javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: class com.manuel.jordan.domain.Person nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class com.manuel.jordan.domain.Person nor any of its super class is known to this context.]
Вы пробовали в веб-среде? Кажется, мне нужно сообщить Spring MVC об использовании этого marshaller
, я сказал кажется, потому что другой URL-адрес, работающий с не коллекциями POJO/XML, пока работает нормально.
Я работаю с Spring 4.0.5, а веб-среда настроена через Java Config.
Дополнение второе
Предложенное вами последнее издание работает
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(marshallingMessageConverter());
}
@Bean
public MarshallingHttpMessageConverter marshallingMessageConverter() {
MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
converter.setMarshaller(jaxbMarshaller());
converter.setUnmarshaller(jaxbMarshaller());
return converter;
}
Но теперь мой XML не является общим, и код JSON не работает.
Для моего другого URL-адреса XML http://localhost:8080/spring-utility/person/getxmlpersons/specific
HTTP Status 406 -
type Status report
message
description The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
Исправлено добавление или обновление:
от:
marshaller.setClassesToBeBound(JaxbGenericList.class, Person.class);
to:
marshaller.setClassesToBeBound(JaxbGenericList.class, Person.class, JaxbPersonList.class);
Но для JSON снова другой URL http://localhost:8080/spring-utility/person/getjsonperson
HTTP Status 406 -
type Status report
message
description The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
Кажется, мне нужно добавить конвертер для JSON (ранее я не определял), я использовал значения по умолчанию Spring, не могли бы вы мне помочь?