Как использовать поддержку Jersey JSON POJO? - PullRequest
40 голосов
/ 02 марта 2011

У меня есть объект, который я хотел бы использовать в JSON как ресурс RESTful. У меня включена поддержка JSON POJO на Джерси (в 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>  

Но когда я пытаюсь получить доступ к ресурсу, я получаю следующее исключение:

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

Класс, который я пытаюсь обслуживать, не сложен, все, что у него есть, это некоторые открытые финальные поля и конструктор, который устанавливает их все. Все поля - это строки, примитивы, классы, подобные этому, или их списки (я пытался использовать простые списки вместо общих списков s, но безрезультатно). Кто-нибудь знает, что дает? Спасибо!

Java EE 6

Джерси 1.1.5

GlassFish 3.0.1

Ответы [ 10 ]

15 голосов
/ 26 сентября 2012

Вы можете использовать @XmlRootElement, если хотите использовать аннотации JAXB (см. Другие ответы).

Однако, если вы предпочитаете чистое отображение POJO, вы должны сделать следующее (К сожалению, оно не записано в документах):

  1. Добавьте Джексона * .jar к вашему пути к классам (Как сказал @Vitali Bichov);
  2. В web.xml, если вы используете com.sun.jersey.config.property.packages параметр init, добавьте org.codehaus.jackson.jaxrs в список. Это будет включать поставщиков JSON в список сканирования Джерси.
12 голосов
/ 02 марта 2011

Джерси-json имеет реализацию JAXB. Причина, по которой вы получаете это исключение, заключается в том, что у вас нет зарегистрированного поставщика или, более конкретно, MessageBodyWriter . Вам необходимо зарегистрировать правильный контекст в вашем провайдере:

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

Это ищет @XmlRegistry в предоставленном имени пакета, который является пакетом, который содержит @XmlRootElement аннотированных POJO.

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

затем создайте ObjectFactory в том же пакете:

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

Зарегистрировав @Provider, Джерси должен упростить для вас сортировку на вашем ресурсе:

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}
11 голосов
/ 28 сентября 2013

Это сделало это для меня - Джерси 2.3.1

В файле web.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>

В файле pom.xml:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
10 голосов
/ 26 апреля 2012

Я следовал инструкциям здесь , которые показывают, как использовать POJO Джерси и Джексона (в противоположность JAXB) Это работало и с Джерси 1.12.

3 голосов
/ 24 июля 2013

Jersey 2.0 обеспечивает поддержку JSON с использованием MOXy и Jackson.

Поддержка MOXy включена по умолчанию, если JAR существует в пути к классам, и поддержку Jackson можно включить с помощью функции.Все это подробно объясняется в главе «Руководство пользователя Jersey 2.0» по привязке JSON:

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

Чтобы добавить поддержку MOXy без необходимости настройки, добавьте следующую зависимость для вас, maven pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>
3 голосов
/ 20 июля 2013

Вы, наверное, уже поняли это, но все, что вам нужно сделать, это добавить эти джексоновые банки в ваш classpath: jackson-core, jackson-jaxrs, jackson-mapper и jackson-xc

Похоже, что есть и другой путь, как отметили другие. Добавьте это в ваш параметр «com.sun.jersey.config.property.packages» (при использовании tomcat и web.xml): «org.codehaus.jackson.jaxrs», например так:

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

Для этого также потребуются те же банки Джексона на вашем пути к классам

3 голосов
/ 02 марта 2011

Почему вы используете последние поля? Я использую джерси, у меня есть несколько объектов / pojos JAXB, и все, что мне нужно было сделать, это просто аннотировать мой метод ресурсов с помощью @Produces ("application / json"), и он работает из коробки. Мне не нужно было связываться с web.xml. Просто убедитесь, что ваши pojos аннотированы правильно.

Вот простое пойо

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


}
2 голосов
/ 28 августа 2012

Я новичок в этом, но я смог использовать POJO после добавления jackson-all-1.9.0.jar в classpath.

1 голос
/ 08 сентября 2014

Перемещение jersey-json зависимости к вершине pom.xml решило эту проблему для меня.

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

  <!-- other dependencies -->

</dependencies>
1 голос
/ 21 марта 2014

Следующее сработало для меня. Я использую Джерси 2.7 с Джексоном с Apache Felix (OSGi), работающим на Tomcat6.

public class MyApplication extends ResourceConfig {

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

И затем, в вашем web.xml (или в моем случае, просто Hashtable), вы бы указали свой javax.ws.rs.Application, например,

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

Не нужно указывать com.sun.jersey.config.property.pacakges или com.sun.jersey.api.json.POJOMappingFeature

Просто убедитесь, что вы указали зависимость от

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>
...