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):
I'm new to this but I was able to use POJOs after adding the jackson-all-1.9.0.jar to the classpath.
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
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;
}
}
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.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>
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>