开发者

How do I use the Jersey JSON POJO support?

I have an object that I'd like to serve in JSON as a RESTful resource. I have Jersey's JSON POJO support turned on like so (in 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>  

But when I try to access the resource, I get this exception:

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

The class th开发者_JS百科at I'm trying to serve isn't complicated, all it's got are some public final fields and a constructor that sets all of them. The fields are all strings, primitives, classes similar to this one, or Lists thereof (I've tried using plain Lists instead of generic List<T>s, to no avail). Does anyone know what gives? Thanks!

Java EE 6

Jersey 1.1.5

GlassFish 3.0.1


You can use @XmlRootElement if you want to use JAXB annotations (see other answers).

However, if you prefer pure POJO mapping, you must do the following (Unfortunately it isn't written in docs):

  1. Add jackson*.jar to your classpath (As stated by @Vitali Bichov);
  2. In web.xml, if you're using com.sun.jersey.config.property.packages init parameter, add org.codehaus.jackson.jaxrs to the list. This will include JSON providers in the scan list of Jersey.


This did it for me - Jersey 2.3.1

In the web.xml file :

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

In the pom.xml file :

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


Jersey-json has a JAXB implementation. The reason you're getting that exception is because you don't have a Provider registered, or more specifically a MessageBodyWriter. You need to register a proper context within your provider:

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

This looks up for an @XmlRegistry within the provided package name, which is a package that contains @XmlRootElement annotated POJOs.

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

then create an ObjectFactory in the same package:

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

With the @Provider registered, Jersey should facilitate the marshalling for you in your resource:

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}


I followed the instructions here which show how to use Jersey and Jackson POJOs(as opposed to JAXB). It worked with Jersey 1.12 as well.


Why are you using final fields? I'm using jersey and i have some JAXB objects/pojos and all i had to do was simply annotate my resource method with @Produces("application/json") and it works out of the box. I didn't have to mess with the web.xml. Just make sure your pojos are annotated correctly.

Here is a simple 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;
    }


}


You've probably already figured this out, but all you need to do is add these jackson jars to your classpath: jackson-core, jackson-jaxrs, jackson-mapper, and jackson-xc

It appears that there is another way, as others have noted. Add this to your "com.sun.jersey.config.property.packages" parameter (if using tomcat and web.xml): "org.codehaus.jackson.jaxrs", like so:

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

Doing this will also require the same jackson jars on your classpath


Jersey 2.0 provides support for JSON using MOXy an Jackson.

MOXy support is enabled by default if the JAR exists in the classpath and Jackson support can be enabled using a Feature. This is all explained in detail in Jersey 2.0 User Guide chapter on JSON Binding:

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

To add MOXy support without the need for configuration add the following dependency to you maven pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>


I'm new to this but I was able to use POJOs after adding the jackson-all-1.9.0.jar to the classpath.


The following worked for me. I'm using Jersey 2.7 with Jackson with Apache Felix (OSGi) running on Tomcat6.

public class MyApplication extends ResourceConfig {

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

And then, in your web.xml (or in my case, just a Hashtable), you would specify your javax.ws.rs.Application like so

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

No need to specify com.sun.jersey.config.property.pacakges or com.sun.jersey.api.json.POJOMappingFeature

Just make sure you specify dependency on

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


Moving jersey-json dependency to the top of the pom.xml solved this problem for me.

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

  <!-- other dependencies -->

</dependencies>


This worked in Jersey 2.30:

In pom.xml:

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

In WEB-INF/web.xml:

<servlet>
  <servlet-name>My Jersey REST Service</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <load-on-startup>1</load-on-startup>
  <!-- ATTENTION: Use Jackson for JSON: -->
  <init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
  </init-param>
  <!-- ... -->
  <init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>com.example.myapp</param-value>
  </init-param>
</servlet>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