Jayyrus
Jayyrus

Reputation: 13051

Jersey global ExceptionHandler doesn't work

i'm trying to create a global ExceptionHandler in this way:

@Provider
public class MyExceptionHandler implements ExceptionMapper<Exception> 
{
    @Override
    public Response toResponse(Exception exception) 
    {
        return Response.status(Status.BAD_REQUEST).entity("TEST").build();  
    }
}

in order to catch all the exception in the controller:

@Path("/policy")
@GET
public void getPolicy(@DefaultValue("no") @QueryParam("_id") String _id) throws Exception{
        int a = Integer.parseInt("test"); // it generates NumberFormatException
}

the NumberFormatException isn't handled by MyExceptionHandler.

Where i'm wrong?

Thanks!

Upvotes: 2

Views: 1357

Answers (2)

pestrella
pestrella

Reputation: 9936

It's worth checking that the ExceptionMapper is registered as a singleton. Registering a component as a singleton depends on your framework. Here's a couple of examples:

Guice

In your injector instance --

Guice.createInjector(new JerseyServletModule() {
    @Override
    protected void configureServlets() {
        /* ... this is where modules are installed and where
         * component dependencies are binded
         */

        bind(MyExceptionHandler.class).in(Scopes.SINGLETON);

        /* configure filters etc, omitted for brevity */
    }
}

Spring

In your Spring config

<bean id="exceptionMapper" class="my.package.MyExceptionHandler" scope="singleton" />

Or using component scanning, mark your ExceptionMapper as @Component --

Config:

<context:component-scan base-package="my.package"/>

Annotated class:

@Component
@Provider
public class MyExceptionHandler implements ExceptionMapper<Exception> {

}

Upvotes: 0

zyexal
zyexal

Reputation: 1579

If you use jersey < 2.5 it could be a bug while component package scanning:

@see: https://java.net/jira/browse/JERSEY-2175

Otherwise,
you properly missed to add the package of your MyExceptionHandler for component scans. The @Provider annotation means, that the implementation "should be discoverable by JAX-RS runtime during a provider scanning phase", but in fact it does'nt did it like we thought. Probably a bug, but i'm not sure.

Meaning: Afaig, you have to register package or mapper by yourself - otherwise it will not work for now!

Note: I did not tested this with servlet 3.x without Application subclass and basic web.xml @see 4.7.2.3.1. JAX-RS application without an Application subclass link

Maybe also interesting:

Disable MBW, MBR, ExceptionMapper automatic registration via META-INF/services

The jersey-metainf-services (Jersey extension module enabling automatic registration of JAX-RS providers (MBW/MBR/EM) via META-INF/services mechanism) was added @since 2.9.x

For the sake of completeness:
You can do the registration by using ResourceConfig.packages(String...packages):

import org.glassfish.jersey.server.ResourceConfig;

public class MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        packages(new String[] { 
            "path.to.foo", 
            "path.to.bar"
        });
    }
}

Alternative in web.xml servlet config

...for packages:

<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>path.to.foo,path.to.bar</param-value>
</init-param>

...for classes

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        path.to.foo.MyExceptionHandler,
        path.to.bar.FooBar
    </param-value>
</init-param>

Upvotes: 1

Related Questions