How to Use the Jersey JSON Pojo Support

How do I use the Jersey JSON POJO support?

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

Jersey 2.x does not support POJO to json?

Yeah so the Jersey distribution doesn't come with any JSON/POJO support. You need to find them yourself and add them to your project.

If you want to use the JacksonFeature, then you need to grab all the jars for it. You can specify any class you want in the provider classes param, but if you don't actually have it, nothing will happen. You are not even told by any exceptions.

These are all the jars you need

  • jersey-media-json-jackson-2.17
  • jersey-entity-filtering-2.17
  • jackson-jaxrs-json-provider-2.3.2
  • jackson-core-2.3.2
  • jackson-databind-2.3.2
  • jackson-annotations-2.3.2
  • jackson-jaxrs-base-2.3.2
  • jackson-module-jaxb-annotations-2.3.2

Note that these are all the jars that are used for Jersey 2.17. If you are using a newer version, then you should go here, and select the version of Jersey you are using. You can download it. Then search for the entity-filtering jar with the same version.

All the other Jackson jars are of the same version, but you should see which version of Jackson the jersey-media-json-jackson uses. When you click the Jersey version, you should be able to scroll down to see which Jackson version it uses. Then just start searching for all the above Jackson jars for that version.

For instance, if you select the latest Jersey 2.21 version of the jersey-media-json-jackson, you can scroll down and see that it uses Jackson 2.5.4. So you should search for all the above Jackson jars in 2.5.4 instead of the 2.3.2 as shown above.


Note for Maven users, all you need is

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey2.version}</version>
</dependency>

This dependency will pull in all the jars you see listed above.

Jersey Json and Pojo

I'm adding this as my own answer because i think this will help anyone with a horrible working copy of Jersey in the future. At the same time, the answer of @Michal Gajdos was grealy helpful and you should also relate to his text when having problems in the future.

What eventually helped me was a dependecy which includes pretty much every thing you need. simply add it and give it a try

<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.2.3</version>
</dependency>

source: Git

Jersey 2.0 equivalent to POJOMappingFeature

You can configure EclipseLink MOXy as the JSON-binding provider by configuring the MOXyJsonProvider class through a JAX-RS Application class.

Example #1

package org.example;

import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;

public class CustomerApplication extends Application {

@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(2);
set.add(MOXyJsonProvider.class);
set.add(CustomerService.class);
return set;
}

}

Example #2

package org.example;

import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;

public class CustomerApplication extends Application {

@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(1);
set.add(ExampleService.class);
return set;
}

@Override
public Set<Object> getSingletons() {
MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();

moxyJsonProvider.setAttributePrefix("@");
moxyJsonProvider.setFormattedOutput(true);
moxyJsonProvider.setIncludeRoot(true);
moxyJsonProvider.setMarshalEmptyCollections(false);
moxyJsonProvider.setValueWrapper("$");

Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
namespacePrefixMapper.put("http://www.example.org/customer", "cust");
moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);
moxyJsonProvider.setNamespaceSeparator(':');

HashSet<Object> set = new HashSet<Object>(1);
set.add(moxyJsonProvider);
return set;
}

}

For More Information

  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
  • http://blog.bdoughan.com/2013/06/moxy-is-new-default-json-binding.html

Getting Jersey 2.x POJO JSON support to work with Jetty

Automatic registration of providers by moxy didn't work as stated by Jersey Reference.

As per what they have stated, only moxy and jackson has POJO to JSON conversion feature.

Documentation says Jackson doesn't auto register(Not a problem any way!)

1. Swap Moxy with Jackson in POM.XML

Remove :

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>

Add:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>

2. Register Jackson Message Body Readers and Writers :

