JAXB Не может обрабатывать интерфейсы - PullRequest
15 голосов
/ 05 ноября 2010

Я думаю, что этот вопрос задавался миллион раз, но ни одно из предложенных решений не помогло мне. Вот мой пример реализации

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: 2 отсчета IllegalAnnotationExceptions com.abc.objectsToReturn.Foo является интерфейс,

Может ли кто-нибудь помочь мне найти правильное решение

Ответы [ 2 ]

6 голосов
/ 05 ноября 2010

Это на самом деле не проблема интерфейса, вам просто нужно изменить способ загрузки 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: Метро , MOXy и т. Д.):

<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 позволяет всей вашей модели быть интерфейсами, оформить заказ:

У меня также есть запись в блоге, которая может иметь отношение к тому, что вы пытаетесь создать:

3 голосов
/ 29 января 2016

Когда вы используете интерфейсы просто для того, чтобы скрыть свои классы реализации от воздействия, и когда между классом и интерфейсом существует отношение 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...