Author: swd847
Date: 2010-07-15 08:52:34 -0400 (Thu, 15 Jul 2010)
New Revision: 13405
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/AbstractUserTransaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/CMTTransaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EJB.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EjbSynchronizations.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/LocalEjbSynchronizations.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Naming.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/NoTransaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SeSynchronizations.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SynchronizationRegistry.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Synchronizations.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionExtension.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionInterceptor.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UTTransaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UserTransaction.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Work.java
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/Hotel.java
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/SimpleTest.java
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/ArtifactNames.java
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/MavenArtifactResolver.java
modules/persistence/trunk/src/test/resources-glassfish/
modules/persistence/trunk/src/test/resources-glassfish/sun-resources.xml
modules/persistence/trunk/src/test/resources-jbossas/
modules/persistence/trunk/src/test/resources-jbossas/jndi.properties
modules/persistence/trunk/src/test/resources-jbossas/seam-transactions-test-ds.xml
modules/persistence/trunk/src/test/resources/META-INF/
modules/persistence/trunk/src/test/resources/META-INF/persistence.xml
modules/persistence/trunk/src/test/resources/META-INF/seam-beans.xml
modules/persistence/trunk/src/test/resources/arquillian.xml
Modified:
modules/persistence/trunk/pom.xml
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionPropagation.java
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transactional.java
Log:
initial port of seam 2 transaction management
Modified: modules/persistence/trunk/pom.xml
===================================================================
--- modules/persistence/trunk/pom.xml 2010-07-15 12:28:14 UTC (rev 13404)
+++ modules/persistence/trunk/pom.xml 2010-07-15 12:52:34 UTC (rev 13405)
@@ -15,8 +15,16 @@
<properties>
<seam.version>3.0.0.b01</seam.version>
+ <arquillian.version>1.0.0-SNAPSHOT</arquillian.version>
+ <junit.version>4.8.1</junit.version>
+ <jboss.home>${env.JBOSS_HOME}</jboss.home>
+ <jboss.domain>default</jboss.domain>
+ <glassfish.version>3.0.1-b19</glassfish.version>
+ <jboss-as-client.version>6.0.0-SNAPSHOT</jboss-as-client.version>
+ <jboss-javaee6-spec.version>1.0.0.Beta4</jboss-javaee6-spec.version>
+ <jboss-server-manager.version>1.0.3.GA</jboss-server-manager.version>
</properties>
-
+
<prerequisites>
<maven>3.0</maven>
</prerequisites>
@@ -30,12 +38,32 @@
<type>pom</type>
<scope>import</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-junit</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+
</dependencies>
+
+
</dependencyManagement>
<dependencies>
-
<dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
@@ -67,9 +95,142 @@
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.jboss.spec</groupId>
+ <artifactId>jboss-javaee-6.0</artifactId>
+ <version>${jboss-javaee6-spec.version}</version>
+ <type>pom</type>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.weld</groupId>
+ <artifactId>weld-extensions</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <profiles>
+ <profile>
+ <id>default</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>jbossas-remote-60</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-jbossas-remote-6</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec</groupId>
+ <artifactId>jboss-javaee-6.0</artifactId>
+ <version>${jboss-javaee6-spec.version}</version>
+ <type>pom</type>
+ <scope>provided</scope>
+ </dependency>
+ <!-- need for org.jnp.interfaces.NamingContextFactory -->
+ <dependency>
+ <groupId>org.jboss.jbossas</groupId>
+ <artifactId>jboss-as-client</artifactId>
+ <version>${jboss-as-client.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-jbossas</directory>
+ </testResource>
+ </testResources>
+ </build>
+ </profile>
+
+ <profile>
+ <id>glassfish-embedded-30</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-glassfish-embedded-30</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.extras</groupId>
+ <artifactId>glassfish-embedded-all</artifactId>
+ <version>${glassfish.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-glassfish</directory>
+ </testResource>
+ </testResources>
+ </build>
+ </profile>
+
+ <profile>
+ <id>glassfish-remote-30</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-glassfish-remote-30</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.extras</groupId>
+ <artifactId>glassfish-embedded-all</artifactId>
+ <version>${glassfish.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-glassfish</directory>
+ </testResource>
+ </testResources>
+ </build>
+ </profile>
+ </profiles>
+
<scm>
<
connection>scm:svn:http://anonsvn.jboss.org/repos/seam/modules/persist...
<
developerConnection>scm:svn:https://svn.jboss.org/repos/seam/modules/p...
@@ -77,3 +238,4 @@
</scm>
</project>
+
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/AbstractUserTransaction.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/AbstractUserTransaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/AbstractUserTransaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,86 @@
+package org.jboss.seam.transaction;
+
+import static javax.transaction.Status.STATUS_ACTIVE;
+import static javax.transaction.Status.STATUS_COMMITTED;
+import static javax.transaction.Status.STATUS_MARKED_ROLLBACK;
+import static javax.transaction.Status.STATUS_NO_TRANSACTION;
+import static javax.transaction.Status.STATUS_ROLLEDBACK;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+
+/**
+ * Base implementation of UserTransaction
+ *
+ * @author Gavin King
+ *
+ */
+public abstract class AbstractUserTransaction implements UserTransaction
+{
+
+ private final Synchronizations synchronizations;
+
+ public AbstractUserTransaction(Synchronizations synchronizations)
+ {
+ this.synchronizations = synchronizations;
+ }
+
+ public boolean isActive() throws SystemException
+ {
+ return getStatus() == STATUS_ACTIVE;
+ }
+
+ public boolean isActiveOrMarkedRollback() throws SystemException
+ {
+ int status = getStatus();
+ return status == STATUS_ACTIVE || status == STATUS_MARKED_ROLLBACK;
+ }
+
+ public boolean isRolledBackOrMarkedRollback() throws SystemException
+ {
+ int status = getStatus();
+ return status == STATUS_ROLLEDBACK || status == STATUS_MARKED_ROLLBACK;
+ }
+
+ public boolean isMarkedRollback() throws SystemException
+ {
+ return getStatus() == STATUS_MARKED_ROLLBACK;
+ }
+
+ public boolean isNoTransaction() throws SystemException
+ {
+ return getStatus() == STATUS_NO_TRANSACTION;
+ }
+
+ public boolean isRolledBack() throws SystemException
+ {
+ return getStatus() == STATUS_ROLLEDBACK;
+ }
+
+ public boolean isCommitted() throws SystemException
+ {
+ return getStatus() == STATUS_COMMITTED;
+ }
+
+ public boolean isConversationContextRequired()
+ {
+ return false;
+ }
+
+ public abstract void registerSynchronization(Synchronization sync);
+
+ public void enlist(EntityManager entityManager) throws SystemException
+ {
+ if (isActiveOrMarkedRollback())
+ {
+ entityManager.joinTransaction();
+ }
+ }
+
+ public Synchronizations getSynchronizations()
+ {
+ return synchronizations;
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/CMTTransaction.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/CMTTransaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/CMTTransaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,128 @@
+package org.jboss.seam.transaction;
+
+import javax.ejb.EJBContext;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+import org.jboss.weld.extensions.core.Veto;
+
+/**
+ * Wraps EJBContext transaction management in a UserTransaction interface. Note
+ * that container managed transactions cannot be controlled by the application,
+ * so begin(), commit() and rollback() are disallowed in a CMT.
+ *
+ * @author Mike Youngstrom
+ * @author Gavin King
+ * @author Stuart Douglas
+ *
+ */
+@Veto
+public class CMTTransaction extends AbstractUserTransaction
+{
+
+ private final EJBContext ejbContext;
+
+ public CMTTransaction(EJBContext ejbContext, Synchronizations sync)
+ {
+ super(sync);
+ this.ejbContext = ejbContext;
+ if (ejbContext == null)
+ {
+ throw new IllegalArgumentException("null EJBContext");
+ }
+ }
+
+ public void begin() throws NotSupportedException, SystemException
+ {
+ ejbContext.getUserTransaction().begin();
+ getSynchronizations().afterTransactionBegin();
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException, IllegalStateException, SystemException
+ {
+ UserTransaction userTransaction = ejbContext.getUserTransaction();
+ boolean success = false;
+ Synchronizations synchronizations = getSynchronizations();
+ synchronizations.beforeTransactionCommit();
+ try
+ {
+ userTransaction.commit();
+ success = true;
+ }
+ finally
+ {
+ synchronizations.afterTransactionCommit(success);
+ }
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException,
SystemException
+ {
+ UserTransaction userTransaction = ejbContext.getUserTransaction();
+ try
+ {
+ userTransaction.rollback();
+ }
+ finally
+ {
+ getSynchronizations().afterTransactionRollback();
+ }
+ }
+
+ public int getStatus() throws SystemException
+ {
+ try
+ {
+ // TODO: not correct for SUPPORTS or NEVER!
+ if (!ejbContext.getRollbackOnly())
+ {
+ return Status.STATUS_ACTIVE;
+ }
+ else
+ {
+ return Status.STATUS_MARKED_ROLLBACK;
+ }
+ }
+ catch (IllegalStateException ise)
+ {
+ try
+ {
+ return ejbContext.getUserTransaction().getStatus();
+ }
+ catch (IllegalStateException is)
+ {
+ return Status.STATUS_NO_TRANSACTION;
+ }
+ }
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException
+ {
+ ejbContext.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int timeout) throws SystemException
+ {
+ ejbContext.getUserTransaction().setTransactionTimeout(timeout);
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization sync)
+ {
+ Synchronizations synchronizations = getSynchronizations();
+ if (synchronizations.isAwareOfContainerTransactions())
+ {
+ synchronizations.registerSynchronization(sync);
+ }
+ else
+ {
+ throw new UnsupportedOperationException("cannot register synchronization
with container transaction, use <transaction:ejb-transaction/>");
+ }
+ }
+
+}
Added: modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EJB.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EJB.java
(rev 0)
+++ modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EJB.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,39 @@
+package org.jboss.seam.transaction;
+
+import javax.ejb.EJBContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+
+/**
+ * utility class to look up the EJBContext
+ *
+ *
+ */
+public class EJB
+{
+ public static String ejbContextName = "java:comp.ejb3/EJBContext";
+ public static final String STANDARD_EJB_CONTEXT_NAME =
"java:comp/EJBContext";
+
+ public static EJBContext getEJBContext() throws NamingException
+ {
+ try
+ {
+ return (EJBContext) Naming.getInitialContext().lookup(ejbContextName);
+ }
+ catch (NameNotFoundException nnfe)
+ {
+ return (EJBContext)
Naming.getInitialContext().lookup(STANDARD_EJB_CONTEXT_NAME);
+ }
+ }
+
+ protected static String getEjbContextName()
+ {
+ return ejbContextName;
+ }
+
+ protected static void setEjbContextName(String ejbContextName)
+ {
+ EJB.ejbContextName = ejbContextName;
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EjbSynchronizations.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EjbSynchronizations.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/EjbSynchronizations.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,109 @@
+package org.jboss.seam.transaction;
+
+import java.rmi.RemoteException;
+import java.util.LinkedList;
+
+import javax.ejb.EJBException;
+import javax.ejb.Remove;
+import javax.ejb.SessionSynchronization;
+import javax.ejb.Stateful;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import javax.enterprise.context.RequestScoped;
+import javax.transaction.Synchronization;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Receives JTA transaction completion notifications from the EJB container, and
+ * passes them on to the registered Synchronizations. This implementation is
+ * fully aware of container managed transactions and is able to register
+ * Synchronizations for the container transaction.
+ *
+ * @author Gavin King
+ *
+ */
+@Stateful
+@RequestScoped
+(a)TransactionAttribute(TransactionAttributeType.SUPPORTS)
+public class EjbSynchronizations implements LocalEjbSynchronizations,
SessionSynchronization
+{
+ private static final Logger log = LoggerFactory.getLogger(EjbSynchronizations.class);
+
+ // maintain two lists to work around a bug in JBoss EJB3 where a new
+ // SessionSynchronization
+ // gets registered each time the bean is called
+ protected LinkedList<SynchronizationRegistry> synchronizations = new
LinkedList<SynchronizationRegistry>();
+ protected LinkedList<SynchronizationRegistry> committing = new
LinkedList<SynchronizationRegistry>();
+
+ public void afterBegin()
+ {
+ log.debug("afterBegin");
+ synchronizations.addLast(new SynchronizationRegistry());
+ }
+
+ public void beforeCompletion() throws EJBException, RemoteException
+ {
+ log.debug("beforeCompletion");
+ SynchronizationRegistry sync = synchronizations.removeLast();
+ sync.beforeTransactionCompletion();
+ committing.addLast(sync);
+ }
+
+ public void afterCompletion(boolean success) throws EJBException, RemoteException
+ {
+ log.debug("afterCompletion");
+ if (committing.isEmpty())
+ {
+ if (success)
+ {
+ throw new IllegalStateException("beforeCompletion was never
called");
+ }
+ else
+ {
+ synchronizations.removeLast().afterTransactionCompletion(false);
+ }
+ }
+ else
+ {
+ committing.removeFirst().afterTransactionCompletion(success);
+ }
+ }
+
+ public boolean isAwareOfContainerTransactions()
+ {
+ return true;
+ }
+
+ public void afterTransactionBegin()
+ {
+ // noop, let JTA notify us
+ }
+
+ public void afterTransactionCommit(boolean success)
+ {
+ // noop, let JTA notify us
+ }
+
+ public void afterTransactionRollback()
+ {
+ // noop, let JTA notify us
+ }
+
+ public void beforeTransactionCommit()
+ {
+ // noop, let JTA notify us
+ }
+
+ public void registerSynchronization(Synchronization sync)
+ {
+ synchronizations.getLast().registerSynchronization(sync);
+ }
+
+ @Remove
+ public void destroy()
+ {
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/LocalEjbSynchronizations.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/LocalEjbSynchronizations.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/LocalEjbSynchronizations.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,15 @@
+package org.jboss.seam.transaction;
+
+import javax.ejb.Local;
+
+/**
+ * Local interface for EjbTransaction
+ *
+ * @author Gavin King
+ *
+ */
+@Local
+public interface LocalEjbSynchronizations extends Synchronizations
+{
+ public void destroy();
+}
Added: modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Naming.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Naming.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Naming.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+package org.jboss.seam.transaction;
+
+import java.util.Hashtable;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * this has been ported to seam and hacked to make it work
+ *
+ * we need to figure out what we are doing with JNDI in seam 3 and make this go
+ * away
+ *
+ * @author stuart
+ *
+ */
+public final class Naming
+{
+ private static final Logger log = LoggerFactory.getLogger(Naming.class);
+ private static Hashtable initialContextProperties;
+
+ private static InitialContext initialContext;
+
+ public static InitialContext getInitialContext(Hashtable<String, String> props)
throws NamingException
+ {
+ if (props == null)
+ {
+ // throw new
+ // IllegalStateException("JNDI properties not initialized, Seam was not
started correctly");
+ }
+ props = new Hashtable<String, String>();
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("JNDI InitialContext properties:" + props);
+ }
+
+ try
+ {
+ return props.size() == 0 ? new InitialContext() : new InitialContext(props);
+ }
+ catch (NamingException e)
+ {
+ log.debug("Could not obtain initial context");
+ throw e;
+ }
+
+ }
+
+ public static InitialContext getInitialContext() throws NamingException
+ {
+ if (initialContext == null)
+ initInitialContext();
+
+ return initialContext;
+ }
+
+ private static synchronized void initInitialContext() throws NamingException
+ {
+ if (initialContext == null)
+ {
+ initialContext = getInitialContext(initialContextProperties);
+ }
+ }
+
+ private Naming()
+ {
+ }
+
+ public static void setInitialContextProperties(Hashtable initialContextProperties)
+ {
+ Naming.initialContextProperties = initialContextProperties;
+ initialContext = null;
+ }
+
+ public static Hashtable getInitialContextProperties()
+ {
+ return initialContextProperties;
+ }
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/NoTransaction.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/NoTransaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/NoTransaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,72 @@
+package org.jboss.seam.transaction;
+
+import javax.persistence.EntityManager;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+
+import org.jboss.weld.extensions.core.Veto;
+
+/**
+ * When no kind of transaction management exists.
+ *
+ * @author Mike Youngstrom
+ * @author Gavin King
+ *
+ */
+@Veto
+public class NoTransaction extends AbstractUserTransaction
+{
+
+ public NoTransaction()
+ {
+ super(null);
+ }
+
+ public void begin() throws NotSupportedException, SystemException
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException, IllegalStateException, SystemException
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ public int getStatus() throws SystemException
+ {
+ return Status.STATUS_NO_TRANSACTION;
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException,
SystemException
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ public void setTransactionTimeout(int timeout) throws SystemException
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization sync)
+ {
+ throw new UnsupportedOperationException("no transaction");
+ }
+
+ @Override
+ public void enlist(EntityManager entityManager) throws SystemException
+ {
+ // no-op
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SeSynchronizations.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SeSynchronizations.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SeSynchronizations.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,71 @@
+package org.jboss.seam.transaction;
+
+import java.util.Stack;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Alternative;
+import javax.transaction.Synchronization;
+
+/**
+ * This implementation does not have access to the JTA TransactionManager, so it
+ * is not fully aware of container managed transaction lifecycle, and is not
+ * able to register Synchronizations with a container managed transaction.
+ *
+ * This is an alternative, and as such must be enabled in beans.xml.
+ *
+ * @author Gavin King
+ * @author Stuart Douglas
+ */
+@RequestScoped
+@Alternative
+public class SeSynchronizations implements Synchronizations
+{
+ protected Stack<SynchronizationRegistry> synchronizations = new
Stack<SynchronizationRegistry>();
+
+ public void afterTransactionBegin()
+ {
+ synchronizations.push(new SynchronizationRegistry());
+ }
+
+ public void afterTransactionCommit(boolean success)
+ {
+ if (!synchronizations.isEmpty())
+ {
+ synchronizations.pop().afterTransactionCompletion(success);
+ }
+ }
+
+ public void afterTransactionRollback()
+ {
+ if (!synchronizations.isEmpty())
+ {
+ synchronizations.pop().afterTransactionCompletion(false);
+ }
+ }
+
+ public void beforeTransactionCommit()
+ {
+ if (!synchronizations.isEmpty())
+ {
+ synchronizations.peek().beforeTransactionCompletion();
+ }
+ }
+
+ public void registerSynchronization(Synchronization sync)
+ {
+ if (synchronizations.isEmpty())
+ {
+ throw new IllegalStateException("Transaction begin not detected, try
installing transaction:ejb-transaction in components.xml");
+ }
+ else
+ {
+ synchronizations.peek().registerSynchronization(sync);
+ }
+ }
+
+ public boolean isAwareOfContainerTransactions()
+ {
+ return false;
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SynchronizationRegistry.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SynchronizationRegistry.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/SynchronizationRegistry.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,71 @@
+package org.jboss.seam.transaction;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A list of Synchronizations to be invoked before and after transaction
+ * completion. This class is used when we can't register a synchronization
+ * directly with JTA.
+ *
+ * @author Gavin King
+ *
+ */
+class SynchronizationRegistry
+{
+ private static final Logger log =
LoggerFactory.getLogger(SynchronizationRegistry.class);
+
+ private List<Synchronization> synchronizations = new
ArrayList<Synchronization>();
+
+ void registerSynchronization(Synchronization sync)
+ {
+ synchronizations.add(sync);
+ }
+
+ void afterTransactionCompletion(boolean success)
+ {
+ // if ( Events.exists() )
+ // {
+ //
Events.instance().raiseEvent("org.jboss.seam.afterTransactionCompletion",
+ // success);
+ // }
+ for (Synchronization sync : synchronizations)
+ {
+ try
+ {
+ sync.afterCompletion(success ? Status.STATUS_COMMITTED :
Status.STATUS_ROLLEDBACK);
+ }
+ catch (Exception e)
+ {
+ log.error("Exception processing transaction Synchronization after
completion", e);
+ }
+ }
+ synchronizations.clear();
+ }
+
+ void beforeTransactionCompletion()
+ {
+ // if ( Events.exists() )
+ // {
+ //
Events.instance().raiseEvent("org.jboss.seam.beforeTransactionCompletion");
+ // }
+ for (Synchronization sync : synchronizations)
+ {
+ try
+ {
+ sync.beforeCompletion();
+ }
+ catch (Exception e)
+ {
+ log.error("Exception processing transaction Synchronization before
completion", e);
+ }
+ }
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Synchronizations.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Synchronizations.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Synchronizations.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,24 @@
+package org.jboss.seam.transaction;
+
+import javax.transaction.Synchronization;
+
+/**
+ * Interface for registering transaction synchronizations
+ *
+ * @author Gavin King
+ *
+ */
+public interface Synchronizations
+{
+ public void afterTransactionBegin();
+
+ public void afterTransactionCommit(boolean success);
+
+ public void afterTransactionRollback();
+
+ public void beforeTransactionCommit();
+
+ public void registerSynchronization(Synchronization sync);
+
+ public boolean isAwareOfContainerTransactions();
+}
\ No newline at end of file
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transaction.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,85 @@
+package org.jboss.seam.transaction;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+
+/**
+ * Supports injection of a Seam UserTransaction object that wraps the current
+ * JTA transaction or EJB container managed transaction.
+ *
+ * @author Mike Youngstrom
+ * @author Gavin King
+ *
+ */
+@ApplicationScoped
+public class Transaction
+{
+
+ @Inject
+ Synchronizations synchronizations;
+
+ @Produces
+ public UserTransaction getTransaction() throws NamingException
+ {
+ try
+ {
+ return createUTTransaction();
+ }
+ catch (NameNotFoundException nnfe)
+ {
+ try
+ {
+ return createCMTTransaction();
+ }
+ catch (NameNotFoundException nnfe2)
+ {
+ return createNoTransaction();
+ }
+ }
+ }
+
+ protected UserTransaction createNoTransaction()
+ {
+ return new NoTransaction();
+ }
+
+ protected UserTransaction createCMTTransaction() throws NamingException
+ {
+ return new CMTTransaction(EJB.getEJBContext(), synchronizations);
+ }
+
+ protected UserTransaction createUTTransaction() throws NamingException
+ {
+ return new UTTransaction(getUserTransaction(), synchronizations);
+ }
+
+ protected javax.transaction.UserTransaction getUserTransaction() throws
NamingException
+ {
+ InitialContext context = Naming.getInitialContext();
+ try
+ {
+ return (javax.transaction.UserTransaction)
context.lookup("java:comp/UserTransaction");
+ }
+ catch (NameNotFoundException nnfe)
+ {
+ try
+ {
+ // Embedded JBoss has no java:comp/UserTransaction
+ javax.transaction.UserTransaction ut = (javax.transaction.UserTransaction)
context.lookup("UserTransaction");
+ ut.getStatus(); // for glassfish, which can return an unusable UT
+ return ut;
+ }
+ catch (Exception e)
+ {
+ throw nnfe;
+ }
+ }
+ }
+
+}
+
+
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionExtension.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionExtension.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionExtension.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,12 @@
+package org.jboss.seam.transaction;
+
+/**
+ * Extension than provides a {@link UserTransaction}
+ *
+ * @author stuart
+ *
+ */
+public class TransactionExtension
+{
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionInterceptor.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionInterceptor.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionInterceptor.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,118 @@
+package org.jboss.seam.transaction;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+
+/**
+ * Implements transaction propagation rules for Seam JavaBean components.
+ *
+ * @author Gavin King
+ * @author Shane Bryzak
+ */
+@Transactional
+public class TransactionInterceptor
+{
+ private static final long serialVersionUID = -4364203056333738988L;
+
+ transient private Map<AnnotatedElement, TransactionMetadata> transactionMetadata
= new HashMap<AnnotatedElement, TransactionMetadata>();
+
+ @Inject
+ UserTransaction transaction;
+
+ private class TransactionMetadata
+ {
+ private boolean annotationPresent;
+ TransactionPropagation propType;
+
+ public TransactionMetadata(AnnotatedElement element)
+ {
+ annotationPresent = element.isAnnotationPresent(Transactional.class);
+
+ if (annotationPresent)
+ {
+ propType = element.getAnnotation(Transactional.class).value();
+ }
+ }
+
+ public boolean isAnnotationPresent()
+ {
+ return annotationPresent;
+ }
+
+ public boolean isNewTransactionRequired(boolean transactionActive)
+ {
+ return propType != null &&
propType.isNewTransactionRequired(transactionActive);
+ }
+ }
+
+ private TransactionMetadata lookupTransactionMetadata(AnnotatedElement element)
+ {
+ if (transactionMetadata == null)
+ {
+ transactionMetadata = new HashMap<AnnotatedElement,
TransactionMetadata>();
+ }
+
+ TransactionMetadata metadata = transactionMetadata.get(element);
+
+ if (metadata == null)
+ {
+ metadata = loadMetadata(element);
+ }
+
+ return metadata;
+ }
+
+ private synchronized TransactionMetadata loadMetadata(AnnotatedElement element)
+ {
+ if (!transactionMetadata.containsKey(element))
+ {
+ TransactionMetadata metadata = new TransactionMetadata(element);
+ transactionMetadata.put(element, metadata);
+ return metadata;
+ }
+
+ return transactionMetadata.get(element);
+ }
+
+ @AroundInvoke
+ public Object aroundInvoke(final InvocationContext invocation) throws Exception
+ {
+ return new Work()
+ {
+
+ @Override
+ protected Object work() throws Exception
+ {
+ return invocation.proceed();
+ }
+
+ @Override
+ protected boolean isNewTransactionRequired(boolean transactionActive)
+ {
+ return isNewTransactionRequired(invocation.getMethod(),
invocation.getTarget().getClass(), transactionActive);
+ }
+
+ private boolean isNewTransactionRequired(Method method, Class<?>
beanClass, boolean transactionActive)
+ {
+ TransactionMetadata metadata = lookupTransactionMetadata(method);
+ if (metadata.isAnnotationPresent())
+ {
+ return metadata.isNewTransactionRequired(transactionActive);
+ }
+ else
+ {
+ metadata = lookupTransactionMetadata(beanClass);
+ return metadata.isNewTransactionRequired(transactionActive);
+ }
+ }
+
+ }.workInTransaction(transaction);
+ }
+
+}
Modified:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionPropagation.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionPropagation.java 2010-07-15
12:28:14 UTC (rev 13404)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/TransactionPropagation.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -3,6 +3,38 @@
/**
* @author Dan Allen
*/
-public enum TransactionPropagation {
+public enum TransactionPropagation
+{
REQUIRED, SUPPORTS, MANDATORY, NEVER;
+
+ public boolean isNewTransactionRequired(boolean transactionActive)
+ {
+ switch (this)
+ {
+ case REQUIRED:
+ return !transactionActive;
+ case SUPPORTS:
+ return false;
+ case MANDATORY:
+ if (!transactionActive)
+ {
+ throw new IllegalStateException("No transaction active on call to
MANDATORY method");
+ }
+ else
+ {
+ return false;
+ }
+ case NEVER:
+ if (transactionActive)
+ {
+ throw new IllegalStateException("Transaction active on call to NEVER
method");
+ }
+ else
+ {
+ return false;
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
}
\ No newline at end of file
Modified:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transactional.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transactional.java 2010-07-15
12:28:14 UTC (rev 13404)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Transactional.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -14,12 +14,14 @@
@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
-(a)Target({ElementType.METHOD, ElementType.TYPE})
-public @interface Transactional {
+@Target( { ElementType.METHOD, ElementType.TYPE })
+public @interface Transactional
+{
/**
* The transaction propagation type.
- *
+ *
* @return REQUIRED by default
*/
- @Nonbinding TransactionPropagation value() default TransactionPropagation.REQUIRED;
+ @Nonbinding
+ TransactionPropagation value() default TransactionPropagation.REQUIRED;
}
\ No newline at end of file
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UTTransaction.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UTTransaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UTTransaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,96 @@
+package org.jboss.seam.transaction;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+
+import org.jboss.weld.extensions.core.Veto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Wraps JTA transaction management in a Seam UserTransaction interface.
+ *
+ * @author Mike Youngstrom
+ * @author Gavin King
+ *
+ */
+@Veto
+public class UTTransaction extends AbstractUserTransaction
+{
+ private static final Logger log = LoggerFactory.getLogger(UTTransaction.class);
+
+ private final javax.transaction.UserTransaction delegate;
+
+ UTTransaction(javax.transaction.UserTransaction delegate, Synchronizations sync)
+ {
+ super(sync);
+ this.delegate = delegate;
+ if (delegate == null)
+ {
+ throw new IllegalArgumentException("null UserTransaction");
+ }
+ }
+
+ public void begin() throws NotSupportedException, SystemException
+ {
+ log.debug("beginning JTA transaction");
+ delegate.begin();
+ getSynchronizations().afterTransactionBegin();
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException, IllegalStateException, SystemException
+ {
+ log.debug("committing JTA transaction");
+ boolean success = false;
+ Synchronizations synchronizations = getSynchronizations();
+ synchronizations.beforeTransactionCommit();
+ try
+ {
+ delegate.commit();
+ success = true;
+ }
+ finally
+ {
+ synchronizations.afterTransactionCommit(success);
+ }
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException,
SystemException
+ {
+ log.debug("rolling back JTA transaction");
+ try
+ {
+ delegate.rollback();
+ }
+ finally
+ {
+ getSynchronizations().afterTransactionRollback();
+ }
+ }
+
+ public int getStatus() throws SystemException
+ {
+ return delegate.getStatus();
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException
+ {
+ delegate.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int timeout) throws SystemException
+ {
+ delegate.setTransactionTimeout(timeout);
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization sync)
+ {
+ getSynchronizations().registerSynchronization(sync);
+ }
+
+}
Added:
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UserTransaction.java
===================================================================
---
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UserTransaction.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/UserTransaction.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,36 @@
+package org.jboss.seam.transaction;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+
+/**
+ * Extends the standard UserTransaction interface with a couple of helpful
+ * methods.
+ *
+ * @author Gavin King
+ *
+ */
+public interface UserTransaction extends javax.transaction.UserTransaction
+{
+
+ public boolean isActive() throws SystemException;
+
+ public boolean isActiveOrMarkedRollback() throws SystemException;
+
+ public boolean isRolledBackOrMarkedRollback() throws SystemException;
+
+ public boolean isMarkedRollback() throws SystemException;
+
+ public boolean isNoTransaction() throws SystemException;
+
+ public boolean isRolledBack() throws SystemException;
+
+ public boolean isCommitted() throws SystemException;
+
+ public boolean isConversationContextRequired();
+
+ public abstract void registerSynchronization(Synchronization sync);
+
+ public void enlist(EntityManager entityManager) throws SystemException;
+}
Added: modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Work.java
===================================================================
--- modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Work.java
(rev 0)
+++
modules/persistence/trunk/src/main/java/org/jboss/seam/transaction/Work.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,84 @@
+package org.jboss.seam.transaction;
+
+import javax.ejb.ApplicationException;
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Performs work in a JTA transaction.
+ *
+ * @author Gavin King
+ */
+public abstract class Work<T>
+{
+ private static final Logger log = LoggerFactory.getLogger(Work.class);
+
+ protected abstract T work() throws Exception;
+
+ protected boolean isNewTransactionRequired(boolean transactionActive)
+ {
+ return !transactionActive;
+ }
+
+ public final T workInTransaction(org.jboss.seam.transaction.UserTransaction
transaction) throws Exception
+ {
+ boolean transactionActive = transaction.isActiveOrMarkedRollback() ||
transaction.isRolledBack();
+ // TODO: temp workaround, what should we really do in this case??
+ boolean newTransactionRequired = isNewTransactionRequired(transactionActive);
+ UserTransaction userTransaction = newTransactionRequired ? transaction : null;
+
+ try
+ {
+ if (newTransactionRequired)
+ {
+ log.debug("beginning transaction");
+ userTransaction.begin();
+ }
+
+ T result = work();
+ if (newTransactionRequired)
+ {
+ if (transaction.isMarkedRollback())
+ {
+ log.debug("rolling back transaction");
+ userTransaction.rollback();
+ }
+ else
+ {
+ log.debug("committing transaction");
+ userTransaction.commit();
+ }
+ }
+ return result;
+ }
+ catch (Exception e)
+ {
+ if (newTransactionRequired && userTransaction.getStatus() !=
Status.STATUS_NO_TRANSACTION && isRollbackRequired(e, true))
+ {
+ log.debug("rolling back transaction");
+ userTransaction.rollback();
+ }
+ throw e;
+ }
+
+ }
+
+ public static boolean isRollbackRequired(Exception e, boolean isJavaBean)
+ {
+ Class<? extends Exception> clazz = e.getClass();
+ return (isSystemException(e, isJavaBean, clazz)) ||
(clazz.isAnnotationPresent(ApplicationException.class) &&
clazz.getAnnotation(ApplicationException.class).rollback());
+ }
+
+ private static boolean isSystemException(Exception e, boolean isJavaBean, Class<?
extends Exception> clazz)
+ {
+ return isJavaBean && (e instanceof RuntimeException) &&
!clazz.isAnnotationPresent(ApplicationException.class);
+ // &&
+ // TODO: this is hackish, maybe just turn off RollackInterceptor for
+ // @Converter/@Validator components
+ // !JSF.VALIDATOR_EXCEPTION.isInstance(e) &&
+ // !JSF.CONVERTER_EXCEPTION.isInstance(e);
+ }
+}
Added:
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/Hotel.java
===================================================================
--- modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/Hotel.java
(rev 0)
+++
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/Hotel.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,205 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.transactions.test;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.jboss.weld.extensions.core.Veto;
+
+/**
+ * <p>
+ * <strong>Hotel</strong> is the model/entity class that represents a hotel.
+ * </p>
+ *
+ * @author Gavin King
+ * @author Dan Allen
+ */
+@Entity
+@Table(name = "hotel")
+@Veto
+public class Hotel implements Serializable
+{
+ private Long id;
+ private String name;
+ private String address;
+ private String city;
+ private String state;
+ private String zip;
+ private String country;
+ private Integer stars;
+ private BigDecimal price;
+
+ public Hotel()
+ {
+ }
+
+ public Hotel(final String name, final String address, final String city, final String
state, final String zip, final String country)
+ {
+ this.name = name;
+ this.address = address;
+ this.city = city;
+ this.state = state;
+ this.zip = zip;
+ this.country = country;
+ }
+
+ public Hotel(final int price, final int stars, final String name, final String
address, final String city, final String state, final String zip, final String country)
+ {
+ this.price = new BigDecimal(price);
+ this.stars = stars;
+ this.name = name;
+ this.address = address;
+ this.city = city;
+ this.state = state;
+ this.zip = zip;
+ this.country = country;
+ }
+
+ @Id
+ @GeneratedValue
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(final Long id)
+ {
+ this.id = id;
+ }
+
+ @Size(max = 50)
+ @NotNull
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(final String name)
+ {
+ this.name = name;
+ }
+
+ @Size(max = 100)
+ @NotNull
+ public String getAddress()
+ {
+ return address;
+ }
+
+ public void setAddress(final String address)
+ {
+ this.address = address;
+ }
+
+ @Size(max = 40)
+ @NotNull
+ public String getCity()
+ {
+ return city;
+ }
+
+ public void setCity(final String city)
+ {
+ this.city = city;
+ }
+
+ @Size(min = 3, max = 6)
+ @NotNull
+ public String getZip()
+ {
+ return zip;
+ }
+
+ public void setZip(final String zip)
+ {
+ this.zip = zip;
+ }
+
+ @Size(min = 2, max = 10)
+ public String getState()
+ {
+ return state;
+ }
+
+ public void setState(final String state)
+ {
+ this.state = state;
+ }
+
+ @Size(min = 2, max = 40)
+ @NotNull
+ public String getCountry()
+ {
+ return country;
+ }
+
+ public void setCountry(final String country)
+ {
+ this.country = country;
+ }
+
+ @Min(1)
+ @Max(5)
+ public Integer getStars()
+ {
+ return stars;
+ }
+
+ public void setStars(final Integer stars)
+ {
+ this.stars = stars;
+ }
+
+ @Column(precision = 6, scale = 2)
+ public BigDecimal getPrice()
+ {
+ return price;
+ }
+
+ public void setPrice(final BigDecimal price)
+ {
+ this.price = price;
+ }
+
+ @Transient
+ public String getLocation()
+ {
+ return city + ", " + state + ", " + country;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Hotel(" + name + "," + address + "," + city +
"," + zip + ")";
+ }
+}
Added:
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/SimpleTest.java
===================================================================
---
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/SimpleTest.java
(rev 0)
+++
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/SimpleTest.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,75 @@
+package org.jboss.seam.transactions.test;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnit;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+
+import junit.framework.Assert;
+
+import org.jboss.arquillian.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.seam.transaction.Transaction;
+import org.jboss.seam.transaction.UserTransaction;
+import org.jboss.seam.transactions.test.util.ArtifactNames;
+import org.jboss.seam.transactions.test.util.MavenArtifactResolver;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.ByteArrayAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+(a)RunWith(Arquillian.class)
+public class SimpleTest
+{
+ @Deployment
+ public static Archive<?> createTestArchive()
+ {
+
+ WebArchive war = ShrinkWrap.create("test.war",
WebArchive.class).addLibraries(MavenArtifactResolver.resolve(ArtifactNames.WELD_EXTENSIONS)).addPackage(Transaction.class.getPackage()).addPackage(SimpleTest.class.getPackage()).addWebResource("META-INF/persistence.xml",
"classes/META-INF/persistence.xml").addWebResource(new ByteArrayAsset(new
byte[0]), "beans.xml");
+
+ return war;
+ }
+
+ @Inject
+ UserTransaction transaction;
+
+ @PersistenceUnit
+ EntityManagerFactory emf;
+
+ @Test
+ public void simpleTest() throws NotSupportedException, SystemException,
SecurityException, IllegalStateException, RollbackException, HeuristicMixedException,
HeuristicRollbackException
+ {
+ transaction.begin();
+ EntityManager em = emf.createEntityManager();
+ em.joinTransaction();
+ Hotel h = new Hotel("test", "Fake St", "Wollongong",
"NSW", "2518", "Australia");
+ em.persist(h);
+ em.flush();
+ transaction.commit();
+
+ transaction.begin();
+ em = emf.createEntityManager();
+ em.joinTransaction();
+ h = new Hotel("test2", "Fake St", "Wollongong",
"NSW", "2518", "Australia");
+ em.persist(h);
+ em.flush();
+ transaction.rollback();
+
+ transaction.begin();
+ em = emf.createEntityManager();
+ em.joinTransaction();
+ List<Hotel> hotels = em.createQuery("select h from Hotel
h").getResultList();
+ Assert.assertTrue(hotels.size() == 1);
+ transaction.rollback();
+
+ }
+}
Added:
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/ArtifactNames.java
===================================================================
---
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/ArtifactNames.java
(rev 0)
+++
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/ArtifactNames.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,7 @@
+package org.jboss.seam.transactions.test.util;
+
+public class ArtifactNames
+{
+ public static final String WELD_EXTENSIONS =
"org.jboss.weld:weld-extensions:1.0.0-SNAPSHOT";
+
+}
Added:
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/MavenArtifactResolver.java
===================================================================
---
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/MavenArtifactResolver.java
(rev 0)
+++
modules/persistence/trunk/src/test/java/org/jboss/seam/transactions/test/util/MavenArtifactResolver.java 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,25 @@
+package org.jboss.seam.transactions.test.util;
+
+import java.io.File;
+
+public class MavenArtifactResolver
+{
+ private static final String LOCAL_MAVEN_REPO =
+ System.getProperty("user.home") + File.separatorChar +
+ ".m2" + File.separatorChar + "repository";
+
+ public static File resolve(String groupId, String artifactId, String version)
+ {
+ return new File(LOCAL_MAVEN_REPO + File.separatorChar +
+ groupId.replace(".", File.separator) + File.separatorChar +
+ artifactId + File.separatorChar +
+ version + File.separatorChar +
+ artifactId + "-" + version + ".jar");
+ }
+
+ public static File resolve(String qualifiedArtifactId)
+ {
+ String[] segments = qualifiedArtifactId.split(":");
+ return resolve(segments[0], segments[1], segments[2]);
+ }
+}
Added: modules/persistence/trunk/src/test/resources/META-INF/persistence.xml
===================================================================
--- modules/persistence/trunk/src/test/resources/META-INF/persistence.xml
(rev 0)
+++ modules/persistence/trunk/src/test/resources/META-INF/persistence.xml 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+ version="2.0">
+ <persistence-unit name="transactionPu">
+ <!--
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ -->
+ <provider>org.hibernate.ejb.HibernatePersistence</provider>
+ <jta-data-source>java:/DefaultDS</jta-data-source>
+ <class>org.jboss.seam.transactions.test.Hotel</class>
+ <exclude-unlisted-classes/>
+ <properties>
+ <!-- Properties for Hibernate (default provider for JBoss AS) -->
+ <property name="hibernate.hbm2ddl.auto"
value="create-drop"/>
+ <property name="hibernate.show_sql" value="true"/>
+ <!-- Only format when you need to debug, because it slows things down -->
+ <property name="hibernate.format_sql" value="false"/>
+
+ <!-- Properties for EclipseLink (default provider for GlassFish) -->
+ <property name="eclipselink.ddl-generation"
value="drop-and-create-tables"/>
+ <property name="eclipselink.logging.level"
value="FINE"/>
+ </properties>
+ </persistence-unit>
+</persistence>
Added: modules/persistence/trunk/src/test/resources/META-INF/seam-beans.xml
===================================================================
--- modules/persistence/trunk/src/test/resources/META-INF/seam-beans.xml
(rev 0)
+++ modules/persistence/trunk/src/test/resources/META-INF/seam-beans.xml 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,30 @@
+<!--
+JBoss, Home of Professional Open Source
+Copyright 2010, Red Hat, Inc., and individual contributors
+by the @authors tag. See the copyright.txt in the distribution for a
+full listing of individual contributors.
+
+This is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of
+the License, or (at your option) any later version.
+
+This software is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this software; if not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+-->
+<beans
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:s="urn:java:seam:core"
+ xmlns:i18n="urn:java:org.jboss.seam.international.locale"
+ xsi:schemaLocation="
+
http://java.sun.com/xml/ns/javaee
+
http://docs.jboss.org/cdi/beans_1_0.xsd">
+
+</beans>
Added: modules/persistence/trunk/src/test/resources/arquillian.xml
===================================================================
--- modules/persistence/trunk/src/test/resources/arquillian.xml
(rev 0)
+++ modules/persistence/trunk/src/test/resources/arquillian.xml 2010-07-15 12:52:34 UTC
(rev 13405)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<arquillian
xmlns="http://jboss.com/arquillian"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:gfembedded="urn:arq:org.jboss.arquillian.glassfish.embedded30"
+
xmlns:gfremote="urn:arq:org.jboss.arquillian.container.glassfish.remote30">
+
+ <engine>
+ <deploymentExportPath>/tmp/</deploymentExportPath>
+ </engine>
+
+ <gfremote:container>
+ <gfremote:remoteServerHttpPort>7070</gfremote:remoteServerHttpPort>
+ </gfremote:container>
+
+ <gfembedded:container>
+
<gfembedded:sunResourcesXml>src/test/resources-glassfish/sun-resources.xml</gfembedded:sunResourcesXml>
+ </gfembedded:container>
+
+</arquillian>
Added: modules/persistence/trunk/src/test/resources-glassfish/sun-resources.xml
===================================================================
--- modules/persistence/trunk/src/test/resources-glassfish/sun-resources.xml
(rev 0)
+++ modules/persistence/trunk/src/test/resources-glassfish/sun-resources.xml 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0
Resource Definitions //EN"
+ "http://www.sun.com/software/appserver/dtds/sun-resources_1_4.dtd">
+<resources>
+ <jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
+ jndi-name="jdbc/__arquillian"/>
+ <jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
+ res-type="javax.sql.DataSource"
+ datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
+ is-isolation-level-guaranteed="false">
+ <property name="databaseName"
value="target/databases/derby"/>
+ <property name="createDatabase" value="create"/>
+ </jdbc-connection-pool>
+ <!--
+ <jdbc-resource pool-name="ArquillianEmbeddedH2Pool"
+ jndi-name="jdbc/__arquillian"/>
+ <jdbc-connection-pool name="ArquillianEmbeddedH2Pool"
+ res-type="javax.sql.DataSource"
+ datasource-classname="org.h2.jdbcx.JdbcDataSource">
+ <property name="user" value="sa"/>
+ <property name="password" value=""/>
+ <property name="url"
value="jdbc:h2:file:target/databases/h2/db"/>
+ </jdbc-connection-pool>
+ -->
+</resources>
Added: modules/persistence/trunk/src/test/resources-jbossas/jndi.properties
===================================================================
--- modules/persistence/trunk/src/test/resources-jbossas/jndi.properties
(rev 0)
+++ modules/persistence/trunk/src/test/resources-jbossas/jndi.properties 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,3 @@
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
+java.naming.provider.url=jnp://localhost:1099
Added: modules/persistence/trunk/src/test/resources-jbossas/seam-transactions-test-ds.xml
===================================================================
--- modules/persistence/trunk/src/test/resources-jbossas/seam-transactions-test-ds.xml
(rev 0)
+++
modules/persistence/trunk/src/test/resources-jbossas/seam-transactions-test-ds.xml 2010-07-15
12:52:34 UTC (rev 13405)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE datasources
+ PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
+ "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>jdbc/__default</jndi-name>
+ <use-java-context>false</use-java-context>
+ <connection-url>jdbc:hsqldb:.</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>20</max-pool-size>
+ </local-tx-datasource>
+</datasources>