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