0

I am testing my backend (Java using Jersey on tomcat server) and frontend (Angular 4 using webpack to serve) on two different ports, thus I am getting a cors access control origin block. For my get methods everything works fine and any data requested is found on the UI. Now I am testing my POST method and I keep getting the same message in the title.

My post method should persist the data sent to it and return a response with the location of the new persisted entity.

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response persistAccountLocation(AccountLocation entity) throws URISyntaxException {


    accountLocationService.persist(entity);

    JsonObject object = Json.createObjectBuilder()
            .add("location", "api/v1/accounts_locations/"+entity.getLocation_id()).build();

    return Response.status(Response.Status.CREATED)// 201
            .entity("Location created")
            .header("Access-Control-Allow-Origin","*")
            .header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE")
            .allow("OPTIONS")
            .entity(object.toString()).build();
}

In my network tab in firefox browser I only see OPTIONS with 200 status

Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: access-control-allow-origin,content-type
Origin: http://localhost:4200
Connection: keep-alive

but after that the post is never happens. I am assuming CORS blocks it at that point. Is there somewhere else I should be allowing access control besides the resource class? I have read that typical all CORS configuration is done on server side. Totally lost. Any feedback appreciated

EDIT

public class CORSResponseFilter
implements ContainerResponseFilter {

    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
            throws IOException {

        MultivaluedMap<String, Object> headers = responseContext.getHeaders();

        headers.add("Access-Control-Allow-Origin", "*");    
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS");         
        headers.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type,");
    }

}

I have made a a filter with slight adjustments and registered it to my app

public class JaxRsApplication extends ResourceConfig{
    public JaxRsApplication() {

        //  register application resources - unmapped resources will throw exception
        register(AccountLocationResource.class);

        register(CORSResponseFilter.class);
    }
overboard182
  • 190
  • 3
  • 17
  • What JAX-RS container/engine are you using? I would not recommend trying to write CORS manually (it actually involves 2 requests to server). – Aleh Maksimovich Nov 14 '17 at 19:09
  • @AlehMaksimovich Using jersey for jax-rs. It is my container. Atleast I think so. My understanding of the terminology is still new to me https://jersey.github.io/ – overboard182 Nov 14 '17 at 19:12
  • @overboard182 Did you manage to solve this? If yes, how? – Rajshri Mohan K S Jan 24 '18 at 12:59
  • @RajshriMohanKS the two snippets in the edit should work. This is only issue on local if you are hosting rest and UI on two different ports. Typically if this goes to an app server you shouldnt have trouble with CORS – overboard182 Feb 04 '18 at 03:42
  • @overboard182 hey thanks! My issue turned out to have nothing to do with CORS at all. The request size was way above the limit enforced by the parser so it was simply rejecting it without a response. Yet, Chrome kept showing it as a CORS issue. – Rajshri Mohan K S Feb 05 '18 at 08:12

1 Answers1

0

Quite a good answer is provided in How to handle CORS using JAX-RS with Jersey stackoverflow question.

You have given a link to Jersey 1, but please make sure what version you are using.

This way you will not have to write

        .header("Access-Control-Allow-Origin","*")
        .header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE")
        .allow("OPTIONS")

for every request. Filter will apply the options for you.

One more thing I have noticed

return Response.status(Response.Status.CREATED)// 201
        .entity("Location created") // <- entity() call here
        .header("Access-Control-Allow-Origin","*")
        .header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE")
        .allow("OPTIONS")
        .entity(object.toString()).build(); // <- one more entity() call here (not sure what effect it may have)
Aleh Maksimovich
  • 2,622
  • 8
  • 19
  • Thank you for your prompt answer. I have made the appropriate changes. Please see edit if you are still interested in tackling this issue with me :) – overboard182 Nov 14 '17 at 20:24