¿Cómo uso el soporte JSON POJO de Jersey?


Tengo un objeto que me gustaría servir en JSON como un recurso RESTful. Tengo el soporte JSON POJO de Jersey activado así (en web.xml):

<servlet>  
    <servlet-name>Jersey Web Application</servlet-name>  
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>  

Pero cuando intento acceder al recurso, obtengo esta excepción:

SEVERE: A message body writer for Java type, class com.example.MyDto, and MIME media type, application/json, was not found
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException
...

La clase que estoy tratando de servir no es complicada, todo lo que tiene son algunos campos finales públicos y un constructor que establece todos ellos. Los campos son todas cadenas, primitivas, clases similares a esta, o Listas de las mismas (he intentado usar listas simples en lugar de Lista genérica s, en vano). ¿Alguien sabe lo que da? ¡Gracias!

Java EE 6

Jersey 1.1.5

GlassFish 3.0.1

Author: Nick, 2011-03-02

10 answers

Jersey-json tiene una implementación JAXB. La razón por la que está recibiendo esa excepción es porque no tiene un Proveedor registrado, o más específicamente un MessageBodyWriter. Necesita registrar un contexto apropiado dentro de su proveedor:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final static String ENTITY_PACKAGE = "package.goes.here";
    private final static JAXBContext context;
    static {
        try {
            context = new JAXBContextAdapter(new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(false).build(), ENTITY_PACKAGE));
        } catch (final JAXBException ex) {
            throw new IllegalStateException("Could not resolve JAXBContext.", ex);
        }
    }

    public JAXBContext getContext(final Class<?> type) {
        try {
            if (type.getPackage().getName().contains(ENTITY_PACKAGE)) {
                return context;
            }
        } catch (final Exception ex) {
            // trap, just return null
        }
        return null;
    }

    public static final class JAXBContextAdapter extends JAXBContext {
        private final JAXBContext context;

        public JAXBContextAdapter(final JAXBContext context) {
            this.context = context;
        }

        @Override
        public Marshaller createMarshaller() {
            Marshaller marshaller = null;
            try {
                marshaller = context.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            } catch (final PropertyException pe) {
                return marshaller;
            } catch (final JAXBException jbe) {
                return null;
            }
            return marshaller;
        }

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException {
            final Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        }

        @Override
        public Validator createValidator() throws JAXBException {
            return context.createValidator();
        }
    }
}

Esto busca un @XmlRegistry dentro del nombre del paquete proporcionado, que es un paquete que contiene @XmlRootElement POJOs anotados.

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

Luego crea una ObjectFactory en el mismo paquete:

@XmlRegistry
public class ObjectFactory {
   public Person createNewPerson() {
      return new Person();
   }
}

Con el @Provider registrado, Jersey debe facilitar el marshalling para usted en su recurso:

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}
 12
Author: hisdrewness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-02 03:54:59

Puede usar @XmlRootElement si desea usar anotaciones JAXB (vea otras respuestas).

Sin embargo, si prefiere el mapeo POJO puro, debe hacer lo siguiente (Desafortunadamente no está escrito en documentos):

  1. Añadir jackson*.jar a su classpath (Según lo declarado por @Vitali Bichov);
  2. En la web.xml, si está utilizando el parámetro init com.sun.jersey.config.property.packages, agregue org.codehaus.jackson.jaxrs a la lista. Esto incluirá proveedores JSON en la lista de análisis de Jersey.
 15
Author: gamliela,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-28 15:01:43

Esto lo hizo por mí - Jersey 2.3.1

En la web.archivo xml:

<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value><my webapp packages>;org.codehaus.jackson.jaxrs</param-value>
</init-param>
</servlet>

En el pom.archivo xml:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
 11
Author: yann-h,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-28 00:28:24

Seguí las instrucciones aquí que muestran cómo usar Jersey y Jackson POJOs(a diferencia de JAXB). También funcionó con Jersey 1.12.

 10
Author: bytesmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-25 21:02:03

¿Por qué está utilizando los campos finales? Estoy usando jersey y tengo algunos objetos / pojos JAXB y todo lo que tenía que hacer era simplemente anotar mi método de recurso con @Produce("aplicación/json") y funciona fuera de la caja. No tuve que meterme con la web.XML. Solo asegúrate de que tus pojos estén anotados correctamente.

Aquí hay un pojo simple

package test;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class SampleJaxbObject {

    private String field1;

    private Integer field2;

    private String field3;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return field2;
    }

    public void setField2(Integer field2) {
        this.field2 = field2;
    }

    public String getField3() {
        return field3;
    }

    public void setField3(String field3) {
        this.field3 = field3;
    }


}
 3
Author: Ricardo Riveros,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-01 23:17:58

Probablemente ya hayas descubierto esto, pero todo lo que necesitas hacer es agregar estos frascos de jackson a tu classpath: jackson-core, jackson-jaxrs, jackson-mapper y jackson-xc

Parece que hay otro camino, como otros han señalado. Añadir esto a su " com.sol.Jersey.config.propiedad.paquetes " parámetro (si se utiliza tomcat y web.xml): "org.codehaus.jackson.jaxrs", así:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>org.codehaus.jackson.jaxrs</param- value>
</init-param>

Hacer esto también requerirá los mismos frascos jackson en su classpath

 3
Author: ChrisO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-20 00:09:22

Jersey 2.0 proporciona soporte para JSON usando MOXy y Jackson.

El soporte de MOXy está habilitado por defecto si el JAR existe en el classpath y el soporte de Jackson se puede habilitar usando una Característica. Todo esto se explica en detalle en el capítulo de la Guía del usuario de Jersey 2.0 sobre la unión JSON:

Https://jersey.java.net/documentation/latest/media.html#json

Para agregar soporte MOXy sin necesidad de configuración, agregue la siguiente dependencia a maven pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>
 3
Author: Arun Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 14:25:33

Soy nuevo en esto, pero pude usar POJOs después de agregar el jackson-all-1.9.0.jar al classpath.

 2
Author: Vitali Bichov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-27 23:00:51

Lo siguiente funcionó para mí. Estoy usandoJersey 2.7 con Jackson con Apache Felix (OSGi) ejecutándose en Tomcat6.

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        super(JacksonFeature.class);
        // point to packages containing your resources
        packages(getClass().getPackage().getName());
    }
}

Y luego, en su web.xml (o en mi caso, solo un Hashtable), usted especificaría su javax.ws.rs.Application así

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value><MyApplication.class.getName()></param-value>
</init-param>

No es necesario especificar com.sun.jersey.config.property.pacakges o com.sun.jersey.api.json.POJOMappingFeature

Solo asegúrese de especificar la dependencia en

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>
 1
Author: shreyas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-20 20:04:30

Mover jersey-json dependencia a la parte superior del pom.xml resolvió este problema para mí.

<dependencies>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
  </dependency>

  <!-- other dependencies -->

</dependencies>
 1
Author: supercobra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-08 11:22:15