Add org.codehaus.jackson.jaxrs to provider packages list. Here is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Web app name</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.myorg.myproj.api;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Web app name</servlet-name>
<url-pattern>/v1/*</url-pattern>
</servlet-mapping>


P.S.
I am not promoting jackson, just that moxy didn't work for me, its writers failed to auto register as they advertised and could not find documentation about manual registration!

Can't enable POJO based JSON binding support for Jackson in Jersey 2.0

The documentation is a bit outdated. The latest Jackson build provides an auto-discoverable provider. Add the following jars to the class path:

1) jackson-annotations-2.2.2.jar

2) jackson-core-2.2.2.jar

3) jackson-databind-2.2.2.jar

4) jackson-jaxrs-base-2.2.1.jar

5) jackson-jaxrs-json-provider-2.2.1.jar

6) jackson-module-jaxb-annotations-2.2.2.jar

Make sure to add "com.fasterxml.jackson.jaxrs.json" to the "jersey.config.server.provider.packages" servlet config property, so the Jackson json provider can be auto-discovered.

Getting Jersey's JSON POJO support to work from embedded Jetty?

I was super disappointed when I saw this one not answered as I've been fighting it all day. Finally figured it out so here's what worked for me.

What I was doing:

    ServletHolder servletHolder = new ServletHolder(new ServletContainer(new PackagesResourceConfig("my.package.with.resources")));
servletHolder.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");

What I needed to do:

    Map<String,Object> initMap = new HashMap<String, Object>();
initMap.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
initMap.put("com.sun.jersey.config.property.packages", "my.package.with.resources");
ServletHolder servletHolder = new ServletHolder(new ServletContainer(new PackagesResourceConfig(initMap)));

I had to make sure to specify my Jersey packages and my POJOMappingFeature flag as init params. Hope this helps.

Jersey/JAX-RS clients that use Jackson to pass POJOs as entities

You're using Jersey 1.x, so have a look at the user guide for JSON/POJO support

First thing: We need to make sure you have the jersey-json module

<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>${jersey-version}</version>
</dependency>

This module will have the needed MessageBodyReader and MessageBodyWriter that will read and write you POJOs to and from JSON

Second thing: We need to make sure we enable the POJO mapping support feature. Both with the server/application and with the client

Server with web.xml

<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>

Server programmatic

public class MyApplication extends PackagesResourceConfig {
public MyApplication() {
getFeatures()..put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
}
}

See other Deployment Options

Client Config

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
Client client = Client.create(clientConfig);

Third thing: We just need to make sure our resource method are annotated properly and we make the client call properly (to allow the correct writers/readers to be discovered).

For methods accepting JSON, it should annotated with @Consumed("application/json") and if the method also produces a response in JSON, it should also be annotated with @Produces("application/json"). So it depends on the semantics of your method, which annotations to include, it could be one or both.

For the client, as long as we have to correct configuration, extracting the Java Object, is just a matter of calling a getXxx with the Java type.

public void testGetFizz() {
// Directly extact
Fizz fizz = r.path("fizz").accept("application/json").get(Fizz.class);
System.out.println(fizz);

// Extract from ClientResponse
ClientResponse response = r.path("fizz").
accept("application/json").get(ClientResponse.class);
Fizz fizz1 = response.getEntity(Fizz.class);
System.out.println(fizz1);
}

Here are other pieces of code I used for my test

@Path("/fizz")
public class FizzResource {

@POST
@Consumes("application/json")
public Response postFizz(Fizz fizz) {
System.out.println("==== Created Fizz ===");
System.out.println(fizz);
System.out.println("=====================");
return Response.created(null).build();
}

@GET
@Produces("application/json")
public Response getFizz() {
Fizz fizz = new Fizz(1, "fizz");
return Response.ok(fizz).build();
}
}

Server config

ResourceConfig resourceConfig = new PackagesResourceConfig("test.json.pojo");
resourceConfig.getFeatures().put(
JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

Client config

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
Client client = Client.create(clientConfig);
r = client.resource(Main.BASE_URI);
// r = WebResource


Related Topics



Leave a reply



Submit