From 16aa82e4a7755e096585f24d3714790b535f91d2 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sat, 17 Jul 2010 14:11:31 +0000 Subject: [PATCH 1/1] --- .../OpenTransactionInViewRequestCycle.java | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 wicket/joe/src/main/java/org/wamblee/wicket/transactions/OpenTransactionInViewRequestCycle.java diff --git a/wicket/joe/src/main/java/org/wamblee/wicket/transactions/OpenTransactionInViewRequestCycle.java b/wicket/joe/src/main/java/org/wamblee/wicket/transactions/OpenTransactionInViewRequestCycle.java new file mode 100644 index 00000000..2953aa07 --- /dev/null +++ b/wicket/joe/src/main/java/org/wamblee/wicket/transactions/OpenTransactionInViewRequestCycle.java @@ -0,0 +1,142 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.wicket.transactions; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +import org.apache.wicket.Application; +import org.apache.wicket.Page; +import org.apache.wicket.Response; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WebRequest; +import org.apache.wicket.protocol.http.WebRequestCycle; + +/** + *

+ * This class provides an Open Transaction in View implementation for + * wicket. It provides a custom request cycle that uses the + * {@link UserTransaction} to make sure that all work is done within a single + * transaction. In hibernate context, this is referred to as open session in + * view. + *

+ * + *

+ * The method used by this class is more correctly called + * Open Transaction in View and has a similar effect to open session in + * view. It is however more general because it supports any (JTA) transactional + * resource. Also it is more efficient/scalable than most open session in view + * implementations because a database connection is only obtained from the + * connection pool when it is needed. + *

+ * + *

+ * To use this request cycle, add it in your wicket {@link Application} subclass + * by overriding + * {@link Application#newRequestCycle(org.apache.wicket.Request, Response)}. For + * example: + *

+ * + *
+ * @Override
+ * public RequestCycle newRequestCycle(Request aRequest, Response aResponse) {
+ *     return new OpenTransactionInViewRequestCycle(this, (WebRequest) aRequest,
+ *         aResponse);
+ * }
+ * 
+ * + * @author Erik Brakkee + * + */ +public class OpenTransactionInViewRequestCycle extends WebRequestCycle { + + private static final Logger LOG = Logger.getLogger(OpenTransactionInViewRequestCycle.class.getName()); + + private static final String JAVA_COMP_USER_TRANSACTION_JNDI = "java:comp/UserTransaction"; + private UserTransaction userTransaction; + + /** + * Constructs the request cycle. + * + * @param aApplication + * Application to use. + * @param aRequest + * Request + * @param aResponse + * Response. + */ + public OpenTransactionInViewRequestCycle(final WebApplication aApplication, + final WebRequest aRequest, final Response aResponse) { + super(aApplication, aRequest, aResponse); + userTransaction = getUserTransaction(); + } + + @Override + protected void onBeginRequest() { + try { + userTransaction.begin(); + } catch (Exception e) { + throw new RuntimeException("Could not start transaction", e); + } + super.onBeginRequest(); + } + + @Override + protected void onEndRequest() { + try { + if ( LOG.isLoggable(Level.FINEST)) { + LOG.finest("Transaction status: " + userTransaction.getStatus()); + } + if (userTransaction.getStatus() == Status.STATUS_ACTIVE) { + userTransaction.commit(); + } else if (userTransaction.getStatus() == Status.STATUS_MARKED_ROLLBACK) { + userTransaction.rollback(); + } else { + LOG.warning("Transaction status is '" + userTransaction.getStatus() + "' not committing or rolling back"); + } + } catch (Exception e) { + throw new RuntimeException("Could not commit transaction", e); + } + super.onEndRequest(); + } + + @Override + public Page onRuntimeException(Page aPage, RuntimeException aE) { + super.onEndRequest(); + try { + userTransaction.rollback(); + } catch (Exception e) { + throw new RuntimeException("Could not rollback transaction", e); + } + return super.onRuntimeException(aPage, aE); + } + + private UserTransaction getUserTransaction() { + try { + InitialContext ctx = new InitialContext(); + return (UserTransaction) ctx + .lookup(JAVA_COMP_USER_TRANSACTION_JNDI); + } catch (NamingException e) { + throw new RuntimeException( + "Could not obtain user transaction object"); + } + } +} -- 2.31.1