Resteasy Atom Links with Jackson instead of Jettison - json

Due to other requirements we need to use Jackson for JSON serialization. Unfortunately Jackson does not support Atom Links with RESTServiceDiscovery as stated in the documentation. Has anyone already build a workaround for this? Or any idea why it is not working with Jackson and how to fix it?
Our current approach is to use XML as output and then use a javascript library to transform XML to JSON.

We were facing the same problem using JBossAS7.
We ended switching from Jackson to Jettison by disabling Jackson in jboss-deployment-structure.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.jboss.resteasy.resteasy-jackson-provider" />
</exclusions>
</deployment>
</jboss-deployment-structure>

Related

MIME media type application/json was not found

[This my controller class. ]
A message body reader for Java class jersey.model.Message, and Java type class jersey.model.Message, and MIME media type application/json was not found.
Try it by adding following dependency in your pom.xml file
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>1.4</version>
</dependency>
Hope this works

Why have Rest-Easy and Jersey different JSON Output Formats?

I have written a rest service API which returns a data structure in a kind of a map layout. The map entries can be from type String, Integer or Date. The rest service method supports XML and Json output.
Now I recognized that the JSON outcome in GlassFish (Jersey) is different as in Wildfly (Reas-Easy)
When running the rest servie on GlassFish with application/json the output looks like this:
{"entity":{"item":{"name":"$modified","value":{"#type":"xs:dateTime","$":"2015-02-17T22:33:57.634+01:00"}}}}
And the same result on WildFly (Rest-Easy) looks like this:
{"entity":[{"item":[{"name":"$modified","value":[1425822673120]}]}]}
Can anybody explain this behavior? I would expect that the output in WildFly should be simmilar to GlassFish?
The interesting thing is that When I call the same method with the request header 'application/xml' both systems return the same (expected) format.
GlassFish XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entity><item><name>$modified</name>
<value xsi:type="xs:dateTime">2015-02-17T22:33:57.634+01:00</value></item></entity></collection>
Wildfly XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entity><item><name>$modified</name>
<value xsi:type="xs:dateTime">2015-03-08T14:51:13.120+01:00</value></item></entity></collection>
Is there a way to configure the JSON Format for Rest-Easy?
It would help if we had the model classes to test, so we could see which providers produce which result (while testing). But without it, I'll just throw some things to consider
Glassfish by default uses MOXy for JSON/POJO support. I personally do not like using MOXy. At first I promoted it's usage, as it's recommended by Jersey, but after a while, you start to learn its limitations. Glassfish also ships with Jackson support, but we need to either disable MOXy explicitly, or just register a Jackson Feature (which is not portable) or a combination of diabling MOXy and adding a Jackson provider.
As far as Wildfly, one thing to consider as mentioned here in the Resteasy Documentation
21.6. Possible Conflict With JAXB Provider
If your Jackson classes are annotated with JAXB annotations and you have the resteasy-jaxb-provider [which Wildfly comes shipped with] in your classpath, you may trigger the Jettision JAXB marshalling code. To turn off the JAXB json marshaller use the #org.jboss.resteasy.annotations.providers.jaxb.IgnoreMediaTypes("application/*+json") on your classes.
Another thing to consider is that both servers come shipped with providers for both Jackson 1.x and Jackson 2.x. Which ever one used may not have a difference in the marshalling result, but is relevant to the next part of this answer (also see here - though this mentions JBoss AS7, I'm not sure if it applies to Wildfly. I think Wildfly uses Jackson 2 by default though).
One way to test which provider is being used is to create a ContextResolver. Now this next example is simply for testing purposes ( you wouldn't normally just add Jackson by itself, but the Jackson provider).
Add this dependency to your project
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.0</version>
</dependency>
Add this class
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
#Provider
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>{
static final Logger logger
= Logger.getLogger(ObjectMapperContextResolver.class.getName());
final ObjectMapper mapper = new ObjectMapper();
#Override
public ObjectMapper getContext(Class<?> type) {
logger.log(Level.INFO, "<===== ***** Jackon 2 is used ***** =====>");
return mapper;
}
}
Result
Glassfish: Jackson 2 not being used
Wildfly: Jackson 2 is used (even with JAXB annotations. Maybe you need to explicitly have the resteasy-jaxb-provider explicitly on the project classpath for the Jettison to kick in).
So how can we fix Glassfish deployment, in a portable way? One way I was able to test and get Jackson 2 to be used on both servers, is to disable MOXy, by adding a server configuration property. This is portable as the property is nothing more than a string. It will be ignored by Resteasy.
#ApplicationPath("/rest")
public class AppConfig extends Application {
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
properties.put("jersey.config.disableMoxyJson", true);
return properties;
}
}
We'll also need to add the Jackson provider to the project
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
Odd that we have to add this dependency, as Glassfish already comes shipped with it, but if I don't add it, I'll get a MessageBodyWiter not found.
This solution has been tested on Wildfly 8.1 and Glassfish 4.0
JAX-RS specifies the interface MessageBodyWriter for serializing your entities but this defines only that a Java Object is converted to an OutputStream. How the result looks like is up to you or the JAX-RS runtime.
Both, RESTeasy and Jersey ship with serializers for MediaTypes like application/json or application/xml and a default serializer which is used if no better one is found.
For serializing a Java Object to XML there is JAXB as standard so the result should not differ (too much). For JSON the situation is different, there is no explicit standard but a lot of serializers like e.g:
Jackson
Jettison
Genson
They all handle some things differently can be configured differently and changed behavior during their history.
To answer the last question: If you are using RESTeasy on Wildfly you are usually using Jackson and you can configure a lot. Here's an example.
Beware that the Jackson configuration options have been renamed from time to time.

How to send response as JSON in Jersey Rest

I have Jersey Rest Webservice with server side code as
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Employee> getEmployees()
{
return new EmployeeService().getEmployees();
}
T
I am testing the service from chrome rest client.
This works fine with
Accept: application/xml
** But when I am requesting this with code
Accept: application/json
I am getting the following exception:-
javax.servlet.ServletException:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class com.rshekhar.domain.Employee, genericType=class com.rshekhar.domain.Employee.
What is the correct way of doing this.
You can use Jersey's built-in Jackson JSON library to automatically serialize JSON from any POJO classes. You just need to add Jackson JSON library to your pom.xml:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>${jersey.version}</version>
</dependency>
Also in order to activate the POJO mapping of Jersey, you need to add the following lines in web.xml:
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
Then if your class method EmployeeService().getEmployees() returns a list of employees, Jersey will serialize it to something like (JSON array)
{"employees": ["name":"Adam", "name":"Robert", ....]}
Can you provide more details related to jersey setup (entity classes annotations for starters)
Do you use JAXB? Which version of Jersey?
Here is nice starting point for your goal: https://github.com/jasonray/jersey-starterkit/wiki/Serializing-a-POJO-to-xml-or-json-using-JAXB
Take a look here and try out the example. It almost exactly the same usecase you have mentioned.
multiple content types in jax-rs
With latest version like 1.19.1 jersey.
add following dependency
compile group: 'com.fasterxml.jackson.jaxrs', name: 'jackson-jaxrs-json-provider', version: '2.10.0.pr1'
in gradle
or if you are using maven.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.10.0.pr1</version>
</dependency>
in maven
It will work.
Thanks,
Praveen R.

JSON description in WADL using Jersey

I have a REST service that produces a JSON output. I'm using Jersey. I can see my WADL in XML format when I type <server>/<rest>application.wadl and I get, for example, the following keys:
<response>
<ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02" xmlns="" element="script" mediaType="application/json"/>
</response>
Now I need to describe the json that the service returns. How can I do that?
EDIT: There seems to be a solution here:
http://java.net/jira/browse/JERSEY-638
There is a patch available, but I don't know how to use this patch. What do I do with the ".patch" file?
The .patch file can be applied using SVN Apply Patch command.
The Jersey source code version 1.x can be found here. There is a checkout URL specified. I think that patch was not officially accepted thou you can use it locally, accepting all the risks, probably.

Create and link XSD to a WADL

I am creating some services using JAX-RS that need to take in arbitrarily complex objects as arguments, not just primitives like integers and strings. A discussion on the CXF mailing list says to just use a wrapper object as a single parameter in this case.
My concern is how to document the input format to the service? If creating a service that looks something like the following:
#POST
#Produces("application/json")
#Consumes("application/json")
#Path("oneParam")
public ComplexObject2 myServiceMethod(ComplexObject1 obj) {
Foo f = obj.foo
Bar b = obj.bar
...
}
the auto-generated WADL that CXF produces will only produce the following:
<resource path="/oneParam">
<method name="POST">
<request>
<representation mediaType="application/json"/>
</request>
<response>
<representation mediaType="application/json"/>
</response>
</method>
</resource>
This contains no information on what the request or response actually contains. Sergey on the CXF mailing list said it was possible to link a schema to the representation, but how am I supposed to do that? And how do I create the XSD?
(P.S. Using POST for idempotent resources might not be RESTful, but it's not important here as we are in essence doing RPC using Json. This is more or less a 1:1 clone of an existing SOAP based api.)
It is possible to link an XSD file into a WADL file and then to reference an XML element in the representation for requests and responses. However, as it is XML schema it doesn't apply to JSON representations.
To link an XSD into a WADL file, create a grammars element at the top of the file before the main resources element.
<grammars>
<include href="myapp.xsd"/>
</grammars>
Then add a reference to an XML element as follows (using a modified version of your example):
<resource path="/oneParam">
<method name="POST">
<request>
<representation mediaType="application/xml" element="myapp:oneParamRequest" />
</request>
<response>
<representation mediaType="application/xml" element="myapp:oneParamResponse" />
</response>
</method>
</resource>
The prefix myapp is defined in the XSD and can be used in the WADL file as well.
I don't know to to configure CXF to do this automatically. My experience with Jersey is similar and we use the generated WADL as a starting point for hand-editing later.