users@jersey.java.net

Re: [Jersey] Resource Management through nested sub-locators

From: Martin Probst <mail_at_martin-probst.com>
Date: Sat, 6 Jun 2009 10:00:55 +0200

Hi Paul,

thanks for your reply.

CloseableService is not enough for me - I would need something that
gets notified when/if an exception occurs. For me, the distinction
between regular termination and error termination is important as that
means whether I need to roll back my transaction or not.

However I think I have mostly solved it. I implemented a regular
servlet Filter that will either commit a pending session on success or
roll it back otherwise. Resources request a session from that filter
class through a static method which stores the session in a thread
local, and makes sure there is always just one per thread. It's a bit
ugly with static, thread locals, and moving outside of Jersey, but it
works.

Martin

On Fri, Jun 5, 2009 at 21:17, Paul Sandoz<Paul.Sandoz_at_sun.com> wrote:
> Hi Martin,
>
> Will CloseableService suit your needs:
>
> https://jersey.dev.java.net/nonav/apidocs/1.1.0ea/jersey/com/sun/jersey/spi/CloseableService.html
>
> Create an instance of Closeable that you add to the CloseableService then
> when the request goes out of scope the close method will be called on the
> instance.
>
> The code at the end of the email shows how things are closed in
> WebApplicationImpl.
>
> Paul.
>
>    public void handleRequest(ContainerRequest request, ContainerResponse
> response) throws IOException {
>        final WebApplicationContext localContext = new
>                WebApplicationContext(this, request, response);
>
>        context.set(localContext);
>        try {
>            _handleRequest(localContext, request, response);
>        } finally {
>            PerRequestFactory.destroy(localContext);
>            closeableFactory.close(localContext);
>            context.set(null);
>        }
>    }
>
> On Jun 4, 2009, at 11:05 AM, Martin Probst wrote:
>
>> Hi,
>>
>> I'm trying to write an app where a resource opens a transactional
>> context that is then used in sublocators, e.g.:
>>
>> @Path("/")
>> class MyResource {
>>
>>  @Path("{child}") Child getChild(@PathParam("child") String childName) {
>>   Session session = getSession(...);
>>   try {
>>     return new Child(session.get(childName));
>>   } catch (Exception e) {
>>     // mhmhm
>>   } finally {
>>     // whoops ?!
>>   }
>>  }
>> }
>>
>> class Child {
>>  @Path("FOO!!!") Foo getFoo(...) { ... };
>> }
>>
>> So, basically I want to open a resource - not in the REST meaning, but
>> in the "file descriptor"/scarce system resource meaning -, in this
>> case a session, and use that in classes that have sub-locators.
>>
>> All nice and dandy, but now I need to manage that resource. So I need
>> to make sure that it will absolutely always be
>> closed/recycled/whatever, and in case an exception happens my session
>> needs to be closed.
>>
>> I found something that recommended @PreDestroy, and that will work for
>> the regular closing part, even though it's a bit ugly. Also, I'm not
>> sure of the semantics - will this be called in case of exceptions?
>> What happens if the @PreDestroy method throws an exception?
>>
>> The other thing is to react when exceptions are thrown. I can
>> implement an ExceptionMapper<Throwable> or <RuntimeException> which
>> will then always be notified if something goes wrong within the web
>> application. The mapper would roll back my session and then ideally
>> re-throw the exception. But that is not allowed from the interface, so
>> it has to convert to a 500 response or something like that.
>>
>> I'm pretty sure that this will work, but it seems like a pretty large
>> stretch of the design, coming from the simple try/catch/finally
>> construct I'm used to. The problem is of course that by passing back
>> the control to Jersey for sublocators, my application code is losing
>> control of the stack, and thus loosing the grip on exceptions and
>> return values.
>>
>> Now, am I missing something or is this just a limitation?
>>
>> If it is a limitation, I'd like to suggest maybe allowing resource
>> methods to request as a @Context parameter some special object which
>> is in effect the UriRule chain from Jersey (or rather some public
>> interface). Then I could do this (in getChild(...) above):
>>
>> public void getChild(@Context RuleChain continuation) {
>>   Session session = getSession(...);
>>   try {
>>     continuation.continueWith(new Child(session.get(childName)));
>>     session.commit();
>>   } catch (Exception e) {
>>     session.rollback();
>>     throw e;
>>   } finally {
>>     session.close();
>>   }
>> }
>>
>> So to allow users to keep the stack hierarchy intact. Or is this
>> already possible and I'm just missing the fact?
>>
>> I think this should be a not totally uncommon use case to open some
>> scarce resource (files, sockets, images, whatever ...), use it in
>> subrules, and really make sure you close it. The workaround with
>> @PreDestroy and ExceptionMapper seems cumbersome and error prone, and
>> I'd guess that there may be a lot of corner cases which are otherwise
>> guaranteed to be covered by the finally block.
>>
>> Martin
>>
>> ---------------------------------------------------------------------
>> 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
>
>