문제

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에 대해 더 많이 알아야 합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top