3 Stimmen

Jersey REST/ JAXB-Fehler, Abbildung einer Schnittstelle

Ich muss eine Schnittstelle in meinem REST-Webdienst verwenden. Hier ist die Schnittstelle Specs.java :

@XmlJavaTypeAdapter(MyAdapter.class)
public interface Specs {

    public BaseProperties getBaseProps();
    public void setBaseProps(BaseProperties baseProps);

}

MyAdapter.java :

public class MyAdapter extends XmlAdapter<Object,Object> 
{  
    public Object unmarshal(Object v) 
    { 
        return v; 
    }  
    public Object marshal(Object v) 
    { 
        return v; 
    }
}

RegSpecs.java

@XmlType
public class RegSpecs implements Specs{
private BaseProperties baseProps;

    public BaseProperties getBaseProps()
    {
        return baseProps;
    }
    public void setBaseProps(BaseProperties baseProps)
    {
        this.baseProps = baseProps;
    }

}

MapSpecs.java

@XmlType
public class MagSpecs implements Specs {

private BaseProperties baseProps;
private Features features;

    public BaseProperties getBaseProps()
    {
        return baseProps;
    }
    public void setBaseProps(BaseProperties baseProps)
    {
        this.baseProps = baseProps;
    }
    public Features getFeatures() {
        return features;
    }
    public void setFeatures(Features features) {
        this.features = features;
    }

}

Der Zugriff auf diesen Dienst führt zu folgendem Fehler:

javax.xml.bind.MarshalException - mit verknüpfter Ausnahme: [javax.xml.bind.JAXBException: weder die Klasse entities.MagSpecs noch eine ihrer Superklassen ist in diesem Kontext bekannt].

Wie kann ich meinen Kontext ändern? Ich verwende JAXB im Paket mit Jersey 1.5

Danke!

EDIT : In einem Versuch, meinen Kontext zu aktualisieren, habe ich diesen Code zu meiner Client (Ressource) Klasse hinzugefügt:

public class BookService  implements ContextResolver<JAXBContext> 
{

        private JAXBContext jaxbContext;

        public BookService() {
            try {
                // Bootstrap your JAXBContext will all necessary classes
                jaxbContext = JAXBContext.newInstance(Specs.class,MagSpecs.class, RegSpecs.class);
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }

        public JAXBContext getContext(Class<?> clazz) {
            if(BookService.class == clazz) {
                return jaxbContext;
            }
            return null;
        }

In diesem Fall erhalte ich den Fehler :

entities.Specs ist eine Schnittstelle, und JAXB kann nicht mit Schnittstellen umgehen. Dieses Problem hängt mit der folgenden Stelle zusammen: bei entities.Specs entities.Specs hat keinen no-arg Standardkonstruktor. dieses Problem hängt mit der folgenden Stelle zusammen: bei entities.Specs

3voto

Donal Fellows Punkte 125686

Der Kunde des Specs Schnittstelle muss wissen, dass MagSpecs kann eine Instanz davon sein, so dass es weiß, dass es für Tooling-Zwecke zu betrachten ist. Der einfachste Weg, dies zu tun, ist, eine @XmlSeeAlso Anmerkung zum Specs Schnittstelle:

@XmlSeeAlso({ MagSpecs.class, RegSpecs.class })
@XmlJavaTypeAdapter(MyAdapter.class) // Never needed this annotation myself...
public interface Specs {
    public BaseProperties getBaseProps();
    public void setBaseProps(BaseProperties baseProps);
}

Wenn ich mit JAXB-Annotationen arbeite, stelle ich im Allgemeinen sicher, dass ich viele Tests schreibe, um zu prüfen, ob ein XML-Schema aus den betreffenden Klassen generiert werden kann, und dass ich von jedem (vernünftigen) Einstiegspunkt in das Netz von Klassen und Schnittstellen ein vernünftiges Schema ohne Ausnahmen generieren kann. Zum Beispiel (und ich entschuldige mich dafür, dass dies ein bisschen lang ist):

private SchemaOutputResolver sink;
StringWriter schema;

@Before
public void init() {
    schema = new StringWriter();
    sink = new SchemaOutputResolver() {
        @Override
        public Result createOutput(String namespaceUri,
                String suggestedFileName) throws IOException {
            StreamResult sr = new StreamResult(schema);
            sr.setSystemId("/dev/null");
            return sr;
        }
    };
    Assert.assertTrue(schema.toString().isEmpty());
}

private void testJAXB(Class<?>... classes) throws Exception {
    JAXBContext.newInstance(classes).generateSchema(sink);
    Assert.assertTrue(schema.toString().length() > 0);
}

@Test
public void testJAXBForSpecs() throws Exception {
    testJAXB(Specs.class);
}

[EDIT]: Sie haben auch brauchen zum Ändern der Specs Schnittstelle in eine Klasse zu integrieren und die aktuellen Implementierungen von ihr erben zu lassen. Es kann eine vollständig abstrakte Klasse sein, wenn Sie wollen. Solange Sie keine schwerwiegenden Funktionen in die Klassen aufnehmen, sollte es funktionieren.

1voto

bdoughan Punkte 144925

EclipseLink JAXB (MOXy) kann Schnittstellen auf XML abbilden (Anmerkung: Ich bin der technische Leiter). Sie müssen sicher sein, dass Sie eine Erstellungsmethode für die entsprechende Objektfabrik haben, um ein konkretes Impl zurückzugeben:

MOXy integriert die Reinigung in REST-Umgebungen:

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X