Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB Can't handle interfaces

Tags:

java

jaxb

I think this question has been asked like a million times, but none of solutions suggested worked for me. Here is my sample implementation

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;
    }

I always get following exception

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions com.abc.objectsToReturn.Foo is an interface,

can any one help me to figure out right solution

like image 857
user497760 Avatar asked Nov 04 '10 21:11

user497760


1 Answers

This isn't really an interface issue, you just need to change the way you bootstrap your JAXBContext.

If you change it to the following:

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);
    }
}

Then you will get the following output (with any JAXB implementation: Metro, MOXy, etc):

<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>

MOXy JAXB allows your entire model to be interfaces, checkout:

  • http://bdoughan.blogspot.com/2010/07/moxy-jaxb-map-interfaces-to-xml.html

I also have a blog post that may be relevant to what you are trying to build:

  • http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html
like image 67
bdoughan Avatar answered Sep 24 '22 11:09

bdoughan