users@jersey.java.net

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

From: Martin Probst <mail_at_martin-probst.com>
Date: Mon, 8 Jun 2009 19:07:43 +0200

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

I'm not quite sure about that. Basically in the Java code I want to
make sure I close that session after the code has executed, and I'd
like to only commit it if I didn't throw an exception. Come to think
of it, that might not be a good idea as a WebApplicationException for
code 304 or similar is not exactly an error, so I might have to
special-case WAEs. I'll probably have to think about that a bit more
to find out what exactly constitutes an error in my application.

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

The not so nice thing about the servlet filter is that you loose all
the niceties of Jersey (and there are a lot!) once your at that level.
But an ExceptionMapper<Throwable> will not be called reliably, because
there might be additional mappers for exception classes that are
closer to the actual thrown exception, right? This doesn't quite meet
with my requirement of really making sure the transaction handling
will always work properly.

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

See here:
https://jersey.dev.java.net/issues/show_bug.cgi?id=303

However the code above creates the Child object by accessing the
session outside of the try/finally, was that intentional? That
wouldn't quite work for me: the point is that you want the
continuation to do all the session related work, so you cannot
construct the actual return value beforehand.

I'd rather have something like this:

public Continuation getChild() {
  final Session session = getSession(...);
  return new Continuation() {
    public void continue(Chain chain) {
      try {
        Child child = session.get("foo"); // .. or whatever
        chain.continueWith(child);
        session.commit();
      } finally {
        if (session.isOpen()) session.rollback();
      }
    }
  };
}

So you basically create a continuation that is responsible for
yielding the actual sub-locator and passing it to the rule chain,
which will then continue just as if the method had directly returned
the child in the first place.

How do the regular EntityManager people handle this? They should be
having the same problem - do they get notified of a request gone bad
in some way?

Martin