2010-11-04 405 views
14

我認爲這個問題已經被提出了100萬次,但沒有任何解決方案建議爲我工作。這裏是我的示例實現JAXB無法處理接口

public class FooImpl2 implements Foo { 
    private int a = 100 ; 
    private String b = "I am FooImpl2"; 
    private boolean c; 

    public int getA() { 
     return a; 
    } 
    public void setA(int a) { 
     this.a = a; 
    } 
    public String getB() { 
     return b; 
    } 
    public void setB(String b) { 
     this.b = b; 
    } 
    public boolean isC() { 
     return c; 
    } 
    public void setC(boolean c) { 
     this.c = c; 
    } 

} 

@XmlRootElement 
@XmlSeeAlso({FooImpl1.class, FooImpl2.class}) 
public interface Foo {} 

public class FooImpl1 implements Foo {  
    private int x; 
    private String y ="I am FooImpl1"; 
    private boolean z; 

    public int getX() { 
     return x; 
    } 
    public void setX(int x) { 
     this.x = x; 
    } 
    public String getY() { 
     return y; 
    } 
    public void setY(String y) { 
     this.y = y; 
    } 
    public boolean isZ() { 
     return z; 
    } 
    public void setZ(boolean z) { 
     this.z = z; 
    }   
} 

@XmlRootElement 
public class Response{ 

    private Foo foo; 

    @XmlElement(type=Object.class) 
    public Foo getFoo() { 
     return foo; 
    } 

    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 

} 

public class SimpleResource {  
    @Path("foo/{val}") @Produces({"application/json"}) @GET 
    public FooAdapter getFoo(@QueryParam("val") int val) { 
     FooAdapter ret = new FooAdapter(); 
     if(val % 2 == 0) { 
      ret.setFoo(new FooImpl2()); 
     } else { 
      ret.setFoo(new FooImpl1()); 
     } 

     return ret; 
    } 

我總是得到以下異常

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException:中 IllegalAnnotationExceptions com.abc.objectsToReturn.Foo 2個字是 接口,

任何一個可以幫我找出正確的解決方案

+0

如果它是一個抽象類,這也會失敗嗎? – Woot4Moo 2010-11-04 21:51:31

+0

@ Woot4Moo的建議與我在JAXB中找到的一致:interface =不工作,abstract class =工作 – Ash 2010-11-04 23:17:47

回答

6

這不是一個真正的接口問題,您只需要改變引導JAXBContext的方式。

如果將其更改爲以下內容:

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Response.class, FooImpl1.class, FooImpl2.class); 

     Response response = new Response(); 
     FooImpl1 foo = new FooImpl1(); 
     response.setFoo(foo); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(response, System.out); 
    } 
} 

然後你會得到下面的輸出(與任何JAXB實現:Metro,等):

<response> 
    <foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="fooImpl1"> 
     <x>0</x> 
     <y>I am FooImpl1</y> 
     <z>false</z> 
    </foo> 
</response> 

莫西JAXB允許您整個款式爲接口,結帳:

我也有一個博客貼子,可能與你正在試圖建立:

+0

Blaise感謝這個例子,但是這並沒有解決我的問題:( – user497760 2010-11-05 13:56:27

+0

你遇到了什麼問題?將需要在您的類路徑中包含eclipselink.jar,添加相應的jaxb.properties,並實現ObjectFactory以返回impl類的實例。 – 2010-11-05 14:05:14

+0

我沒有在示例代碼中看到對eclipselink.jar的類的任何引用 另外,ObjectFactory如何知道它必須提取jaxb.properties? – user497760 2010-11-05 14:51:34

3

當您使用的界面,從曝光隱藏你的實現類,當類和接口之間存在1對1(或接近1對1)關係時,可以像下面那樣使用XmlJavaTypeAdapter。

@XmlJavaTypeAdapter(FooImpl.Adapter.class) 
interface IFoo { 
    ... 
} 
class FooImpl implements IFoo { 
    @XmlAttribute 
    private String name; 
    @XmlElement 
    private int x; 

    ... 

    static class Adapter extends XmlAdapter<FooImpl,IFoo> { 
    IFoo unmarshal(FooImpl v) { return v; } 
    FooImpl marshal(IFoo v) { return (FooImpl)v; } 
    } 
} 

class Somewhere { 
    public IFoo lhs; 
    public IFoo rhs; 
} 
+1

下面是一個精確副本:https://jaxb.java.net/guide/Mapping_interfaces.html#Use__XmlJavaTypeAdapter。您應該始終引用您的來源 – Murmel 2016-08-26 16:27:30