users@jersey.java.net

Re: [Jersey] transaction-per-request

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 19 Apr 2010 10:50:41 +0200

HI Adam,

The problem with using a ContainerResponseFilter to commit or roll
back is that the response filter is not guaranteed to get called in
the following circumstances:

1) if the resource throws an exception that is not mapped.
      The exception will get passed through to the container and
response filters will not be called.

2) a filter declared before TransactionManagementFilter throws an
exception.
     This breaks the filter chain:

   https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/package-summary.html

I am not sure if that is what you intended or not.

If you are not interesting in supporting the mapping of exceptions to
error pages then you can map say Throwable to a 500 response, this
will catch anything that would otherwise be destined for the
container. Then you can do the commit or rollback in the Closeable

Paul.



On Apr 16, 2010, at 8:37 PM, Adam Rabung wrote:

> Aha, I think getMappedThrowable was the missing piece of the puzzle
> for me. Like Martin, I want to be able to rollback on exception.
> Does this code look like a good start to you? My transactions are
> thread-local, and managed via these static methods...
>
> package mdt.web.jersey;
>
> import java.io.Closeable;
> import java.io.IOException;
>
> import javax.ws.rs.core.Context;
>
> import mdt.core.Transaction;
>
> import com.sun.jersey.spi.CloseableService;
> import com.sun.jersey.spi.container.ContainerRequest;
> import com.sun.jersey.spi.container.ContainerRequestFilter;
> import com.sun.jersey.spi.container.ContainerResponse;
> import com.sun.jersey.spi.container.ContainerResponseFilter;
>
> public class TransactionManagementFilter implements
> ContainerResponseFilter, ContainerRequestFilter {
> private CloseableService _closeableService;
>
> public TransactionManagementFilter(@Context CloseableService cs) {
> _closeableService = cs;
> }
>
> public ContainerRequest filter(ContainerRequest req) {
> Transaction.start();
> _closeableService.add(new TransactionReference());
> return req;
> }
>
> public ContainerResponse filter(ContainerRequest req,
> ContainerResponse response) {
> if (response.getMappedThrowable() == null) {
> Transaction.commit();
> }
> else {
> Transaction.rollback();
> }
> return response;
> }
>
> public static class TransactionReference implements Closeable {
> public void close() throws IOException {
> Transaction.ensureTransactionClosed();
> }
> }
> }
>
>
> On Fri, Apr 16, 2010 at 9:53 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
> wrote:
>> HI Adam,
>>
>> To be honest i cannot recall all that discussion :-) need to go
>> through it
>> again.
>>
>> Filters are not appropriate to perform rolllback because the chain
>> can be
>> bypassed or broken by the throwing of an exception. But a request
>> filter
>> could add a Closeable that is guaranteed to get called. IIRC Martin
>> had a
>> particular requirement related to throwing of exceptions and
>> rollback. It is
>> now possible to obtain the mapped exception from ContainerResponse:
>>
>> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/spi/container/ContainerResponse.html
>> #getMappedThrowable%28%29
>>
>> but i do not know if that satisfies his needs.
>>
>>
>> To help me get up to speed can you tell me what your ideal solution
>> might
>> look like and using CloseableService does not work for you?
>>
>> Paul.
>>
>> On Apr 15, 2010, at 7:08 PM, Adam Rabung wrote:
>>
>>> Hello,
>>> I am trying to cleanly implement "transaction-per-request" alongside
>>> Jersey Resources. That is, I'd like no mention of transactions in
>>> individual resources, but rather in a central place, as outlined by
>>> Martin Probst in an earlier email [1]:
>>>
>>> try {
>>> chain.doFilter(request, response);
>>> commitSession();
>>> } finally {
>>> rollbackSession(); // no-op if already committed
>>> closeSession();
>>> }
>>>
>>> I've seen a few conversations about this topic on the mailing list,
>>> but I can't piece together a good solution using the advice. I'd
>>> rather avoid Spring for tx management, as it's not yet a dependency.
>>> I've taken a look at CloseableService, ResourceFilter, overriding
>>> ServletContainer.service, etc, and cannot see how I can use these to
>>> implement transparent rollback-on-exception. I got it working by
>>> calling rollback in a custom ExceptionMapper, but that feels very
>>> dirty :)
>>>
>>> If anyone has pulled this off, could they offer some pseudocode
>>> describing the approach? Extra bonus points if the solution gives
>>> me
>>> metadata on what resource is being executed :)
>>>
>>> Thank you,
>>> Adam
>>>
>>> [1] http://markmail.org/thread/aefgmci6r2thkqxc
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>