Search code examples
javajax-rsthorntailexceptionmapper

Why CORSFilter conflicts with ExceptionMapper<Throwable>?


I have this Java thorntail application, where I wanted to catch all uncaught exceptions.

I wanted to respond with 500 instead of the default error page that JAXRS gives, so I just used implementation of ExceptionMapper<Throwable>.

Did the testing using Postman without issues, but once I tried to do the AJAX call in browser, I ended up sending OPTIONS request, which is failing.

CORS part is also implemented on the application side by implementing ContainerResponseFilter.

I have a feeling that MATCHING happens in an early stage of request and only later the CORSFilter has effect on the response.

Few things that I already tried:

  • @PreMatching
  • @Priority
  • Tried to import jboss.resteasy CorsFilter
  • Tried to filter out exceptions by exception instanceof DefaultOptionsMethodException, but ended up figuring out that DefaultOptionsMethodException is not in the classpath and it's internal (?) package included in thorntails classpath (??)
  • ...
// CORSFilter
package com.testapplication.test.rest;

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.ext.Provider;

@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-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        responseContext.getHeaders().add("Access-Control-Max-Age", "-1");
        responseContext.getHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    }
}
// UncaughtExceptionMapper
package com.testapplication.test.rest;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class UncaughtExceptionMapper extends Throwable implements ExceptionMapper<Throwable> {
    @Override
    public Response toResponse(Throwable exception) {
        exception.printStackTrace();
        return Response.status(500).entity("{\"message\": \"a\"}").build();
    }
}

Example repository: https://github.com/trimpirim/cors-filter-conflict-exception-mapper


Solution

  • Try the filter at the bottom of this post. Just using a response filter will not perform correctly in regards to the CORS interaction. You need a request filter also to abort the request for the preflight requests.