문제
JAXB 주석으로 표시된 일부 기존 도메인 개체를 마샬링하고 제거하기 위해 JAXB의 내부 검사를 사용하려고 합니다.대부분의 작업은 예상대로 작동하지만 상당히 간단한 클래스를 직렬화하는 데 꽤 어려움을 겪고 있습니다.이 클래스는 여러 Bean에서 @XmlElement로 사용되며 다음과 같습니다.
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> {}
Bean getter의 반환 유형으로 Range와 DoubleRange를 모두 사용하면 다음과 같은 예외가 발생합니다.
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 사양에 Bean에서 이러한 유형이 발견될 때 해당 유형에 대한 특별한 조항이 있기 때문에 작동한다는 것을 알고 있습니다. 그러나 JAXB 내부 검사에 원하는 것을 전달할 수 있는 방법이 있습니까? 제네릭이 아닌 필드로 range를 다시 구현할 필요 없이 엔진을 사용하시겠습니까?
해결책
다음을 수행하여 사용자 정의 어댑터 (JAXB의 Xmladapter를 사용하지 않음)를 작성할 수 있습니다.
1) 모든 종류의 요소를 받아들이고 jaxb 주석이 있고 원하는대로 처리하는 클래스를 선언합니다 (내 예에서는 모든 것을 문자열로 변환).
@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 대신이 클래스를 사용하십시오.
메모
- 물론 이것은 할 것입니다 ~ 아니다 복잡한 (중첩) 데이터 구조를 위해 작동합니다.
- 당신은 이것을 다시 돌려받지 않는 방법을 생각해야합니다. 더 까다로울 수 있습니다. 너무 까다 롭다면, 내 것보다 더 나은 제안을 기다리십시오;)
다른 팁
어때
public class Range<**E extends Number**> implements Serializable { ...
숫자는 a입니다 수업
나는 JaxB가 알고 있다고 확신한다 기본 마샬링/숫자에 대한 규칙
특정 유형에 맞지 않으려면 여기에 설명 된대로 Xmladapter가 필요합니다. JAXB 상속, 마샬링 클래스의 서브 클래스에 대한 undarshal
같은 것을 시도하십시오 간단한 XML 직렬화 @Element 및 @ElementList와 같은 여러 주석이있는 XML 요소의 일반 유형을 지원합니다. 프로그래밍 모델은 매우 유사하지만 JAXB보다 간단합니다.
사실, 이것이 왜 작동하지 않는지는 분명하지 않습니다. JAXB는 특정 하위 유형을 올바르게 해결할 수 있어야합니다.이 유형은 루트 유형이 아닙니다 (설명에 따라는 아닙니다). 내 말은, 그것은 단지 콩 일뿐입니다. 따라서 T가있는 Bean이 직접 유형으로 대체 된 경우 서브 클래스를 사용하여 유형을 바인딩하는 일반 버전 IFF (예제에서 수행)해야합니다.
아마도 구현의 버그 일 수 있습니까?
그래서 문제는 삭제인 것 같습니다. E
~에 start
그리고 end
~이다 Comparable
.인터페이스를 처리할 수 없다면 시도해 볼 수 있습니다. Object
, 그러나 나는 그것이 (지금이든 나중에든) 그것에 대해서도 불평하기를 바랍니다.아마도 당신은 만들 수 있습니다 Range
각 특정 항목에 대해 추상화하고 전문화합니다. E
.JAXB에 대해 더 많이 알아야 합니다.