JAXB Marshalling and Generics
Я пытаюсь использовать JSXB-интроспекцию для маршаллинга и unmashall некоторых существующих объектов домена, помеченных аннотациями JAXB. Большинство вещей работает так, как ожидалось, но у меня довольно много проблем с получением довольно простого класса для сериализации. Этот класс используется как элемент @XmlElement для ряда beans и выглядит примерно так:
public class Range<E extends Comparable<E>> implements Serializable {
protected boolean startInclusive, endInclusive;
protected E start, end;
public Range(){
startInclusive = endInclusive = true;
}
public boolean contains(E value){...}
public E getEnd() {
return end;
}
public void setEnd(E end) {
this.end = end;
}
public boolean isEndInclusive() {
return endInclusive;
}
public void setEndInclusive(boolean endInclusive) {
this.endInclusive = endInclusive;
}
public E getStart() {
return start;
}
public void setStart(E start) {
this.start = start;
}
public boolean isStartInclusive() {
return startInclusive;
}
public void setStartInclusive(boolean startInclusive) {
this.startInclusive = startInclusive;
}
}
Я пытался сделать следующее, без каких-либо успехов, JAXB все еще злится на интерфейс Comparable.
public class DoubleRange extends Range<Double> {}
Используя как Range, так и DoubleRange в качестве типов возврата для getter bean, получается исключение, подобное:
java.lang.Comparable is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.lang.Comparable
at protected java.lang.Comparable com.controlpath.util.Range.start
at example.util.Range
at example.util.DoubleRange
at public example.util.DoubleRange example.domain.SomeBean.getRange()
at example.domain.SomeBean
Я понимаю, что в большинстве случаев List <T> и Map < T, U > работает только потому, что спецификация JAXB имеет специальные положения для этих типов, когда они встречаются на beans, но есть ли способ передать то, что я хочу для механизма самоанализа JAXB, не переустраивая диапазон с не-генерическими полями?
Ответы
Ответ 1
Вы можете написать пользовательский адаптер (не используя JAXB XmlAdapter), выполнив следующие действия:
1) объявить класс, который принимает все типы элементов и имеет аннотации JAXB
и обрабатывает их по вашему желанию (в моем примере я конвертирую все в String)
@YourJAXBAnnotationsGoHere
public class MyAdapter{
@XmlElement // or @XmlAttribute if you wish
private String content;
public MyAdapter(Object input){
if(input instanceof String){
content = (String)input;
}else if(input instanceof YourFavoriteClass){
content = ((YourFavoriteClass)input).convertSomehowToString();
}else if(input instanceof .....){
content = ((.....)input).convertSomehowToString();
// and so on
}else{
content = input.toString();
}
}
}
// I would suggest to use a Map<Class<?>,IMyObjToStringConverter> ...
// to avoid nasty if-else-instanceof things
2) используйте этот класс вместо E в вашем классе, который будет называться
ПРИМЕЧАНИЯ
- Конечно, это работа не для сложных (вложенных) структур данных.
- Вам нужно подумать, как отменить это снова, может быть сложнее. Если
это слишком сложно, подождите лучшего предложения, чем мое;)
Ответ 2
Как насчет
public class Range<**E extends Number**> implements Serializable { ...
Для unmarshalling для определенного типа вам нужен XmlAdapter как я
описанный здесь: Наследование JAXB, не связанное с подклассом маршалированного класса
Ответ 3
Попробуйте что-то вроде Простая XML-сериализация, она поставляется с поддержкой общих типов в XML-элементах с рядом аннотаций, таких как @Element и @Elementlist. Модель программирования очень похожа, но проще, чем JAXB.
Ответ 4
Собственно, мне не совсем понятно, почему это не сработает. Кажется, что JAXB должен иметь возможность правильно разрешать определенный подтип: if (и только если!) Этот тип НЕ является корневым типом (который не соответствует вашему описанию). Я имею в виду, это всего лишь Bean; поэтому, если bean с заменой Т на работу прямого типа, то должна быть общая версия iff с использованием подклассификации для типов привязки (как это сделано в примере).
Возможно, это может быть ошибкой в реализации?
Ответ 5
Итак, похоже, проблема заключается в стирании E
на start
, а end
- Comparable
. Если он не может обрабатывать интерфейсы, вы можете попробовать Object
, но я надеюсь, что он тоже будет жаловаться (сейчас или позже). Возможно, вы могли бы сделать реферат Range
и специализироваться на каждом конкретном E
. Я должен знать больше о JAXB.