1. Overview
In this quick article, we’ll learn about how to enable CORS (Cross-Origin Resource Sharing) in a JAX-RS based system. We’ll set up an application on top of JAX-RS to enable CORS mechanism.
2. How to Enable CORS Mechanism
There are two ways by which we can enable CORS in JAX-RS. The first and the most basic way is to create a filter to inject necessary response header at run-time in every request. The other one is to manually add an appropriate header in each URL endpoint.
Ideally, the first solution should be used; however, when that’s not an option, the more manual option is technical OK as well.
2.1. Using the Filter
JAX-RS has the ContainerResponseFilter interface – implemented by the container response filters. Typically, this filter instance is applied globally to any HTTP response.
We’ll implement this interface to create a custom filter which will inject Access-Control-Allow-* header to each outgoing request and enable the CORS mechanism:
@Provider public class CorsFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { responseContext.getHeaders().add( "Access-Control-Allow-Origin", "*"); responseContext.getHeaders().add( "Access-Control-Allow-Credentials", "true"); responseContext.getHeaders().add( "Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); responseContext.getHeaders().add( "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); } }
A couple of points here:
- Filters implementing ContainerResponseFilter must be explicitly annotated with @Provider to be discovered by the JAX-RS runtime
- We’re injecting ‘Access-Control-Allow-*‘ header with ‘*’, that means any URL endpoints to this server instance can be accessed via any domain; if we want to restrict the cross-domain access explicitly, we have to mention that domain in this header
2.2. Using Header Modification into Each Endpoint
As stated earlier, we can explicitly inject the ‘Access-Control-Allow-*‘ header at the endpoint level as well:
@GET @Path("/") @Produces({MediaType.TEXT_PLAIN}) public Response index() { return Response .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Credentials", "true") .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization") .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD") .entity("") .build(); }
A point to note here is if we’re trying to enable CORS in a large application, we shouldn’t try this method because in this case, we have to manually inject the header into every URL endpoints which will introduce additional overhead.
However, this technique can be used in applications, where we need to enable CORS in only some of the URL endpoints.
3. Testing
Once the application is up, we can test the headers using the curl commands. A sample headers output should be something like below:
HTTP/1.1 200 OK Date : Tue, 13 May 2014 12:30:00 GMT Connection : keep-alive Access-Control-Allow-Origin : * Access-Control-Allow-Credentials : true Access-Control-Allow-Headers : origin, content-type, accept, authorization Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS, HEAD Transfer-Encoding : chunked
What’s more, we can create a simple AJAX function and check the cross domain functionality:
function call(url, type, data) { var request = $.ajax({ url: url, method: "GET", data: (data) ? JSON.stringify(data) : "", dataType: type }); request.done(function(resp) { console.log(resp); }); request.fail(function(jqXHR, textStatus) { console.log("Request failed: " + textStatus); }); };
Of course in order to actually perform the check, we’ll have to run this on a different origin than the API we’re consuming.
You can do that locally quite easily by running a client app on a separate port – since the port does determine the origin.
4. Conclusion
In this article, we showed about implementing CORS mechanism in JAX-RS based applications.
Like always, the full source code is available over on GitHub.