IAmYourFaja
IAmYourFaja

Reputation: 56934

How does Spring MVC handle headers for a 1-page app?

Yesterday I asked this question and got some very good feedback. To summarize my situation, I am trying to add cache-prohibiting HTTP response headers to my Spring MVC web app (a project I inherited unexpectedly).

So, per the answer-er's (and ultimately, @Bozho's) suggestion, I added this to my Spring config file:

<mvc:annotation-driven/>
<mvc:interceptors>
    <bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
        <property name="cacheSeconds" value="-1"/>
        <property name="useExpiresHeader" value="true"/>
        <property name="useCacheControlHeader" value="true"/>
        <property name="useCacheControlNoStore" value="true"/>
    </bean>
</mvc:interceptors>

I re-built my app locally, and opened it up in Firefox so I could use Firebug to test the headers coming back with the HTTP responses.

Unfortunately for me, the original developers aimed to make this a "1-page web app" with about 40+ AJAX calls per actual JSP page.

Not only do I not see the headers I'm looking for Cache-Control, Expires, etc. in any of these 40+ AJAX requests, but I'm concerned that since there's more than 1 AJAX request per JSP page, the Spring interceptor doesn't know which AJAX calls to add the headers to. I'm not seeing any error messages or logging output to indicate Spring doesn't like my configuration, etc. Everything seems to be acting fine...its just not working!

Thanks in advance for any help here!

Upvotes: 0

Views: 1291

Answers (2)

IAmYourFaja
IAmYourFaja

Reputation: 56934

Spring can be very finicky when it comes to your XML configuration and adding snippets that you find from the web often doesn't work, even for the most trivial examples. Without knowing more about your config it is hard to reproduce this and see where your config is wrong or conflicting with the interceptor declarations.

You can always force your controllers to return the cache-prohibiting headers by declaring instances of HttpHeaders objects, configuring them, and including them as the response entity (which is what it looks like you're using):

HttpHeaders headers = new HttpHeaders();
headers.add("Pragma", "no-cache");
headers.add("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
headers.add("Cache-Control", "max-age=0, no-cache, no-store");

If you have a lot of controllers, and many methods for each controller, this turns into a lot of repetitive, nasty code. Instead you could extend HttpHeaders:

public class YourAppHeaders extends HttpHeaders {
    public YourAppHeaders()            
        add("Pragma", "no-cache");
        add("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
        add("Cache-Control", "max-age=0, no-cache, no-store");
    }
}

Then, you can just go through each @Controller's source file and find/replace new HttpHeaders instances with new YourAppHeaders instances.

I'm recommending this approach over the XML configuration for several reasons:

  • Your XML configuration is not working and I don't have enough information to understand why; and
  • This method is guaranteed to work; and
  • It is the minimal amount of code you can add to accomplish what you're looking for

Best of luck - HTH

Upvotes: 0

axtavt
axtavt

Reputation: 242726

If your configuration looks exactly as shown, your interceptor declaration won't take effect. You need to put interceptor declaration into <mvc:interceptors>, see Bozho's answer.

Regarding multiple AJAX queries, in should be fine as long as these queries are handled by Spring MVC controllers. By default interceptor intercepts all requests coming to controllers, though you can narrow down their scope to specific URL patterns if you want.

Upvotes: 1

Related Questions