I need to use JSON.stringify and JSON.parse in a java class that contains resteasy services to exchange information with a Jquery script.
Which library should import the java class or what should I do ?, because in the script itself let me do it by default. Thank you very much.
So from my understanding you want to be able to serialize and deserialize JSON to and from Java object, as that's what JSON.stringify and JSON.parse does for Javascript.
To be able to handle that, we need a MessageBodyReader and a MessageBodyWriter to handle the conversion. The Resteasy has the providers available as part of the framework. We just need to add the module.
Hopefully you are using Maven, if not see this post. With Maven you should have either one of these dependencies
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
The only difference is in which Jackson flavor will be used 1.x or 2.x
Once you have to provider on the classpath, it should be auto configured. All you need to do is use your POJO ad the conversion will be done e.g
#GET
#Produces("application/json")
public Response getMyPojo() {
MyPojo pojo = new MyPojo();
return Response.ok(pojo).build();
}
#POST
#Consumes("application/json")
public Response createMyPojo( MyPojo pojo ) {
// do something with pojo
}
Related
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.
I have created a Jersey 2.5 Scala REST API Project.
I have a ResourceConfig file, we will call it MyApplication, that looks similar to this:
class MyApplication extends ResourceConfig {
packages(classOf[MyResource].getPackage().getName())
}
All it does is register the resource: MyResource. How can I configure Jersey (2.5) to provide out-of-the-box style JSON Serialization/Deserialization.
For example, here is what MyResource might look like:
#Path("/")
class MyResource {
#POST
#Produces(Array("application/json"))
#Consumes(Array("application/json"))
def getIt(request:SomeRequestModel) = {
/* Do something with the request, return some response model */
return new SomeResponseModel
}
}
So to reiterate, how can I configure Jersey to automatically deserialize and serialize the request and response models, respectively?
It's not actually Jersey that provides the serialisation, it simply draws on an implementation of JAX-RS to perform that role.
Assuming Jersey is a strict requirement, the easiest solution here is to use jackson with Scala bindings. You can find an example here: https://bitbucket.org/jordipradel/jersey-scala-example
If you're not completely tied to Jersey... Might I suggest trying either Spray or spray2-mini instead for a far more idiomatic Scala solution?
I have used Jersey little when developing Java REST services. However, I would say you appear to be conflating two concepts--registering JAX-RS providers and configuring providers to serialize/deserialize JSON.
To register a provider, you use ResourceConfig as you have done.
As for the second issue of configuring Jersey to "know" how to serialize/deserialize JSON:
"As stated in Section 4.3, “Auto-Discoverable Features” JSON-Processing media module is one of the modules where you don't need to explicitly register it's Features (JsonProcessingFeature) in your client/server Configurable as this feature is automatically discovered and registered when you add jersey-media-json-processing module to your classpath."
To add the Jackson flavor of that module to the classpath, you just manually put it there or do this with Maven:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.5</version>
</dependency>
I chose Jackson because it is in my view the best JSON serializer/deserializer in the Java realm.
Having said all this, I once experimented writing services with my preferred Java REST framework, RESTEasy, in Scala. It was more awkward than my first date. Scala and RESTEasy just don't fit together because of an idiom mismatch, issues with types, and so on.
If you want to write REST services in Scala, please consider frameworks built with the language in mind like Scalatra, Unfiltered, or Spray.
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.
I want to support both XML and JSON representations of Resources in my REST API. I have no choice but to use CXF implementation of Jax-RS without using Spring. I am using JAXB to marshall and unmarshall objects. I have the following methods defined that return different representations of the same resource.
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.WILDCARD})
#ElementClass(response = MyList.class)
public Response listXML(){
MyList list = getList();
return Response.status(
Response.Status.FOUND).
entity(list).type(MediaType.APPLICATION_XML).build();
}
#GET
#Produces({MediaType.APPLICATION_JSON})
#ElementClass(response = MyList.class)
public Response listJson(){
MyList list = getList();
return Response.status(
Response.Status.FOUND).
entity(list).type(MediaType.APPLICATION_JSON).build();
}
This works fine for the XML representation. But if I set the Accept header of my HTTP request to application/json I get the following message.
No message body writer has been found for response class MyList.
What am I missing here? The MyList class is generated by JAXB from XSDs and has all the necessary annotations Looks like I need to configure CXF to use a JSON provider. I haven't been able to find good documentation on configuring the JSON provider in the web.xml for a webapplication that doesn't use Spring. If anyone has got this work, please guide me.
I got it figured out. I needed to configure JSONProvider as one of initparams for NonSpringServlet in the deployment descriptor. This wasn't working for me before as I was missng the cxf extensions library and the jettison library. These dependencies don't get automatically pulled by maven or gradle if you only have a dependency on cxf front end jars.
I'm using Jersey for my RESTful services and Genson to perform my JSON/POJO conversion. There's no setup for Genson, I just drop it into the classpath and it just works, except that it throws an error on date parsing because the format is unexpected.
Now, if I were to do this as a servlet, using Gson, I set the date format on a Gson instance that I maintain. That forces the parse of the POJO to use the correct format. I see that Genson has a similar interface, but I don't know how to get the instance from the Jersey servlet service or maybe the Spring context so that I cat set the format.
So, the short question is: how do I set a date format for Genson when started through Jersey?
To configure Genson instances you can use Genson.Builder class (it is similar to Gson on this point). Then you have to inject it with Jersey.
#Component
#Provider
public class GensonProvider implements ContextResolver<Genson> {
private final Genson genson = new Genson.Builder().setDateFormat(yourDateFormat).create();
#Override
public Genson getContext(Class<?> type) {
return genson;
}
}
You might also want to have a look at how Genson is integrated into Jersey here.