In “Transaction Handling in Tapestry5” I described, how to configure transactions wrapping a complete page or component render request. The same is necessary (possible) for Ajax components. Besides having less transactions and sharing the first-level-cache for subsequent calls, this realizes the “Open Session in View Pattern” automatically. So you can access the database lazily via getter from an entity, for example, without running into lazy loading exceptions due to the fact that the transaction has been closed and the entities are detached already.
Similar to the page- and component render filter we add a ajax component filter:
public void contributeAjaxComponentEventRequestHandler(OrderedConfiguration<ComponentEventRequestFilter> configuration, @InjectService("AjaxTransactionFilter") ComponentEventRequestFilter ajaxComponentTransactionFilter ) { configuration.add("ajaxComponentTransactionFilter", ajaxComponentTransactionFilter); } public ComponentEventRequestFilter buildAjaxTransactionFilter() { return new ComponentEventRequestFilter() { @Override public void handle(ComponentEventRequestParameters parameters, ComponentEventRequestHandler handler) throws IOException { try { // begin transaction, process page render request and commit the transaction. // rollback the transaction, if an exception is thrown. UserTransaction tx = ControllerUtil.beginTransaction(); try { handler.handle(parameters); ControllerUtil.commitTransaction(tx); } catch (RuntimeException e) { ControllerUtil.rollbackTransaction(tx); throw e; } } catch (Exception e) { throw new IllegalStateException(e); } } }; }
See “Circumvent Nested Transaction Issues in Tapestry-5.x” for resolving issues with nested transactions.