views:

64

answers:

3

I have a number of classes exposed as JAX-RS request "handlers", using javax.ws.rs.Path annotations. I want to add certain actions before every request and after each request. Also, I need to create a global application-wide exception handler, which will catch everything thrown by these handlers and protocol.

Is it possible to achieve this with standard JAX-RS without creating of a custom class inherited from com.sun.jersey.spi.container.servlet.ServletContainer (I'm using Jersey).

A: 

You can use filters to read and modify all requests and responses.

Eugene Kuleshov
A: 

You could create a proxy RESTful service and use this as the entry point to all your other RESTful services. This proxy can receive requests, do any pre-processing, call the RESTful service required, process the response and then return something to the caller.

I have a set up like this in a project I've been working on. The proxy performs functions like authentication, authorisation and audit logging. I can go into further details if you like.

Edit:
Here is an idea of how you might want to implement a proxy that supports GET requests;

@Path("/proxy")
public class Proxy
{
private Logger log = Logger.getLogger(Proxy.class);

@Context private UriInfo uriInfo;

@GET
@Path("/{webService}/{method}")
public Response doProxy(@Context HttpServletRequest req,
                 @PathParam("webService") String webService,
                 @PathParam("method") String method)
{
    log.debug("log request details");

    //implement this method to work out the URL of your end service
    String url = constructURL(req, uriInfo, webService, method);

    //Do any actions here before calling the end service

    Client client = Client.create();
    WebResource resource = client.resource(url);

    try
    {
        ClientResponse response = resource.get(ClientResponse.class);
        int status = response.getStatus();
        String responseData = response.getEntity(String.class);

        log.debug("log response details");

        //Do any actions here after getting the response from the end service,
        //but before you send the response back to the caller.

        return Response.status(status).entity(responseData).build();
    }
    catch (Throwable t)
    {
        //Global exception handler here
        //remember to return a Response of some kind.
    }
}
Qwerky
@Qwerky Sounds like a solution, but how will you "process the response"? Can you give an example of this RESTful proxy?
Vincenzo
A: 

You can also use ExceptionMappers. This mechanism which catch the exception thrown by your service and convert it to the appropriate Response:

@Provider  
public class PersistenceMapper implements ExceptionMapper<PersistenceException> {  

    @Override  
    public Response toResponse(PersistenceException arg0) {  
        if(arg0.getCause() instanceof InvalidDataException) { 
           return Response.status(Response.Status.BAD_REQUEST).build();  
        } else { 
           ... 
        } 
    }  

}  

For more information see:

Blaise Doughan