2012-09-07 12 views
6

Estoy usando JAX RS para crear un servicio web REST utilizando el @Path, @GET, @Produces({"application/json, "application/xml"}) habitual.JAX RS - Error de referencia circular/cíclica JSON y XML

Devuelvo un POJO como respuesta que se envía como JSON o XML según el tipo de solicitud. Funcionaba bien hasta que agregué una relación Many-To-Many con otra entidad. La relación es bidireccional.

Estoy usando JBoss AS 7. Agregué Jackson's @JsonManagedReference y @JsonBackReference pero fue en vano.

¿Cómo superar esto?

desplegué mis JAX RS como esto: -

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd" version="3.0"> 
    <servlet> 
     <servlet-name>javax.ws.rs.core.Application</servlet-name> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>javax.ws.rs.core.Application</servlet-name> 
     <url-pattern>/rest/*</url-pattern> 
    </servlet-mapping> 
</web-app>  

no me extiendo cualquier clase de aplicación o usado cualquier clase de activador JAXRS.

Este RESTEasy de JBoss utiliza a Jackson como su proveedor JSON, incluso entonces ¿por qué no reconoce las anotaciones @JsonManagedReference?

¿Tengo que actualizar las dependencias? Si es así, ¿cómo? Y cómo solucionarlo si la solicitud es de XML, allí también falla en referencia circular en JAXB.

¡Gracias de antemano!

+1

¿Has visto esta pregunta? http://stackoverflow.com/questions/3073364/jaxb-mapping-cyclic-references-to-xml – Tomalak

+0

Gracias, lo estoy investigando, pero aún deja a JSON a la vista, ¿no? – Stuarty

+1

Supongo que debe haber un enfoque análogo para JSON. (No sé, sin embargo. La pregunta sonaba razonablemente similar, así que quería vincularlos). – Tomalak

Respuesta

4

Nota: Soy el líder EclipseLink JAXB (MOXy) y miembro del grupo de expertos JAXB (JSR-222).

MOXy ofrece la extensión @XmlInverseReference que se puede utilizar para admitir relaciones bidireccionales en enlace XML y JSON.


JAVA MODELO

cliente

Customer tiene una colección de objetos PhoneNumber.

package forum12312395; 

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
public class Customer { 

    private List<PhoneNumber> phoneNumbers; 

    @XmlElement(name="phone-number") 
    public List<PhoneNumber> getPhoneNumbers() { 
     return phoneNumbers; 
    } 

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) { 
     this.phoneNumbers = phoneNumbers; 
    } 

} 

Fax

Cada objeto PhoneNumber mantiene un puntero al objeto Customer. Esta propiedad está anotada con @XmlInverseReference.

package forum12312395; 

import javax.xml.bind.annotation.XmlValue; 
import org.eclipse.persistence.oxm.annotations.XmlInverseReference; 

public class PhoneNumber { 

    private String value; 
    private Customer customer; 

    @XmlValue 
    public String getValue() { 
     return value; 
    } 

    public void setValue(String value) { 
     this.value = value; 
    } 

    @XmlInverseReference(mappedBy="phoneNumbers") 
    public Customer getCustomer() { 
     return customer; 
    } 

    public void setCustomer(Customer customer) { 
     this.customer = customer; 
    } 

} 

jaxb.propiedades

Para utilizar moxy como su proveedor de JAXB es necesario incluir un archivo llamado jaxb.properties en el mismo paquete que el modelo de dominio con la siguiente entrada (ver: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

ENTRADA

A continuación se encuentran los documentos que vamos a desempatar en este ejemplo

input.xml

<?xml version="1.0" encoding="UTF-8"?> 
<customer> 
    <phone-number>555-WORK</phone-number> 
    <phone-number>555-HOME</phone-number> 
</customer> 

input.json

{ 
    "customer" : { 
     "phone-number" : ["555-HOME", "555-WORK"] 
    } 
} 

DEMO

package forum12312395; 

import javax.xml.bind.*; 
import javax.xml.transform.stream.StreamSource; 
import org.eclipse.persistence.jaxb.UnmarshallerProperties; 
import org.eclipse.persistence.oxm.MediaType; 

public class Demo { 

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

     // JSON 
     Unmarshaller jsonUnmarshaller = jc.createUnmarshaller(); 
     jsonUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON); 
     StreamSource json = new StreamSource("src/forum12312395/input.json"); 
     Customer customerFromJSON = (Customer) jsonUnmarshaller.unmarshal(json); 
     for(PhoneNumber phoneNumber : customerFromJSON.getPhoneNumbers()) { 
      System.out.println(phoneNumber.getCustomer()); 
     } 

     // XML 
     Unmarshaller xmlUnmarshaller = jc.createUnmarshaller(); 
     StreamSource xml = new StreamSource("src/forum12312395/input.xml"); 
     Customer customerFromXML = (Customer) xmlUnmarshaller.unmarshal(xml); 
     for(PhoneNumber phoneNumber : customerFromXML.getPhoneNumbers()) { 
      System.out.println(phoneNumber.getCustomer()); 
     } 
    } 

} 

SALIDA

a continuación es el resultado de la ejecución del código de demostración. Como puede ver, la propiedad customer se completa en todos los objetos PhoneNumber.

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

PARA MÁS INFORMACIÓN