2010-11-04 5 views
14

Je pense que cette question a été posée un million de fois, mais aucune des solutions proposées n'a fonctionné pour moi. Voici mon exemple d'implémentationJAXB Impossible de gérer les interfaces

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

Je reçois toujours exception suivante

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 chefs de IllegalAnnotationExceptions com.abc.objectsToReturn.Foo est une interface ,

peut me aider à trouver bonne solution

+0

Est-ce que cela échoue également s'il s'agit d'une classe abstraite? – Woot4Moo

+0

@ Woot4Moo suggestion est le long de ce que j'ai trouvé avec JAXB: interface = ne fonctionne pas, classe abstraite = fonctionne – Ash

Répondre

6

Ce n'est pas vraiment un problème d'interface, vous avez juste besoin de changer la façon dont vous amorcez votre JAXBContext.

Si vous le changiez à ce qui suit:

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

vous obtiendrez la sortie suivante (avec une mise en œuvre de JAXB: Metro, , 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 permet à votre modèle complet à être des interfaces, commander:

J'ai aussi un billet de blog qui peut être pertinent à ce que vous essayez de construire:

+0

Blaise merci pour l'exemple, mais cela n'a pas résolu mon problème :( – user497760

+0

Quels problèmes avez-vous rencontré? devra inclure le fichier eclipselink.jar sur votre chemin de classe, ajouter le fichier jaxb.properties approprié et implémenter ObjectFactory pour renvoyer les instances des classes impl –

+0

Je ne vois aucune référence aux classes de eclipselink.jar dans l'exemple de code De même, comment ObjectFactory sait-il qu'il doit prendre en charge jaxb.properties? – user497760

3

Lorsque vous utilisez des interfaces juste pour cacher vos classes d'implémentation d'une exposition, et quand il y a une relation 1-to-1 (ou proche de 1-on-1) entre une classe et une interface, XmlJavaTypeAdapter peut être utilisé comme ci-dessous.

@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

Ce qui est une copie exacte de: https://jaxb.java.net/guide/Mapping_interfaces.html#Use__XmlJavaTypeAdapter. Vous devriez toujours citer vos sources – Murmel

Questions connexes