I'd like to discuss how to best use (JPA) transactions with RequestFactory.

As a basis, I'm assuming the approach where one user interaction should 
normally result in one DB transaction, so that the whole interaction can 
either fail or succeed, atomically.

The first thing to consider with RequestFactory is, that each method call 
in a RequestContext can succeed or fail individually. Also note, that the 
fire() call will (usually) succeed as a whole, even if one of the 
RequestContext method calls fails.

So for example, if you have

  ctx.opA().to(receiverA);
  ctx.opB().to(receiverB);
  ctx.fire(receiverX);

Then this may result in the sequence

  receiverA.onSuccess(), 
  receiverB.onFailure(), 
  receiverX.onSuccess().

What this means is, that you get atomicity only for the individual 
RequestContext methods. Therefore you definitely shouldn't wrap the entire 
RequestFactoryServlet's onPost() method in one transaction, but rather only 
the individual service method implementations individually. (Otherwise, the 
client may believe, that opA has succeeded, while in reality the entire 
transaction was rolled back.)

And if you need a transaction with multiple objects involved, you will have 
to wrap the entire interaction in one service method call.

*Side note: Convenience solution*
*
*
If you grow tired of wrapping each service method implementation in a 
transaction individually, you may want to use your own 
ServiceLayerDecorator in the RequestFactoryServlet constructor, and 
override invoke() like this:

  @Override
  public Object invoke(final Method domainMethod, final Object... args) {
     
    // Note: Ideally use dependency injecton for this:
    final EntityManager em = getRequestScopedEntityManager();

    try {
      
      em.getTransaction().begin();
      final Object result = super.invoke(domainMethod, args);
      em.getTransaction().commit();
      
      return result;
      
    } catch (final Error e) {
      em.getTransaction().rollback();
      throw e;
      
    } catch (final RuntimeException e) {
      em.getTransaction().rollback();
      throw e;
    }
  }

(Better solutions are welcome!)


*Question/Discussion:*

There is however a little issue that remains: RequestFactory calls 
Locator.find() outside of such a transaction:

   1. In RequestState.getBeansForPayload(), which calls 
   ServiceLayerDecorator.loadDomainObjects()
   2. In SimpleRequestProcessor.createReturnOperations, which calls 
   ServiceLayerDecorator.isLive()

I think, it's possible to pretty much ignore this (at least if you don't 
use isolation levels higher than READ_COMMITTED, and if your DB is ok with 
autocommit style queries), or is it? Note: My Locator's find method re-uses 
the same RequestScoped EntityManager instance - so I get the same 
underlying Hibernate session with the same first-level cache - it's just 
not in the same transaction, that's all.

How do you deal with this? What is the intended transaction concept by the 
RequestFactory designers?

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-web-toolkit/-/ASBa77ljy3cJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to