Как использовать поддержку JSON POJO в Джерси?
У меня есть объект, который я хотел бы использовать в 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
...
Класс, который я пытаюсь выполнить, не является сложным, все, что у него есть, - это некоторые публичные конечные поля и конструктор, который устанавливает все из них. Поля - это все строки, примитивы, классы, подобные этому, или их списки (я пробовал использовать простые списки вместо общего списка <T> s, безрезультатно). Кто-нибудь знает, что дает? Спасибо!
Java EE 6
Джерси 1.1.5
GlassFish 3.0.1
Ответы
Ответ 1
Джерси-джсон имеет реализацию JAXB. Причина, по которой вы получаете это исключение, состоит в том, что у вас нет зарегистрированного Provider или, более конкретно, 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();
}
Ответ 2
Вы можете использовать @XmlRootElement
, если хотите использовать аннотации JAXB (см. другие ответы).
Однако, если вы предпочитаете чистое сопоставление POJO, вы должны сделать следующее (к сожалению, оно не написано в документах):
- Добавить jackson *.jar в ваш путь к классу (как указано @Vitali Bichov);
- В web.xml, если вы используете параметр
com.sun.jersey.config.property.packages
init, добавьте org.codehaus.jackson.jaxrs
в список. Это будет включать поставщиков JSON в списке сканирования Джерси.
Ответ 3
Это сделало это для меня - Джерси 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>
Ответ 4
Я выполнил инструкции здесь, в которых показано, как использовать Джерси и POJO Джексона (в отличие от JAXB). Он работал с Джерси 1.12.
Ответ 5
Почему вы используете конечные поля?
Я использую трикотаж, и у меня есть некоторые объекты /pojos JAXB, и все, что мне нужно было сделать, это просто аннотировать мой метод ресурсов с помощью @Produces ( "application/json" ), и он работает из коробки. Мне не нужно было возиться с web.xml. Просто убедитесь, что ваши pojos аннотированы правильно.
Вот простое pojo
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;
}
}
Ответ 6
Вы, наверное, уже поняли это, но все, что вам нужно сделать, это добавить эти джэксон-банки в ваш путь к классу: 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>
Для этого также потребуются те же самые джойстики Jackcl на пути к классу
Ответ 7
Джерси 2.0 обеспечивает поддержку JSON, используя MOXy Jackson.
Поддержка MOXy включена по умолчанию, если JAR существует в пути к классам, и поддержка Jackson может быть включена с помощью функции. Это подробно объясняется в главе руководства пользователя Джерси 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>
Ответ 8
Я новичок в этом, но я смог использовать POJO после добавления jackson-all-1.9.0.jar в путь к классам.
Ответ 9
Следующие работали для меня. Я использую Jersey 2.7 с Jackson с 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>
Ответ 10
Перемещение jersey-json
зависимости от вершины pom.xml решило эту проблему для меня.
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18.1</version>
</dependency>
<!-- other dependencies -->
</dependencies>