Changed JtaModule to use structural typing instead of Field reflection, plus added a guard
This commit is contained in:
parent
8e884df116
commit
ea60588c21
6 changed files with 41 additions and 27 deletions
|
|
@ -9,7 +9,7 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||
|
||||
import scala.collection.mutable.HashMap
|
||||
|
||||
import se.scalablesolutions.akka.util.ReflectiveAccess.JTAModule._
|
||||
import se.scalablesolutions.akka.util.ReflectiveAccess.JtaModule
|
||||
|
||||
import se.scalablesolutions.akka.util.Logging
|
||||
import se.scalablesolutions.akka.config.Config._
|
||||
|
|
@ -92,8 +92,8 @@ object Transaction {
|
|||
private[this] val persistentStateMap = new HashMap[String, Committable with Abortable]
|
||||
private[akka] val depth = new AtomicInteger(0)
|
||||
|
||||
val jta: Option[TransactionContainer] =
|
||||
if (JTA_AWARE) Some(createTransactionContainer)
|
||||
val jta: Option[JtaModule.TransactionContainer] =
|
||||
if (JTA_AWARE) Some(JtaModule.createTransactionContainer)
|
||||
else None
|
||||
|
||||
log.trace("Creating transaction " + toString)
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ object ReflectiveAccess {
|
|||
|
||||
lazy val isRemotingEnabled = RemoteClientModule.isRemotingEnabled
|
||||
lazy val isTypedActorEnabled = TypedActorModule.isTypedActorEnabled
|
||||
lazy val isJtaEnabled = JtaModule.isJtaEnabled
|
||||
|
||||
def ensureRemotingEnabled = RemoteClientModule.ensureRemotingEnabled
|
||||
def ensureTypedActorEnabled = TypedActorModule.ensureTypedActorEnabled
|
||||
def ensureJtaEnabled = JtaModule.ensureJtaEnabled
|
||||
|
||||
/**
|
||||
* Reflective access to the RemoteClient module.
|
||||
|
|
@ -193,7 +195,11 @@ object ReflectiveAccess {
|
|||
}
|
||||
}
|
||||
|
||||
object JTAModule {
|
||||
object JtaModule {
|
||||
|
||||
type TransactionContainerObject = {
|
||||
def apply(): TransactionContainer
|
||||
}
|
||||
|
||||
type TransactionContainer = {
|
||||
def beginWithStmSynchronization(transaction: Transaction): Unit
|
||||
|
|
@ -201,15 +207,23 @@ object ReflectiveAccess {
|
|||
def rollback: Unit
|
||||
}
|
||||
|
||||
def createTransactionContainer: TransactionContainer = {
|
||||
try {
|
||||
val clazz = Class.forName("se.scalablesolutions.akka.stm.TransactionContainer$")
|
||||
val instance = clazz.getDeclaredField("MODULE$")
|
||||
val applyMethod = clazz.getDeclaredMethod("apply")
|
||||
applyMethod.invoke(instance.get(null)).asInstanceOf[TransactionContainer]
|
||||
} catch {
|
||||
case cnfe: ClassNotFoundException => throw new IllegalStateException("Couldn't locale akka-jta, make sure you have it on your classpath")
|
||||
lazy val isJtaEnabled = transactionContainerObjectInstance.isDefined
|
||||
|
||||
def ensureJtaEnabled = if (!isJtaEnabled) throw new ModuleNotAvailableException(
|
||||
"Can't load the typed actor module, make sure that akka-jta.jar is on the classpath")
|
||||
|
||||
val transactionContainerObjectInstance: Option[TransactionContainerObject] = {
|
||||
try {
|
||||
val clazz = loader.loadClass("se.scalablesolutions.akka.actor.TransactionContainer$")
|
||||
val ctor = clazz.getDeclaredConstructor(Array[Class[_]](): _*)
|
||||
ctor.setAccessible(true)
|
||||
Some(ctor.newInstance(Array[AnyRef](): _*).asInstanceOf[TransactionContainerObject])
|
||||
} catch { case e: Exception => None }
|
||||
}
|
||||
|
||||
def createTransactionContainer: TransactionContainer = {
|
||||
ensureJtaEnabled
|
||||
transactionContainerObjectInstance.get.apply.asInstanceOf[TransactionContainer]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.atomikos.icatch.config.{TSInitInfo, UserTransactionService, UserTrans
|
|||
|
||||
import se.scalablesolutions.akka.config.Config._
|
||||
import se.scalablesolutions.akka.util.Duration
|
||||
import se.scalablesolutions.akka.stm.{TransactionService, TransactionContainer}
|
||||
|
||||
object AtomikosTransactionService extends AtomikosTransactionService
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||
*/
|
||||
|
||||
package se.scalablesolutions.akka.stm
|
||||
package se.scalablesolutions.akka.jta
|
||||
|
||||
import javax.transaction.{TransactionManager, UserTransaction,
|
||||
Transaction => JtaTransaction, SystemException,
|
||||
|
|
@ -11,8 +11,11 @@ import javax.naming.{InitialContext, Context, NamingException}
|
|||
|
||||
import se.scalablesolutions.akka.config.Config._
|
||||
import se.scalablesolutions.akka.util.Logging
|
||||
import se.scalablesolutions.akka.stm.Transaction
|
||||
import se.scalablesolutions.akka.AkkaException
|
||||
|
||||
class JtaConfigurationException(message: String) extends AkkaException(message)
|
||||
|
||||
/**
|
||||
* Detects if there is a UserTransaction or TransactionManager available in the JNDI.
|
||||
*
|
||||
|
|
@ -47,12 +50,12 @@ object TransactionContainer extends Logging {
|
|||
.transactionContainer
|
||||
} catch {
|
||||
case e: ClassNotFoundException =>
|
||||
throw new StmConfigurationException(
|
||||
throw new JtaConfigurationException(
|
||||
"JTA provider defined as 'atomikos', but the AtomikosTransactionService classes can not be found." +
|
||||
"\n\tPlease make sure you have 'akka-jta' JAR and its dependencies on your classpath.")
|
||||
}
|
||||
case _ =>
|
||||
throw new StmConfigurationException(
|
||||
throw new JtaConfigurationException(
|
||||
"No UserTransaction on TransactionManager could be found in scope." +
|
||||
"\n\tEither add 'akka-jta' to the classpath or make sure there is a" +
|
||||
"\n\tTransactionManager or UserTransaction defined in the JNDI.")
|
||||
|
|
@ -133,7 +136,7 @@ class TransactionContainer private (
|
|||
tm match {
|
||||
case Left(Some(userTx)) => userTx.begin
|
||||
case Right(Some(txMan)) => txMan.begin
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +145,7 @@ class TransactionContainer private (
|
|||
tm match {
|
||||
case Left(Some(userTx)) => userTx.commit
|
||||
case Right(Some(txMan)) => txMan.commit
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,42 +154,42 @@ class TransactionContainer private (
|
|||
tm match {
|
||||
case Left(Some(userTx)) => userTx.rollback
|
||||
case Right(Some(txMan)) => txMan.rollback
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
}
|
||||
|
||||
def getStatus = tm match {
|
||||
case Left(Some(userTx)) => userTx.getStatus
|
||||
case Right(Some(txMan)) => txMan.getStatus
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
|
||||
def isInExistingTransaction = tm match {
|
||||
case Left(Some(userTx)) => userTx.getStatus == Status.STATUS_ACTIVE
|
||||
case Right(Some(txMan)) => txMan.getStatus == Status.STATUS_ACTIVE
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
|
||||
def isRollbackOnly = tm match {
|
||||
case Left(Some(userTx)) => userTx.getStatus == Status.STATUS_MARKED_ROLLBACK
|
||||
case Right(Some(txMan)) => txMan.getStatus == Status.STATUS_MARKED_ROLLBACK
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
|
||||
def setRollbackOnly = tm match {
|
||||
case Left(Some(userTx)) => userTx.setRollbackOnly
|
||||
case Right(Some(txMan)) => txMan.setRollbackOnly
|
||||
case _ => throw new StmConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a UserTransaction or TransactionManager in scope")
|
||||
}
|
||||
|
||||
def suspend = tm match {
|
||||
case Right(Some(txMan)) => txMan.suspend
|
||||
case _ => throw new StmConfigurationException("Does not have a TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a TransactionManager in scope")
|
||||
}
|
||||
|
||||
def resume(tx: JtaTransaction) = tm match {
|
||||
case Right(Some(txMan)) => txMan.resume(tx)
|
||||
case _ => throw new StmConfigurationException("Does not have a TransactionManager in scope")
|
||||
case _ => throw new JtaConfigurationException("Does not have a TransactionManager in scope")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package se.scalablesolutions.akka.jta
|
|||
|
||||
import javax.transaction.{Transaction, Status, TransactionManager, Synchronization}
|
||||
|
||||
import se.scalablesolutions.akka.stm.{TransactionService, TransactionContainer}
|
||||
import se.scalablesolutions.akka.util.Logging
|
||||
import se.scalablesolutions.akka.config.Config._
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
package se.scalablesolutions.akka.jta
|
||||
|
||||
import se.scalablesolutions.akka.util.Logging
|
||||
import se.scalablesolutions.akka.stm.TransactionContainer
|
||||
|
||||
import java.util.{List => JList}
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue