Search code examples
ajaxcorsjersey

How to handle CORS error with an angular app and a java backend?


I have an angular App that tries to send ajax requests to a java backend (API built with Jersey).

Here is the client request :

let settings = {
      "url": "http://localhost:8080/simulator/config",
      "method": "POST",
      "timeout": 0,
      "headers": {
        "Content-Type": "application/json"
      },
      "data": JSON.stringify({
        "fromDate": fromDate,
        "tsIntervalTag": tsIntervalTag,
        "tsIntervalDevice": tsIntervalDevice,
        "devicePerMinute": devicePerMinute,
        "tagPerMinute": tagPerMinute,
        "quantityOfTags": quantityOfTags,
        "quantityOfDevices": quantityOfDevices
      }),
    };

    $.ajax(settings).done(function (response) {
      console.log(response);
    });

And here is the java backend request handler:

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postIt(String body) {
        try {
            //do stuff
            return Response.ok(body, MediaType.APPLICATION_JSON).header("Access-Control-Allow-Origin", "*").build();
        } catch (Exception e) {
            return Response.serverError().entity(e).header("Access-Control-Allow-Origin", "*").build();
        }
    }

As you can see, as nearly all answers about CORS state, the Access-Control-Allow-Origin header is set to * wildcard, so from my understanding, the response should get back to the browser.

But the browser console returns the following:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/simulator/config. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/simulator/config. (Reason: CORS request did not succeed).

So what did I miss ?


Solution

  • It seems like with Jersey, it is better to use filters to set CORS. (At least in my scenario where all requests should be accepted from anywhere (so far)).

    So I created the following class (in its own java file):

    package com.example;
    
    import java.io.IOException;
    
    import javax.ws.rs.container.ContainerRequestContext;
    import javax.ws.rs.container.ContainerResponseContext;
    import javax.ws.rs.container.ContainerResponseFilter;
    import javax.ws.rs.core.MultivaluedMap;
    import javax.ws.rs.ext.Provider;
    
    @Provider
    public class CORSFilter implements ContainerResponseFilter {
    
        @Override
        public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
                throws IOException {
            System.out.println("FILTER HERE ");
            MultivaluedMap<String, Object> headers = responseContext.getHeaders();
            headers.add("Access-Control-Allow-Origin", "*"); // Allow Access from everywhere
            headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
            headers.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
        }
    
    }
    

    And that's is basically it. All requests will go through this and get the correct headers. I do not know why setting the headers in method directly did not work though.