2010-11-04 404 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