javaangularjsjax-rswildfly-8

ExceptionMapper causes "No 'Access-Control-Allow-Origin' header is present on the requested resource" when handling an exception


I have an AngularJS client trying to consume a REST Web Service on Wildfly. It works when the server returns an object, but when an exception is thrown, I'm getting the following message:

XMLHttpRequest cannot load http://localhost:8080/ProdutosBackend-0.0.1-SNAPSHOT/rest/user/create. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:51647' is therefore not allowed access. The response had HTTP status code 500.

I tried lots of combinations of headers and filters, but nothing can make this works.

Client code:

var user = { 
      email : $scope.signUpData.email,
      password : $scope.signUpData.password,
      name : $scope.signUpData.name
    };

$http.post(
  'http://localhost:8080/ProdutosBackend-0.0.1-SNAPSHOT/rest/user/create',
  user).
  then(function(data) {
    console.log("It works!");
  },
  function(response) {
    console.log(response);
  });

Web Service

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import br.com.produtos.business.UserBO;
import br.com.produtos.business.exceptions.BusinessException;
import br.com.produtos.entity.User;
import br.com.produtos.transaction.Transaction;

@Path("/user")
public class UserREST {

    @POST
    @Path("/create")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces({ MediaType.APPLICATION_JSON })
    public User createAcount(@Context HttpServletRequest httpServletRequest, User user) throws BusinessException {
        if (user.getEmail().equals("fff")) {
            throw new BusinessException("Bussiness error.");
        }

        {...}

        return user;
    }

}

ExceptionMapper

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

public class ThrowableMapper implements ExceptionMapper<Throwable> {

    @Override
    public Response toResponse(Throwable throwable) {
        return Response.status(500).entity(throwable.getMessage()).build();
    }

}

Application

@ApplicationPath("/rest")
public class ThisApplication extends Application {

    public static CorsFilter cors;

    private Set<Object> singletons = new HashSet<Object>();
    private Set<Class<?>> empty = new HashSet<Class<?>>();

    public ThisApplication() {
        CorsFilter filter = new CorsFilter();
        filter.getAllowedOrigins().add("*");

        cors = filter;

        singletons.add(filter);

        singletons.add(new ThrowableMapper());

        singletons.add(new UserREST());
    }

    public Set<Class<?>> getClasses() {
        return empty;
    }

    public Set<Object> getSingletons() {
        return singletons;
    }

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ProdutosBackend</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>br.com.produtos.rest.ThisApplication</param-value>
  </context-param>
  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
  </context-param>
  <listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
  </listener>
  <servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

Solution

  • I solved the problem returning the message encapsulated into a json string.

    public class ThrowableMapper implements ExceptionMapper<Throwable> {
    
        @Override
        public Response toResponse(Throwable throwable) {
            return Response.status(500).entity("{ \"message\": \"" + throwable.getMessage() + "\" }").build();
        }
    
    }