It's pretty easy to make web-services answer with JSONP callbacks if you're using Jersey. Adding single filter you can make all web-services' resources add callbacks to their response.
Here is the code of such filter. Note that it's Jersey-based.
package net.sukharevd.ws.rs;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.api.json.JSONWithPadding;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
/**
* Filter that optionally wraps a JSON response in a JSONP callback.
* <p/>
* For this wrapping to happen two things need to be true:
* <ul>
* <li>The Media type of the response must be set to JSON or application/javascript</li>
* <li>The request must have a query parameter called {@code callback}</li>
* </ul>
* <p/>
*
* @see <a href="http://weblogs.java.net/blog/felipegaucho/archive/2010/02/25/jersey-feat-jquery-jsonp">JSONP with
* Jersey and jQuery</a>
*/
public class JsonpResponseFilter implements ContainerResponseFilter {
@Override
public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
if (response.getMediaType() == null || !response.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)
&& !response.getMediaType().equals(new MediaType("application", "javascript"))
&& !response.getMediaType().equals(new MediaType("application", "x-javascript"))) {
return response;
}
String callback = request.getQueryParameters().getFirst("callback");
if (callback == null || callback.isEmpty()) {
return response;
}
if (response.getEntity() != null && response.getEntity().getClass() != GenericEntity.class
&& response.getEntity().getClass() != JSONWithPadding.class) {
@SuppressWarnings("unchecked")
final GenericEntity<?> genericEntity = new GenericEntity(response.getEntity(), response.getEntityType());
JSONWithPadding jsonp = new JSONWithPadding(genericEntity, callback);
response.setEntity(jsonp);
response.setResponse(Response.fromResponse(response.getResponse())
.type("application/javascript")
.entity(jsonp).build());
return response;
}
return response;
}
}
You can add this filter to web.xml as easy as adding parameter
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>net.sukharevd.ws.rs.JsonpResponseFilter</param-value>
</init-param>
or if you use GrizzlyServerFactory
ResourceConfig rc = new PackagesResourceConfig("net.sukharevd.ws.rs");
rc.getContainerResponseFilters().add(new JsonpResponseFilter());
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
Here you can find GitHub repository with web-services and GWT-client sample projects.
Comments