NPE Брошенный Маршаллинг в JAX-RS - PullRequest
5 голосов
/ 23 июля 2010

У меня есть веб-сервис JAX-RS, который использует классы сущностей JPA. У меня есть такой класс ресурсов:

@Path("/entity")
public class MyEntityResource
{
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("/{entity}")
    public MyEntity getMyEntity(@PathParam("entity") String entity)
    {
        log.debug("Entering getMyEntity with param: " + entity);
        MyEntity entityObject = genericService.find(MyEntity.class, entity);

        if (entityObject == null)
        {
            log.debug("Entity not found.");
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }

        log.debug("Exiting getMyEntity");

        return entityObject;
    }
}

Когда я запускаю службу и выполняю вызов get для объекта, я получаю эту ошибку:

SEVERE: The response of the WebApplicationException cannot be utilized as the response is already committed. Re-throwing to the HTTP container
javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
 - with linked exception:
[Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: java.lang.NullPointerException]
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:151)
... 
<snip>
... 
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: java.lang.NullPointerException]
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:271)
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:171)
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:149)
    ... 32 more
Caused by: Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: java.lang.NullPointerException
    at org.eclipse.persistence.exceptions.XMLMarshalException.marshalException(XMLMarshalException.java:76)
    at org.eclipse.persistence.oxm.XMLMarshaller.marshal(XMLMarshaller.java:502)
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:269)
    ... 34 more
Caused by: java.lang.NullPointerException
    at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConverted(ConversionException.java:69)
... 
<snip>
... 
    at org.eclipse.persistence.oxm.XMLMarshaller.marshal(XMLMarshaller.java:916)
    at org.eclipse.persistence.oxm.XMLMarshaller.marshal(XMLMarshaller.java:468)
    ... 35 more

Нигде ни в одной из трассировок стека не упоминается ни один из моих классов. Кроме того, оператор "Exiting getMyEntity" регистрируется перед исключением.

Понятия не имею, что бросает NPE или как его отладить.

До этой ошибки я получал [com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: от своих классов сущностей JPA (EclipseLink) и добавил аннотацию MOXy @XmlInverseReference в мой дочерний класс в родительском методе получения.

Есть мысли о том, что может вызвать это исключение?

Ответы [ 2 ]

4 голосов
/ 26 июля 2010

Мы провели некоторое автономное обсуждение этой проблемы, и в интересах других, которые находят этот пост ниже, правильная настройка использования @XmlInverseReference на нескольких уровнях:

Сущность A

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import java.util.Set;

@Entity
@XmlRootElement
public class EntityA implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Set<EntityB> entityBs;

    @Id
    @XmlAttribute
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(mappedBy = "entityABean")
    @XmlElement
    public Set<EntityB> getEntityBs() {
        return this.entityBs;
    }

    public void setEntityBs(Set<EntityB> entityBs) {
        this.entityBs = entityBs;
    }

}

Сущность B

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlInverseReference;

import java.util.Set;

@Entity
@XmlRootElement
public class EntityB implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Set<EntityC> entityCs;
    private EntityA entityABean;

    @Id
    @XmlAttribute
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne
    @JoinColumn(name = "EntityA")
    @XmlInverseReference(mappedBy = "entityBs")
    public EntityA getEntityABean() {
        return this.entityABean;
    }

    public void setEntityABean(EntityA entityABean) {
        this.entityABean = entityABean;
    }

    @OneToMany(mappedBy = "entityBBean")
    @XmlElement
    public Set<EntityC> getEntityCs() {
        return this.entityCs;
    }

    public void setEntityCs(Set<EntityC> entityCs) {
        this.entityCs = entityCs;
    }
}

Сущность C

import java.io.Serializable;
import javax.persistence.*;

import org.eclipse.persistence.oxm.annotations.XmlInverseReference;

@Entity
public class EntityC implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private EntityB entityBBean;

    @Id
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne
    @JoinColumn(name = "EntityB")
    @XmlInverseReference(mappedBy = "entityCs")
    public EntityB getEntityBBean() {
        return this.entityBBean;
    }

    public void setEntityBBean(EntityB entityBBean) {
        this.entityBBean = entityBBean;
    }
}

Демо

import java.io.FileInputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(EntityA.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        FileInputStream xml = new FileInputStream("src/test/jaxb/input.xml");
        EntityA a = (EntityA) unmarshaller.unmarshal(xml);

        for(EntityB b : a.getEntityBs()) {
            System.out.println(b.getEntityABean());
            for(EntityC c : b.getEntityCs()) {
                System.out.println(c.getEntityBBean());
            }
        }
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(a, System.out);
    }

}

Демонстрация - Вывод

test.jaxb.EntityA@1292d26
test.jaxb.EntityB@196c1b0
test.jaxb.EntityB@196c1b0
test.jaxb.EntityA@1292d26
test.jaxb.EntityB@1e13d52
test.jaxb.EntityB@1e13d52

Input.xml

<?xml version="1.0" encoding="UTF-8"?>
<entityA>
   <entityBs>
      <entityCs/>
      <entityCs/>
   </entityBs>
   <entityBs>
      <entityCs/>
      <entityCs/>
   </entityBs>
</entityA>

Эта проблема также решается на форумах EclipseLink, для получения дополнительной информации см .:

Ниже приведен еще один пример использования @XmlInverseReference с моделью JPA

1 голос
/ 23 июля 2010

Включили ли вы файл jaxb.properties в ваши классы сущностей?

Проверьте ответ Блейза на этот вопрос: JAXB Отображение циклических ссылок на XML

Надеюсь, это поможет.RG

...