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
Is There Any Good and Free Date and Time Picker Available for Java Swing
Utf-8 Charset Doesn't Work with Javax.Mail
Arrays.Fill with Multidimensional Array in Java
Add Multiple Items to an Already Initialized Arraylist in Java
In Java, When I Call Outputstream.Close() Do I Always Need to Call Outputstream.Flush() Before
Cleanest Way to Toggle a Boolean Variable in Java
Use Ant for Running Program with Command Line Arguments
Data Structures That Can Map a Range of Keys to a Value
Error: Java_Home Is Not Defined Correctly Executing Maven
How to Set a Long Java Classpath in Windows
How to Achieve Conditional Resource Import in a Spring Xml Context
Print Full Call Stack on Printstacktrace()