Implementing JSONP in Spring MVC 3.0.x

by vivin

In Spring 3, it’s very easy to get a view to return JSON. However, there is no built-in mechanism to return JSONP. I was able to find a pretty good tutorial That uses Spring’s DelegatingFilterProxy. I implemented this solution and I got it to work, but I didn’t like the fact that I had to create a separate filter and a bunch of other classes just for that. I also wanted to use a specific extension (.jsonp) for JSONP just to make it more explicit. Spring uses MappingJacksonJsonView to return JSON. I figured that I could extend this view and have it return JSONP instead of JSON.

Although I pulled my hair out for an hour or two (I was getting a 404 when hitting my controller with with a .jsonp extension; I’ll explain why, later), the resulting solution is actually pretty simple. First, you need to extend MappingJacksonJsonView to create your own view. Since MappingJacksonJsonView already handles the creation of JSON, all we need to do is pad it with our callback. The way to do this is to override the MappingJacksonJsonView#render(Map model, HttpServletRequest request, HttpServletResponse response) method (This method is actually defined in AbstractView, a Spring-provided abstract class that you can override in your own view). The full source is below:

package net.vivin.mvc.spring.view.jsonp;

import org.springframework.web.servlet.view.json.MappingJacksonJsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class MappingJacksonJsonpView extends MappingJacksonJsonView {

	 * Default content type. Overridable as bean property.
	public static final String DEFAULT_CONTENT_TYPE = "application/javascript";

    public String getContentType() {
        return DEFAULT_CONTENT_TYPE;

	 * Prepares the view given the specified model, merging it with static
	 * attributes and a RequestContext attribute, if necessary.
	 * Delegates to renderMergedOutputModel for the actual rendering.
	 * @see #renderMergedOutputModel
	public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

        if("GET".equals(request.getMethod().toUpperCase())) {
            Map<String, String&#91;&#93;> params = request.getParameterMap();

            if(params.containsKey("callback")) {
                response.getOutputStream().write(new String(params.get("callback")[0] + "(").getBytes());
                super.render(model, request, response);
                response.getOutputStream().write(new String(");").getBytes());

            else {
                super.render(model, request, response);

        else {
            super.render(model, request, response);

The DEFAULT_CONTENT_TYPE public static property and the getContentType() method are important. Spring uses this method (among other things) to find the best candidate view. I spent at least an hour trying to figure out why I was getting 404’s. It was because I hadn’t overridden the property and the accessor to return the correct content-type. Going back to the render method itself, you can see that it’s pretty simple. First I make sure that the request method is GET. Then I get the request parameter-map and check for the callback parameter. If this parameter exists, I write out the name of the callback with an open parenthesis. Then I call the parent class’s render method. This method belongs to MappingJacksonJsonView and will write out JSON to the response. Finally, I write out a closing parenthesis and a semicolon to the response and set the content type to application/javascript. So as you can see, I’ve converted JSON into JSONP.

The next thing you need to do is include an entry for your new view in the springmvc-servlet.xml file. This part also took a little work. I wasn’t sure how to include my new view within the ContentNegotiatingViewResolver bean. But this post proved to be remarkably helpful. The post actually talks about returning XML or JSON (based on the extension), but I was able to adapt it to return JSON or JSON. Here’s what it looks like:

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="favorPathExtension" value="true"/>
        <property name="mediaTypes">
                <entry key="json" value="application/json"/>
                <entry key="jsonp" value="application/javascript"/>
        <property name="defaultViews">
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
                <bean class="net.vivin.mvc.spring.view.jsonp.MappingJacksonJsonpView"/>

If you notice, the value property for jsonp has been set to application/javascript. Spring uses this value and checks it against the view class to figure out the best candidate view. If you didn’t override the DEFAULT_CONTENT_TYPE property and the associated getter, you would get a 404.

Finally, you need a url-pattern entry under servlet-mapping in your web.xml file so that the new .jsonp extension is recognized:


That’s pretty much it. With this code in place, you can hit your controller with and you’ll get your data back as JSONP! I thought this solution was pretty simple and a little less invasive than creating a filter. Comments/suggestions/criticisms for improvement are welcome!