This functionality is new in EclipseLink 2.5.0 (and 2.4.2), you can try it out today using a nightly build available from:
Web Application (foo.html)
The data that we are requesting (to populate the div with id="message") via HTTP comes from a different server than the one hosting our application. We will utilize JSON with padding to get the data. The response from the URL will be a call to our foo function. We will supply the function name via the callback query parameter.
<html> <body> <div id="message"></div> <script> function foo(dataWeGotViaJsonp){ document.getElementById('message').innerHTML = dataWeGotViaJsonp.bar; } </script> <script type="text/javascript" src="http://www.example.com/foo?callback=foo"></script> </body> </html>
Response (from http://www.example.com/foo?callback=foo)
Below is the response from making the HTTP call. See how the JSON data is wrapped in a call to our foo function.
foo({ "bar" : "Hello World" });
RESTful Service (FooResource)
Below is the RESTful service implemented with JAX-RS. Our GET method returns an instance of the MOXy class JSONWithPadding parameterized with the domain class Foo. When instantiating this class we give it the callback function name (default is callback) and an instance of the domain class. We will use the callback function name from the query parameters if one was provided.
package org.example.padding; import javax.ws.rs.*; import javax.ws.rs.core.*; import org.eclipse.persistence.oxm.JSONWithPadding; @Path("/foo") public class FooResource { @GET @Produces("application/x-javascript") public JSONWithPadding<Foo> getFoo(@Context UriInfo uriInfo) { Foo foo = new Foo(); foo.setBar("Hello World"); MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters(); String callbackName = queryParameters.getFirst("callback"); if(null == callbackName) { return new JSONWithPadding<Foo>(foo); } else { return new JSONWithPadding<Foo>(foo, callbackName); } } }
Java Model (Foo)
Below is the Java model that we will use for this example.
package org.example.padding; public class Foo { private String bar; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } }
Handling the application/x-javascript Media Type (MyProvider)
Due to a bug (see: http://bugs.eclipse.org/404927) that we will fix in EclipseLink 2.5.1 you will need to subclass MOXyJsonProvider to override @Produces and the isWritable method in order to utilize JSON with padding.
package org.example.padding; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.Provider; import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider; import org.eclipse.persistence.oxm.JSONWithPadding; @Provider @Produces({ MediaType.APPLICATION_JSON, "application/x-javascript" }) @Consumes(MediaType.APPLICATION_JSON) public class MyProvider extends MOXyJsonProvider { public MyProvider() { setFormattedOutput(true); } @Override public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { if(type == JSONWithPadding.class && "application/x-javascript".equals(mediaType.toString())) { return true; } return super.isWriteable(type, genericType, annotations, mediaType); } }
Further Reading
If you enjoyed this post then you may also be interested in:
- MOXy as your JAX-RS JSON Provider - MOXyJsonProvider
- JSON Binding With EclipseLink MOXy - Twitter Example
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.