toResponse in jersey ExceptionMapper does not get invoked
Asked Answered
M

12

21

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??

Marlonmarlow answered 14/3, 2014 at 18:42 Comment(7)
Do you get this: "Mapper created" ? Maybe your mapper is not recognized properly. Lower the logging level of jersey to see what classes are being scanned.Sandalwood
Yes I'm getting the "Mapper created" (edited, thanks)Marlonmarlow
What do you get as a result? You should get empty 500 response based on your code.Sandalwood
If you use javax.ws.rs.core.Application to register resources. You can add EntityExceptionMapper.class into set of resource types. Something likes this: classes.add(EntityExceptionMapper.class);Quasar
I get a 204 no content (as my toResponse never seems to be called), following your comment Loc, I tried with something that would be already registered (to see if it would work) I tried extending WebApplicationException, and now it works! I will look into either using that as a type for my exception or registering my own. I think this is about to get solved! Thanks a lot.Marlonmarlow
@LocHa using classes.add(EntityExceptionMapper.class); worked for me thanks a lot @Provider does not seems to workPeriodicity
The first time that I got what I'm looking for from the questions and not from the answer! Thanks a lot!Barony
F
17

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;
    }
}
Flotilla answered 3/6, 2015 at 18:7 Comment(1)
you save my days thanks a lotIncorrigible
W
6

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();
Witchcraft answered 29/7, 2014 at 19:17 Comment(0)
A
5

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

Articulator answered 24/7, 2017 at 9:41 Comment(0)
I
3

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> {...
Infamy answered 2/12, 2014 at 9:28 Comment(0)
C
2

I had the same problem and was able to fix it by including the package of my ExceptionMapper in the jersey.config.server.provider.packages in my web.xml file. Below is a snippet from my web.xml.

<servlet>
    <servlet-name>voteride-servlet</servlet-name>
    <servlet-class>
        org.glassfish.jersey.servlet.ServletContainer
    </servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            com.voteride.ws;com.voteride.errorHandling;org.codehaus.jackson.jaxrs
        </param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.scanning.recursive</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
Calgary answered 10/4, 2016 at 4:58 Comment(0)
P
2

Try to register your exception mapper class in your X extends ResourceConfig file. register(CustomExceptionMapper.class); this line will help application to find your mapper class and return whatever you have written inside the toResponse method of mapper class

Pas answered 23/2, 2017 at 11:3 Comment(1)
That's basically almost the same as this answer above: https://mcmap.net/q/600243/-toresponse-in-jersey-exceptionmapper-does-not-get-invoked because Application extends ResourceConfig; you could have added a comment there...Velum
P
1

I'm using the Jersey JdkHttpServerFactory, and I just had to add the ExceptionMapper class as a resource, just like my other controller resources:

import com.sun.net.httpserver.HttpServer;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

// ...

Set<Class> resources = new HashSet<>();
// Add whatever other resource classes you have...

//--->>> Add the exception mapper <<<---
resources.add(EntityExceptionMapper.class);

ResourceConfig resources = new ResourceConfig(resources);
URI uri = UriBuilder.fromUri("http://localhost/").build();
HttpServer server = JdkHttpServerFactory.createHttpServer(uri, resources);
Patel answered 11/8, 2015 at 19:14 Comment(0)
D
1

I am still using jersey 1.17 , spring and jersy-spring

@Component annotation fixes this

Diathermic answered 11/11, 2015 at 19:38 Comment(0)
D
1

I fixed it by:

import org.glassfish.jersey.internal.spi.AutoDiscoverable;
import org.glassfish.jersey.server.ServerProperties;

public class JerseySpiConfigurator implements AutoDiscoverable {

    @Override
    public void configure(FeatureContext context) {
        context.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); 
    }
}
Droopy answered 25/11, 2022 at 8:58 Comment(0)
M
0

I had the same problem. I just had to modify the web.xml. Previously in my web.xml file param-value was com.two95.restful.resource I just changed to root package com.two95.restful. Then it started working like a charm with just the @Provider annotation.

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.two95.restful</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
Mentalism answered 26/5, 2016 at 5:20 Comment(0)
M
0

I also face the same issue.Just add the package name that have the ExceptionMappperHandler classes.

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>Service,Utilities.ExceptionMapper</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Here,service contain all service classes and Utilities.ExceptionMapper contains all exceptionMapper. Hope its help

Macon answered 13/1, 2017 at 15:9 Comment(0)
T
0

If you're using Guice, try this in you configure method

install(new ComponentScanModule("com.acme.application", Provider.class));

 
Thoron answered 3/3, 2022 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.