How to allow cross origin requests in a JAX-RS micro service

Earlier this year (2019) I started building a modular micro service with Jersey, the JAX-RS reference implementation. I wrote a few blog posts (1, 2, 3, 4 & 5) about it since then. In this post, we are going to create a simple index.html and try to fetch data from the Java backend, and see what we run into.

If you are only interested in reading how to allow cross origin requests in JAX-RS, scroll down.

Grabbing the template from last blog post

Make sure you have:

On github, do a and then switch to the 3.5.1 tag by running:

Verify that it works by running and visit http://localhost:8080/person to see:

Character encoding and javax.ws.core.Response

Something you will notice when visiting http://localhost:8080 in Firefox is a console message about character encoding:

So if we take a look at our method that returns “Got it!” in MyResource.java:

We can use the javax.ws.rs.core.Response object to craft custom responses to solve this problem:

We could wrap the Person object in a Response object in the getPerson() call:

Adding Response object makes WADL crash

When visiting the WADL url (http://localhost:8080/application.wadl) you will see this error:

Either turn off WADL:

Or if you want to keep using WADL, don’t use the Response object and revert it to the old way.

Fetching data from a frontend

So let’s create the simplest frontend possible, an index.html with the following html:

Simple create a file anywhere on your hard drive and open it with chrome while the SimpleJerseyService is running (use again to launch it)

When you click on the “Log Person” button get this CORS error:

Cross Origin Resource Sharing

This is blocked by a Cross Origin Resource Sharing policy. CORS is a mechanism that was added to most browsers in 2014 to protect sites and users against cross site scripting (which was one of the most dangerous vulnerabilities in websites, see this myspace example). What this means is that FireFox will try to do a call to http://localhost:8080/person, but because it doesn’t find CORS headers in the reply from the java backend, it will think it is not allowed because index.html is not on the same domain (actually, since we are running from the hard drive, index.html has no domain at all, you can see it’s null in the browser message).

On production I use Google App Engine. If I would have a frontend that calls the backend, I would run a static frontend on the App Engine nodejs10 runtime, and the backend on the App Engine java11 runtime. Using a dispatch.yaml I could run both on the same domain, and thus I would not have this CORS errors.

But locally, we have this problem. What we want is our Java backend to include CORS headers in the requests to allow fetching data from any domain ONLY when running locally.

Running in local or production mode

I have already changed my Main.java so that if the first argument of the main method is “LOCAL”, it will pass a boolean to the startServer method telling to run locally.

The startServer method will then use this boolean to decide whether use the local or production hostname and port.

Adding a response filter to add the CORS headers

We can modify the javax.ws.rs.core.Response object of each request to include CORS headers like this:

But that is a lot of code for something that only needs to happen when running locally. Therefore I added the following filter to the startServer() method:

When running again with this filter enabled, you no longer have the CORS errors and the index.html nicely prints the person object retrieved from our backend:

Check out the full source code on Github.

Java/TypeScript Developer. Interested in web/mobile/backend/database/cloud. Freelancing, only interested in job offers from employers directly. No middle men.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store