Freitag, 12. Oktober 2012

Cross domain request & Jersey. And IE9 caching ajax problem solution (304 not modified).


Cross domain request & Jersey. And IE9 caching ajax problem solution (304 not modified).

In our pretty cloud world cross domain requests are common practise. Web applications consume code across CDNs and several other sources. So the good old "same domain policy" is definitely out-dated. There are many solutions to that thing.. like JSONP. But the finest solution allowing open access across all boundaries come with the CORS Specs by W3C  (see http://enable-cors.org/)

You'll find a lot of discussions about Jersey & CORS at the following blogs:

Basic Coding Ideas

http://blog.kdecherf.com/2011/06/19/java-jersey-a-cors-compliant-rest-api/

http://2rdscreenretargeting.blogspot.de/2012/06/enable-cors-for-jersey.html


The Solution: Jersey and CORS

http://software.dzhuvinov.com/cors-filter-configuration.html

A sample web.xml with CORS support for Jersey:

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>origin, content-type, accept</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>




IE9 is even caching Ajax GET request.

Something a developer wouldnt except happens at Microsofts IE9: its caching AJAX GET requests. In the developer console an ajax GET request response with 304 (not modified), but have tested it, IE9 never touches the server resource in that case. So the 304 Header is a misleading information, because your Jersey Server was never called by IE9 and in fact was never sending an 304 response.  Its all about the caching behaviour of IE9.

To get rid of that, the best solution is to send a "Cache-Control: no-cache" Header with your GET/POST/etc responses. You can use ContainerResponseFilters within Jersey to automatically add "no caching" to every response. Normally caching f.e. JSON data client-side doesnt make sense at all.

To avoid browsers caching your responses, your web.xml file cloud make use of ContainerResponseFilters:

        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
            <param-value>here.you.point.to.a.filter.class</param-value>
        </init-param>



A sample class look like:


public class HttpHeaderFilter implements ContainerResponseFilter {

    @Override
    public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {

        Response.ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
        resp.header("Cache-Control","no-cache");
        contResp.setResponse(resp.build());
        return contResp;
    }

}


Thanks to Dean Moses for his worthful information about IE9 Caching:

http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/