Използвам Jaxb2Marshaller за маршал Java beans чрез пролетна анотация @ResponseBody. За JSON маршалингът работи добре. Но за xml непрекъснато получавах HTTP 406 отговор. Малко копаене в клас Jaxb2Marshaller разкрива, че той проверява за @XmlRootElement за ограничени класове (вижте фрагмента по-долу).
Докато генерирах Java код от xsd, моят pojo не съдържа @XmlRootElement и правилният конвертор на съобщения не беше идентифициран от AnnotationMethodHandlerAdapter и накрая доведе до 406.
Вместо автоматично генериране на Java код от xsd, създадох свой собствен pojo клас и използвах @XmlRootElement. Тогава маршалингът работи добре.
Искам да разбера защо е важно @XmlRootElement да проверява за ограничени класове. Или по някакъв начин да посочите елемент като @XmlRootElement в xsd.
Кодов фрагмент от Jaxb2Marshaller:
public boolean supports(Class clazz) {
return supportsInternal(clazz, true);
}
private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement) {
if (checkForXmlRootElement && clazz.getAnnotation(XmlRootElement.class) == null) {
return false;
}
if (clazz.getAnnotation(XmlType.class) == null) {
return false;
}
if (StringUtils.hasLength(getContextPath())) {
String className = ClassUtils.getQualifiedName(clazz);
int lastDotIndex = className.lastIndexOf('.');
if (lastDotIndex == -1) {
return false;
}
String packageName = className.substring(0, lastDotIndex);
String[] contextPaths = StringUtils.tokenizeToStringArray(getContextPath(), ":");
for (String contextPath : contextPaths) {
if (contextPath.equals(packageName)) {
return true;
}
}
return false;
}
else if (!ObjectUtils.isEmpty(classesToBeBound)) {
return Arrays.asList(classesToBeBound).contains(clazz);
}
return false;
}
Редактиране: Отговорът на Blaise ми помогна да реша проблема с @XmlRootElement. Но все пак, ако някой има информация защо е необходима проверка за XmlRootElement, ще бъде добра информация.