9

I want to customize 404 response, that the server (not me) throws whenever it can't find a requested resource, (or throw a customized WebApplicationException myself, if it's possible to test if a requested resource is present in one app? probably a List of resources is stored somewhere?). please don't refer me to solutions that suggest to extend WebApplicationException, because even doing so, my problem is when to throw it?, when resource is not found! but how to express this need in jersey framework

Curcuma_
  • 589
  • 1
  • 8
  • 30

1 Answers1

14

Jersey throws javax.ws.rs.NotFoundException when it cannot find an endpoint. Just use an exception mapper to transform it to a response of your choice:

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

@Provider
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {

    public Response toResponse(NotFoundException exception) {
        return Response.status(Response.Status.NOT_FOUND)
                .entity("No such resource")
                .build();
    }
}
Lukasz Wiktor
  • 17,016
  • 4
  • 63
  • 80
  • 1
    thank's but unfortunately after adding your code, to the same package where my main class resides, and running `curl -g -i http://localhost:8080/base/@@@11` I'm receiving 404 with no content, as far as I know `@Provider` is here to tell server this is the class to throw when a resource was not found, is this right? then how to make it work?! – Curcuma_ Nov 01 '14 at 05:20
  • I don't think I need to register it somewhere, is that right? – Curcuma_ Nov 01 '14 at 05:28
  • If you have configured package scanning and you placed a provider in the specified package then it should work. There are several types of providers in JAX-RS (see more: http://stackoverflow.com/questions/13557442/what-does-provider-in-jax-rs-mean). ExceptionMappers allow you to catch any exception you want to handle and produce a custom response. In this case we're handling NotFoundException because it's being thrown by the server when no matching resource is found. – Lukasz Wiktor Nov 01 '14 at 06:28
  • enabling package scanning as you stated made it work, I just added `final ResourceConfig resourceConfig = new ResourceConfig(); Map initParams = new HashMap(); initParams.put( ServerProperties.PROVIDER_PACKAGES, NotFoundExceptionMapper.class.getPackage().getName());` and passed resourceConfig to `GrizzlyHttpServerFactory.createHttpServer`. – Curcuma_ Nov 01 '14 at 12:33
  • 2
    That's great! The other option to register a provider or a resource is to do it individually for each class. In this case it would be `resourceConfig.register(NotFoundExceptionMapper.class)` or through init params: `initParams.put(ServerProperties.PROVIDER_CLASSNAMES, NotFoundExceptionMapper.class)`. However, package scanning is very useful when you have many resources and providers. You can set it to your root package and then every class annotated with `@Resource` or `@Provider` gets registered automatically. – Lukasz Wiktor Nov 03 '14 at 07:20
  • just a little comment for Guice users: to be undertaken, your mapper classes need to be bind at startup. Example : `bind(JerseyGenericExceptionMapper.class).in(Scopes.SINGLETON); bind(JerseyNotFoundExceptionMapper.class).in(Scopes.SINGLETON); bind(JerseyParamExceptionMapper.class).in(Scopes.SINGLETON);` – boly38 Jan 27 '16 at 14:13