2012-03-06 5 views
7

일부 XML을 언 마샬하는 데 JAXB를 사용하려하지만 "인스턴스를 만들 수 없습니다 ..."예외가 발생합니다. 이유를 이해합니다 - 추상적 인 클래스의 인스턴스를 만들려고합니다. 내가 원하는 것은 특정 구현 클래스의 인스턴스를 만드는 것입니다. 내 목표는 setter 메서드에 대한 클래스 별 검사를하는 것입니다. 아마도 "qux"는 BarImpl에 대한 유효한 baz 값이지만 BarImpl2는 다른 것을하려고합니다.JAXB 및 추상 클래스

나는 Foo에 주석을 달지 않음으로써 거기에가는 길을 가졌지 만, 술집에 주석을 달지 않으면 상황이 추락합니다.

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlRootElement(name="foo") 
    public static abstract class Foo { 
     @XmlElement(name="bar") 
     Bar bar; 
    } 

    @XmlRootElement(name="bar") 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    public static class FooImpl extends Foo { } 
    public static class BarImpl extends Bar { } 
} 

답변

14

는 다음을 수행 할 수 있습니다 :

JAXBTest

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElements; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlTransient; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlTransient 
    public static abstract class Foo { 
     @XmlElements({ 
      @XmlElement(name="bar",type=BarImpl.class), 
      @XmlElement(name="bar",type=BarImpl2.class), 
     }) 
     Bar bar; 
    } 

    @XmlTransient 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    @XmlRootElement(name="foo") 
    public static class FooImpl extends Foo { } 

    @XmlRootElement(name="bar") 
    public static class BarImpl extends Bar { } 

    public static class BarImpl2 extends Bar { } 
} 
+0

이 실종 한 가지 내가 할 경우 BarImpl2 (푸의) 바 이미 BarImpl로 표시되어 있다는 점이다. –

+0

이 사용 사례를 처리하기 위해'@ XmlElements'를 사용하기 위해 제 대답을 업데이트했습니다. –

+0

효과가있었습니다! BarImpl2의 구현자는 Foo의 주석을 변경해야하지만 이제는 단지 성가심 일뿐입니다. –