JTA: Added option to register "joinTransaction" function and which classes to NOT roll back on

This commit is contained in:
Jonas Bonér 2010-04-22 12:18:18 +02:00
parent 8605b85ab0
commit 41b78d0bc7
2 changed files with 44 additions and 34 deletions

View file

@ -54,6 +54,7 @@ import se.scalablesolutions.akka.config.Config._
*/
object TransactionContext extends TransactionProtocol with Logging {
implicit val tc = TransactionContainer()
private[TransactionContext] val stack = new scala.util.DynamicVariable(new TransactionContext(tc))
/**
@ -91,6 +92,32 @@ object TransactionContext extends TransactionProtocol with Logging {
*/
def registerSynchronization(sync: Synchronization) = synchronization.add(sync)
/**
* Registeres a join transaction function.
* <p/>
* Here is an example on how to integrate with JPA EntityManager.
*
* <pre>
* TransactionContext.registerJoinTransactionFun(() => {
* val em: EntityManager = ... // get the EntityManager
* em.joinTransaction // join JTA transaction
* })
* </pre>
*/
def registerJoinTransactionFun(fn: () => Unit) = joinTransactionFuns.add(fn)
/**
* Handle exception. Can be overriden by concrete transaction service implementation.
* <p/>
* Here is an example on how to handle JPA exceptions.
*
* <pre>
* TransactionContext.registerExceptionNotToRollbackOn(classOf[NoResultException])
* TransactionContext.registerExceptionNotToRollbackOn(classOf[NonUniqueResultException])
* </pre>
*/
def registerExceptionNotToRollbackOn(e: Class[_ <: Exception]) = exceptionsNotToRollbackOn.add(e)
object Required extends TransactionMonad {
def map[T](f: TransactionMonad => T): T = withTxRequired { f(this) }
def flatMap[T](f: TransactionMonad => T): T = withTxRequired { f(this) }

View file

@ -68,43 +68,26 @@ import javax.transaction.{
trait TransactionProtocol extends Logging {
protected val synchronization: JList[Synchronization] = new CopyOnWriteArrayList[Synchronization]
protected val joinTransactionFuns: JList[() => Unit] = new CopyOnWriteArrayList[() => Unit]
protected val exceptionsNotToRollbackOn: JList[Class[_ <: Exception]] = new CopyOnWriteArrayList[Class[_ <: Exception]]
/**
* Join JTA transaction. Can be overriden by concrete transaction service implementation
* to hook into other transaction services.
* <p/>
* Here is an example on how to integrate with JPA EntityManager.
*
* <pre>
* override def joinTransaction = {
* val em: EntityManager = ... // get the EntityManager
* em.joinTransaction // join JTA transaction
* }
* </pre>
*/
def joinTransaction: Unit = {}
def joinTransaction: Unit = {
val it = joinTransactionFuns.iterator
while (it.hasNext) {
val fn = it.next
fn()
}
}
/**
* Handle exception. Can be overriden by concrete transaction service implementation.
* <p/>
* Here is an example on how to handle JPA exceptions.
*
* <pre>
* def handleException(tm: TransactionContainer, e: Exception) = {
* if (isInExistingTransaction(tm)) {
* // Do not roll back in case of NoResultException or NonUniqueResultException
* if (!e.isInstanceOf[NoResultException] &&
* !e.isInstanceOf[NonUniqueResultException]) {
* log.debug("Setting TX to ROLLBACK_ONLY, due to: %s", e)
* tm.setRollbackOnly
* }
* }
* throw e
* }
* </pre>
*/
def handleException(tm: TransactionContainer, e: Exception) = {
tm.setRollbackOnly
var rollback = true
val it = joinTransactionFuns.iterator
while (it.hasNext) {
val exception = it.next
if (e.getClass.isAssignableFrom(exception.getClass))
rollback = false
}
if (rollback) tm.setRollbackOnly
throw e
}