REST / JAXB ошибка Джерси, сопоставление интерфейса - PullRequest
3 голосов
/ 08 февраля 2011

Мне нужно использовать интерфейс в моем веб-сервисе REST. Вот интерфейс 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;
    }

}

При доступе к этой услуге выдается следующая ошибка:

javax.xml.bind.MarshalException - со связанным исключением: [javax.xml.bind.JAXBException: класс entity.MagSpecs или любой из его суперкласса известны этому контексту.]

Как изменить мой контекст? Я использую JAXB в комплекте с Джерси 1.5

Спасибо!

РЕДАКТИРОВАТЬ: пытаясь обновить свой контекст, я добавил этот код в мой класс клиента (ресурса):

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

В этом случае я получаю ошибку:

entity.Specs - это интерфейс, и JAXB не может обрабатывать интерфейсы. эта проблема связана со следующим местоположением: на лицах. Спецификации entity.Specs не имеет конструктора по умолчанию без аргументов. эта проблема связана со следующим местоположением: у юридических лиц. Спецификации

Ответы [ 2 ]

3 голосов
/ 08 февраля 2011

Клиент интерфейса Specs должен знать, что MagSpecs может быть его экземпляром, чтобы он мог смотреть на него в целях инструментов. Самый простой способ сделать это - поместить аннотацию @XmlSeeAlso в интерфейс Specs:

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

В общем, всякий раз, когда я работаю с аннотациями JAXB, я пишу множество тестов, чтобы проверить, можно ли сгенерировать схему XML из рассматриваемых классов, проверяя ее из каждой (вменяемой) точки входа в сеть Классы и интерфейсы Я могу генерировать разумную схему без исключений. Например (и я прошу прощения за это немного долго):

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]: вам также нужно , чтобы изменить интерфейс Specs на класс и получить от него текущие реализации. Это может быть полностью абстрактный класс, если хотите. Пока вы не вносите серьезную функциональность в классы, это должно работать.

1 голос
/ 10 февраля 2011

EclipseLink JAXB (MOXy) может отображать интерфейсы в XML (обратите внимание, я технический руководитель).Вы должны быть уверены, что у вас есть метод create на соответствующей фабрике объектов для возврата конкретного значения:

MOXy интегрирует очистку в среды REST:

...