org.wamblee.wicket.transactions.OpenTransactionInViewRequestCycle Maven / Gradle / Ivy
/*
* 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");
}
}
}