2010-07-22 24 views
5

Tengo un servicio web JAX-RS que hace uso de clases de entidad JPA. Tengo una clase de recurso así:NPE Throwwn Marshalling Entity en JAX-RS

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

Cuando ejecuto el servicio y hacer una llamada get en la entidad, me sale este error:

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 

En ninguna parte de cualquiera de los seguimientos de pila son cualquier de mis clases referenciadas. Además, la declaración "Exiting getMyEntity" se registra antes de la excepción.

No tengo idea de qué está arrojando el NPE o cómo solucionarlo.

Antes de este error, obtenía un [com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: de mis clases de entidad JPA (EclipseLink) y añadí la anotación MOXy @XmlInverseReference a mi clase secundaria en el método getter principal.

¿Alguna idea de qué podría estar arrojando esta excepción?

Respuesta

4

Hemos tenido algunas discusiones en línea sobre este tema, y ​​para el beneficio de otros que se encuentran por debajo de esta entrada es la correcta configuración de utilizar @XmlInverseReference en múltiples niveles:

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

} 

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

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

demostración

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

} 

Demo - Salida

[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

input.xml

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

Esta cuestión también está siendo manejado en los foros EclipseLink, para más información ver:

A continuación se muestra otro ejemplo del uso @XmlInverseReference con un modelo de APP

+0

Además de lo anterior, el NPE fue causado por un campo Timestamp en una clase/elemento nieto que era nulo. Extendí XmlAdapter para manejar la clasificación de marcas de tiempo y esto arrojó el NPE. – sdoca

1

¿Incluyó un archivo jaxb.properties con sus clases de entidad?

Salida respuesta de Blaise a esta pregunta: JAXB Mapping cyclic references to XML

Espero que esto ayude. RG

+0

Desde el seguimiento de la pila, el archivo jaxb.properties parece estar en su lugar. –

+0

Gracias por responder. Sí, tengo un jaxb.archivo de propiedades con estos contenidos: # Especificar que la aplicación EclipseLink moxy JAXB se debe utilizar javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory Creo que se está leyendo, porque el seguimiento de la pila se refiere a: org.eclipse.persistence.jaxb.JAXBMarshaller.marshal (JAXBMarshaller.java:271) vi el otro post, que es donde aprendí sobre moxy y la anotación @XmlInverseReference que utilicé en mi código . – sdoca

Cuestiones relacionadas