Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

toResponse in jersey ExceptionMapper does not get invoked

So I'm building a web application, we are using JPA and Jersey to consume/produces JSON data.

I have a custom "EntityException" aswell as a custom "EntityExceptionMapper"

Here's the mapper:

  @Provider
public class EntityExceptionMapper implements ExceptionMapper<EntityException> {

    public EntityExceptionMapper() {
        System.out.println("Mapper created");
    }

    @Override
    public Response toResponse(EntityException e) {
        System.out.println("This doesnt print!");
        return Response.serverError().build();
    }
}

My Exception:

public class EntityException extends Exception implements Serializable{

  public EntityException(String message) {
      super(message);
      System.out.println("This prints...");
  }

}

And I'm calling it from a REST call:

@POST
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public String test() throws EntityException{
    throw new EntityException("This needs to be send as response!!");
    //return "test";
}

My problem is that, when the above exception is thrown, I get in the constructor (prints: "This prints...") Edit: I also get the: "Mapper created!"

But my response is empty, and I don't get to the sys out of my toResponse method. This is really similar to the example on the jersey website:

https://jersey.java.net/nonav/documentation/1.12/jax-rs.html#d4e435

What am I missing??

like image 509
alex Avatar asked Mar 14 '14 18:03

alex


4 Answers

I am using deployment agnostic application model so the following worked for me:

public class MyApplication extends Application {
    public Set<Class<?>> getClasses() {
        Set<Class<?>> s = new HashSet<Class<?>>();
        s.add(HelloWorldResource.class);

        /** you need to add ExceptionMapper class as well **/
        s.add(EntityExceptionMapper.class)
        return s;
    }
}
like image 155
bluetech Avatar answered Nov 16 '22 00:11

bluetech


I had a similar problem where the ExceptionMapper had the proper @Provider annotation and the rest of the code was identical to Jersey's example but still wasn't registered properly.

Well it turns out I had to register manually my custom ExceptionMapper within my HttpServlet with the method addExceptionMapper. Because it's now manually registered, the @Provider annotation can be safely removed.

So with the following ExceptionMapper (I'm catching every RuntimeException to rethrow them as 400)

public class MyCustomExceptionHandler implements ExceptionMapper<RuntimeException> {

  @Override
  public Response toResponse(RuntimeException exception) {
    return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
  }
}

I had to add the 2nd line in my init :

HttpServlet serviceServlet = jerseyServletFactory.create(someResource);
jerseyServletFactory.addExceptionMapper(new MyCustomExceptionHandler()); //<--

httpServer.register(serviceServlet, "/api");
httpServer.start();
like image 42
Pierre-Luc Pineault Avatar answered Nov 16 '22 00:11

Pierre-Luc Pineault


I have encountered the same issue while develop sample REST API. While creating REST API i have given base package name like org.manish.rest.message, I supposed to create every other packages under the base package like this


  1. model - org.manish.rest.message.model
  2. database - org.manish.rest.message.database
  3. resource - org.manish.rest.message.resource

in web.xml init param was given like this

 <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>org.manish.rest.message</param-value>
 </init-param>

It means, i have registered my base package in web.xml, what ever package i will create under this; will be consider by JAX-RS based on my call and requirement. But when i created my exception package by mistake i put package name org.manish.rest.exception. Since this was not registered in web.xml so my complete exception class was not considered to handle exception by JAX-RS. As a correction, i have just modified my exception package name from org.manish.rest.exception to org.manish.rest.message.exception

After that i executed once in post man and i got expected result.

Hope this can solve your query.

Thanks Manish

like image 39
Kushwaha Avatar answered Nov 15 '22 23:11

Kushwaha


I used spring to wire up jersey app and used @Component with @Provider.

When I moved to jersey v > 2.5, it stopped working.

I resolved this very issue by putting @Singleton annotation instead of @Component alongside @Provider, like this:

@Provider
@Singleton
public class EntityExceptionMapper implements ExceptionMapper<EntityException> {...
like image 27
mSolujic Avatar answered Nov 16 '22 00:11

mSolujic