Can you do traditional Servlet Filtering with JAX-RS/Jersey?

Imagine you have a filter that starts a database transaction, processes the request, and then then attempts to commit the transaction.

doFilter(...) {
    ...
    transaction.begin();
    filterChain.doFilter(request, response);
    transaction.commit();
}

Using Jersey, there are some problems:

  1. Using a Filter, the Jersey Servlet Container commits/flushes the response before execution returns to your filter. So, if the commit fails, you can't modify the return code to be a failure. Also, exceptions won't be caught by a JAX-RS ExceptionMapper.
  2. Using ContainerRequestFilter/ContainerResponseFilter.

    public ContainerRequest filter(ContainerRequest request) { ... } public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { ... }

This allows exceptions to bubble up to an ExceptionMapper, but splits logic over 2 separate methods/interfaces. The problem is that if there's an exception that doesn't map to a response, the ContainerResponseFilter is never called, so you can't clean up.

What's the preferred way to handle this in a JAX-RS environment? Is there a way to configure the flushing of the response, or is there a class or interface that I'm overlooking?

Answers


I've been researching this a bit as well for a JAX-RS/RESTEasy application. The two options I was considering before reading this question:

  1. Write an ExceptionMapper<Throwable> (or ExceptionMapper<DaoException> with a custom DaoException) and handle it there or in the ContainerResponseFilter that will get executed because of the ExceptionMapper<?> handling all exceptions.
  2. Before transaction.begin(), check the current state of the transaction, and roll back there if needed.

There are problems with both options.

  1. I find an ExceptionMapper<Throwable> too broad, while the ExceptionMapper<DaoException> might miss some other exception, again leaving the transaction not cleaned up.
  2. Rolling back the transaction on the next request might take a long time, possibly causing locking issues for other transactions.

So after reading your question, I'm currently thinking:

  • Using a ContainerRequestFilter to start transactions (in combination with the @NameBinding annotation construction).
  • Using a ContainerResponseFilter to commit transactions (if the resource method has not yet closed it).
  • Using a Filter to make sure the transaction was closed, and if not, roll it back.

Need Your Help

Large Text and Images In SQL

sql mysql sql-server

Is it a good idea to store large amounts of text (eg html pages) inside your SQL database? Or is it a better idea to store it as html files in the filesystem?

JUnit & Integration tests - Is it possible to run one ahead of any test that is run

java junit

I have extracted all my integration tests out of my multi-module setup and put them all into a separate project. These integration tests are based on spring and a use a real database. I am using