2010-07-22 15 views
5

Mam usługę sieciową JAX-RS, która korzysta z klas jednostek JPA. Mam klasy zasobu takiego:Neph Thrown Marshalling Entity w 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; 
    } 
} 

Kiedy uruchomić usługę i wykonać połączenia dostać się na podmiot, otrzymuję ten błąd:

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 

nigdzie w żadnej z ślady stosu są wszelkie z moich klas wymienionych. Ponadto instrukcja "Exiting getMyEntity" jest rejestrowana przed wyjątkiem.

Nie mam pojęcia, co rzuca NPE lub jak to debugować.

Przed tym błędem otrzymywałem [com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: z moich klas jednostek JPA (EclipseLink) i dodałem adnotację MOXy @XmlInverseReference do mojej klasy potomnej w metodzie parenter.

Jakieś przemyślenia na temat tego, co może rzucić ten wyjątek?

Odpowiedz

4

Mieliśmy trochę nieaktywny dyskusję na temat tego problemu i dla dobra innych, że ten post poniżej jest poprawna konfiguracja z użyciem @XmlInverseReference na wielu poziomach:

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

} 

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

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

Demo

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 - Wyjście

[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> 

Ten problem jest również obsługiwane na forach EclipseLink, aby uzyskać więcej informacji, patrz:

Poniżej jest kolejnym przykładem wykorzystania @XmlInverseReference z JPA modelu

+0

W związku z powyższym NPE zostało spowodowane z pola Znacznik czasu w klasie/elemencie wnuka, który miał wartość zerową. Rozszerzyłem XmlAdapter, aby obsłużyć zestawienie znaczników czasu, a to rzuciło NPE. – sdoca

1

Czy dołączono plik jaxb.properties do klas encji?

Wyjazd Blaise odpowiedź na to pytanie: JAXB Mapping cyclic references to XML

Nadzieja to pomaga. RG

+0

Od ślad stosu, plik jaxb.properties wydaje się być na swoim miejscu. –

+0

Dzięki za odpowiedź. Tak, mam jaxb.właściwości pliku z tych treści: # określić, że realizacja EclipseLink Moxy JAXB należy stosować javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory wierzę, że są odczytywane, ponieważ ślad stosu odnosi się do: org.eclipse.persistence.jaxb.JAXBMarshaller.marshal (JAXBMarshaller.java:271) Widziałem inny post, gdzie dowiedziałem się o MOXy i adnotacji @XmlInverseReference, których użyłem w moim kodzie . – sdoca