users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 08 Jun 2009 11:26:41 +0200

On Jun 6, 2009, at 10:00 AM, Martin Probst wrote:

> 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.
>


By success if you mean the status code is < 500 for success and >= 500
otherwise then you can perform that check within the Closeable
implementation. For example:

public class MyCloseable implements Closeable {
   private HttpContext hc;

   public MyCloseable(HttpContext hc, ...) { this.hc = hc; }

   public void close() {
     if (hc.getResponse().getStatus() < 500) {
         ...
     } else {
         ...
     }
   }
}


But for Servlet there are cases where the exception may be passed
through to the Servlet (if it is not mapped by Jersey), so the status
may not be set accordingly unless you have an exception mapper to map
all exceptions, or use a servlet filter as you have done.



I think your idea of allowing a sub-locator method to continue
matching within its stack frame is an interesting idea. It should be
something that is possible to support, i like the idea of returning a
"closure" from which the continue can be performed and wrapped around
a try/catch, that way it the "RuleChain" is something that cannot be
used in other incorrect scenarios.

public Continuation getChild() {
    final Session session = getSession(...);

    return new Continuation(new Child(session.get(childName)) {
        public continue(Continuation next) {
            try {
                next.continue();
            } catch(Exception e) { ... }
              finally { ... }
        }
    }
}

If this is something you would like to see can you please log a
feature/enhancement issue.

Thanks,
Paul



> 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
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>