Проблема с JAXB маршалингом объекта: javax.xml.bind.JAXBException: class ... или любой из его суперкласса известен в этом контексте - PullRequest
4 голосов
/ 02 декабря 2010

В моем проекте JAX-RS (Джерси) у меня возникла проблема с переносом одного из аннотированных JAXB объектов в JSON. Вот сообщение об ошибке, которое я вижу в журналах:

SEVERE: внутренняя ошибка сервера javax.ws.rs.WebApplicationException: javax.xml.bind.JAXBException: класс com.dnb.applications.webservice.mobile.view.CompaniesAndLocations, ни один из его суперклассов не известен этому контексту.

Указывает ли это на какую-то конкретную проблему? У моего ресурса есть такой метод:

@Path("/name/{companyname}/location/{location}")
@Produces("application/json; charset=UTF-8;")
@Consumes("application/json")
@POST
public Viewable findCompanyByCompanyNameAndLocationAsJSON(@PathParam("companyname") String companyName,
        @PathParam("location") String location, CriteriaView criteria) {
    criteria = criteria != null ? criteria : new CriteriaView();
    criteria.getKeywords().setCompanyName(companyName);
    return getCompanyListsHandler().listsByCompanyNameAndLocation(criteria, location);
}

Viewable - пустой интерфейс. Вышеуказанный метод возвращает объект типа CompaniesAndLocations, определенный следующим образом:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "companiesAndLocations", propOrder = { "count", "normalizedLocations", "companyList", "companyMap", "modifiers",
        "modifiersMap", "companyCount", "navigators" })
public class CompaniesAndLocations extends BaseCompanies implements Viewable {

    @XmlElement(name = "normalizedLocations", required = false)
    protected List<NormalizedLocation> normalizedLocations;

    public List<NormalizedLocation> getNormalizedLocations() {
        if (normalizedLocations == null) {
            normalizedLocations = new ArrayList<NormalizedLocation>();
        }
        return normalizedLocations;
    }

}

BaseCompanies определяет ряд других полей:

@XmlTransient
public abstract class BaseCompanies {

    @XmlElement(name = "modifiers", required = false)
    private List<Modifiers> modifiers;
....

Я должен добавить, что я немного отклоняюсь от подхода, используемого другим рабочим кодом в приложении. Другие методы ресурсов получают свои объекты из ObjectFactory, помеченного @XmlRegistry. Я не думаю, что это необходимо, хотя. Я видел другой код, который непосредственно создает JAXB-аннотированный POJO без использования фабрики ObjectFactory.

Есть идеи?

1 Ответ

7 голосов
/ 04 декабря 2010

JAX-RS делает все возможное, чтобы загрузить JAXBContext, но он не всегда может охватить все классы, о которых ему нужно знать. По этой причине вы можете реализовать ContextResolver. Это дает вам полный контроль над тем, как создается JAXBContext. Ниже приведен пример того, как это может выглядеть:

package org.example.order;

import javax.ws.rs.Produces;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.JAXBContextFactory;

@Provider
@Produces({"application/xml", "application/json"})
public class PurchaseOrderContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext jaxbContext;

    public PurchaseOrderContextResolver() {
        try {
            // Bootstrap your JAXBContext will all necessary classes
            jaxbContext = JAXBContext.newInstance(PurchaseOrder.class);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

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

}
...