diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/Transaction.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/Transaction.java
index 6a5bdb9..666aa26 100644
--- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/Transaction.java
+++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/Transaction.java
@@ -51,6 +51,7 @@ public interface Transaction extends Serializable {
* Indicates whether the given transaction is still active.
*
* @return a boolean
+ * @throws TransactionException if an unexpected error occurs
*/
boolean isActive();
@@ -58,29 +59,38 @@ public interface Transaction extends Serializable {
* Indicates whether the given transaction is already marked to be rolled back.
*
* @return a boolean
+ * @throws TransactionException if an unexpected error occurs
*/
boolean isMarkedRollback();
/**
* Create a new transaction and associate it with the current thread.
+ *
+ * @throws TransactionException if the transaction can't be started
*/
void begin();
/**
* Complete the transaction associated with the current thread. When this method completes, the thread is no longer
* associated with a transaction.
+ *
+ * @throws TransactionException if the transaction can't be commited
*/
void commit();
/**
* Roll back the transaction associated with the current thread. When this method completes, the thread is no longer
* associated with a transaction.
+ *
+ * @throws TransactionException if the transaction can't be rolled back
*/
void rollback();
/**
* Modify the transaction associated with the current thread such that the only possible outcome of the transaction
* is to roll back the transaction.
+ *
+ * @throws TransactionException if an unexpected error occurs
*/
void setRollbackOnly();
}
diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/TransactionException.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/TransactionException.java
new file mode 100644
index 0000000..27c20a4
--- /dev/null
+++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/TransactionException.java
@@ -0,0 +1,64 @@
+/*
+ * Demoiselle Framework
+ * Copyright (C) 2010 SERPRO
+ * ----------------------------------------------------------------------------
+ * This file is part of Demoiselle Framework.
+ *
+ * Demoiselle Framework is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License version 3
+ * as published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License version 3
+ * along with this program; if not, see
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301, USA.
+ * ----------------------------------------------------------------------------
+ * Este arquivo é parte do Framework Demoiselle.
+ *
+ * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou
+ * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação
+ * do Software Livre (FSF).
+ *
+ * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
+ * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou
+ * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português
+ * para maiores detalhes.
+ *
+ * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título
+ * "LICENCA.txt", junto com esse programa. Se não, acesse
+ * ou escreva para a Fundação do Software Livre (FSF) Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
+ */
+package br.gov.frameworkdemoiselle.transaction;
+
+import br.gov.frameworkdemoiselle.DemoiselleException;
+
+
+/**
+ * Represents exceptions that occur during framework managed transactions. A transaction
+ * exception will be thrown when a transaction can't be started, commited or rolled back.
+ *
+ * @author serpro
+ *
+ */
+public class TransactionException extends DemoiselleException {
+
+ private static final long serialVersionUID = 1L;
+
+ public TransactionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TransactionException(Throwable cause) {
+ super(cause);
+ }
+
+ public TransactionException(String message) {
+ super(message);
+ }
+}
diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java
index 02bb3c3..c4ae6b2 100644
--- a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java
+++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java
@@ -129,6 +129,7 @@ public class ConnectionProducer implements Serializable {
} else {
try {
connection = producer.create(name).getConnection();
+ setTransactionIsolationLevel(connection);
disableAutoCommit(connection);
cache.put(name, connection);
@@ -143,6 +144,14 @@ public class ConnectionProducer implements Serializable {
return connection;
}
+ private void setTransactionIsolationLevel(Connection connection) {
+ try {
+ connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ } catch (SQLException cause) {
+ getLogger().debug(getBundle().getString("set-autocommit-failed"));
+ }
+ }
+
private void disableAutoCommit(Connection connection) {
try {
connection.setAutoCommit(false);
diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/transaction/JDBCTransaction.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/transaction/JDBCTransaction.java
index 0bcf0b1..237994a 100644
--- a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/transaction/JDBCTransaction.java
+++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/transaction/JDBCTransaction.java
@@ -94,7 +94,7 @@ public class JDBCTransaction implements Transaction {
status = getProducer().getStatus(connection);
status.setActive(false);
} catch (Exception cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
}
@@ -112,7 +112,7 @@ public class JDBCTransaction implements Transaction {
status = getProducer().getStatus(connection);
status.setActive(false);
} catch (Exception cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
}
diff --git a/impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/transaction/JPATransaction.java b/impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/transaction/JPATransaction.java
index 546f181..c954abd 100644
--- a/impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/transaction/JPATransaction.java
+++ b/impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/transaction/JPATransaction.java
@@ -46,6 +46,8 @@ import javax.persistence.EntityTransaction;
import br.gov.frameworkdemoiselle.annotation.Priority;
import br.gov.frameworkdemoiselle.internal.producer.EntityManagerProducer;
import br.gov.frameworkdemoiselle.util.Beans;
+import br.gov.frameworkdemoiselle.util.NameQualifier;
+import br.gov.frameworkdemoiselle.util.ResourceBundle;
/**
* Represents the strategy destinated to manage JPA transactions.
@@ -59,6 +61,8 @@ public class JPATransaction implements Transaction {
private static final long serialVersionUID = 1L;
private EntityManagerProducer producer;
+
+ private ResourceBundle bundle;
private EntityManagerProducer getProducer() {
if (producer == null) {
@@ -67,6 +71,14 @@ public class JPATransaction implements Transaction {
return producer;
}
+
+ private ResourceBundle getBundle() {
+ if (bundle==null) {
+ bundle = Beans.getReference(ResourceBundle.class , new NameQualifier("demoiselle-jpa-bundle"));
+ }
+
+ return bundle;
+ }
public Collection getDelegate() {
return getProducer().getCache().values();
@@ -75,23 +87,58 @@ public class JPATransaction implements Transaction {
@Override
public void begin() {
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (!transaction.isActive()) {
- transaction.begin();
+
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (!transaction.isActive()) {
+ transaction.begin();
+ }
}
}
+ catch(Exception e) {
+ /*
+ Precisamos marcar para rollback todos os EntityManagers que conseguimos iniciar
+ antes da exceção ser disparada.
+ */
+ setRollbackOnly();
+
+ throw new TransactionException(e);
+ }
}
@Override
public void commit() {
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (transaction.isActive()) {
- transaction.commit();
+
+ int commitedEntityManagers = 0;
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (transaction.isActive()) {
+ transaction.commit();
+ commitedEntityManagers++;
+ }
+ }
+ }
+ catch(Exception e) {
+ /*
+ Precisamos marcar para rollback todos os EntityManagers que conseguimos iniciar
+ antes da exceção ser disparada.
+ */
+ setRollbackOnly();
+
+ /*
+ Esse erro pode ser bastante problemático, pois EntityManagers já encerrados com commit
+ não podem ser revertidos. Por isso anexamos uma mensagem recomendando ao usuário que considere o uso de JTA em sua aplicação.
+ */
+ if (commitedEntityManagers>0) {
+ throw new TransactionException(getBundle().getString("partial-rollback-problem"),e);
+ }
+ else {
+ throw new TransactionException(e);
}
}
}
@@ -99,25 +146,37 @@ public class JPATransaction implements Transaction {
@Override
public void rollback() {
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (transaction.isActive()) {
- transaction.rollback();
+
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (transaction.isActive()) {
+ transaction.rollback();
+ }
}
}
+ catch(Exception e) {
+ throw new TransactionException(e);
+ }
}
@Override
public void setRollbackOnly() {
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (transaction.isActive()) {
- transaction.setRollbackOnly();
+
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (transaction.isActive()) {
+ transaction.setRollbackOnly();
+ }
}
}
+ catch(Exception e) {
+ throw new TransactionException(e);
+ }
}
@Override
@@ -125,14 +184,19 @@ public class JPATransaction implements Transaction {
boolean active = false;
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (transaction.isActive()) {
- active = true;
- break;
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (transaction.isActive()) {
+ active = true;
+ break;
+ }
}
}
+ catch (Exception e) {
+ throw new TransactionException(e);
+ }
return active;
}
@@ -142,14 +206,19 @@ public class JPATransaction implements Transaction {
boolean rollbackOnly = false;
EntityTransaction transaction;
- for (EntityManager entityManager : getDelegate()) {
- transaction = entityManager.getTransaction();
-
- if (transaction.isActive() && transaction.getRollbackOnly()) {
- rollbackOnly = true;
- break;
+ try {
+ for (EntityManager entityManager : getDelegate()) {
+ transaction = entityManager.getTransaction();
+
+ if (transaction.isActive() && transaction.getRollbackOnly()) {
+ rollbackOnly = true;
+ break;
+ }
}
}
+ catch(Exception e) {
+ throw new TransactionException(e);
+ }
return rollbackOnly;
}
diff --git a/impl/extension/jpa/src/main/resources/demoiselle-jpa-bundle.properties b/impl/extension/jpa/src/main/resources/demoiselle-jpa-bundle.properties
index 1d5cce2..2afd0b9 100644
--- a/impl/extension/jpa/src/main/resources/demoiselle-jpa-bundle.properties
+++ b/impl/extension/jpa/src/main/resources/demoiselle-jpa-bundle.properties
@@ -47,4 +47,5 @@ malformed-jpql=Consulta JPQL mal formada para pagina\u00E7\u00E3o de dados.
invalid-scope-for-entity-manager=O escopo especificado para o Entity Manager \u00E9 inv\u00E1lido. Por favor informe um dos escopos v\u00E1lidos para a propriedade frameworkdemoiselle.persistence.entitymanager.scope\: request, session, view, conversation, application
entity-manager-scope-not-defined=N\u00E3o foi poss\u00EDvel ler o escopo configurado para o Entity Manager, usando o escopo padr\u00E3o [{0}]
passivable-scope-without-optimistic-lock=Um Entity Manager armazenado no escopo [{0}] suporta apenas trava otimista com vers\u00E3o. Use o tipo adequado ou remova a trava. (veja [LockModeType.OPTIMISTIC_FORCE_INCREMENT])
-defining-entity-manager-scope=Definindo escopo [{0}] para produtor de Entity Manager
\ No newline at end of file
+defining-entity-manager-scope=Definindo escopo [{0}] para produtor de Entity Manager
+partial-rollback-problem=N\u00E3o foi poss\u00EDvel reverter a transa\u00E7\u00E3o para todos os EntityManager's configurados, favor considerar o uso de transa\u00E7\u00F5es JTA em uma aplica\u00E7\u00E3o com m\u00FAltiplos EntityManager's
diff --git a/impl/extension/jpa/src/test/java/transaction/interceptor/JPATransactionTest.java b/impl/extension/jpa/src/test/java/transaction/interceptor/JPATransactionTest.java
index f03e131..b86368f 100644
--- a/impl/extension/jpa/src/test/java/transaction/interceptor/JPATransactionTest.java
+++ b/impl/extension/jpa/src/test/java/transaction/interceptor/JPATransactionTest.java
@@ -8,6 +8,8 @@ import static junit.framework.Assert.assertTrue;
import javax.inject.Inject;
import javax.persistence.EntityManager;
+import junit.framework.Assert;
+
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -18,6 +20,7 @@ import org.junit.runner.RunWith;
import test.Tests;
import br.gov.frameworkdemoiselle.annotation.Name;
import br.gov.frameworkdemoiselle.transaction.TransactionContext;
+import br.gov.frameworkdemoiselle.transaction.TransactionException;
@RunWith(Arquillian.class)
public class JPATransactionTest {
@@ -74,6 +77,20 @@ public class JPATransactionTest {
assertEquals("desc-1", entity1.getDescription());
assertEquals("desc-2", entity2.getDescription());
}
+
+ @Test
+ public void commitWithException() {
+ tb.commitWithException();
+
+ try {
+ tb.commitWithException();
+ Assert.fail();
+ }
+ catch(TransactionException te) {
+ te.printStackTrace();
+ //success
+ }
+ }
@Test
public void rollbackWithSuccess() {
diff --git a/impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java b/impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java
index c99f3cd..2ea45e9 100644
--- a/impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java
+++ b/impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java
@@ -42,6 +42,15 @@ public class TransactionalBusiness {
em1.persist(entity1);
em2.persist(entity2);
}
+
+ @Transactional
+ public void commitWithException() {
+ MyEntity1 entity1 = new MyEntity1();
+ entity1.setId(createId("id-1"));
+ entity1.setDescription("desc-1");
+
+ em1.persist(entity1);
+ }
@Transactional
public void rollbackWithSuccess() throws Exception {
diff --git a/impl/extension/jpa/src/test/java/transaction/manual/JPATransactionTest.java b/impl/extension/jpa/src/test/java/transaction/manual/JPATransactionTest.java
index fd93d97..be941d8 100644
--- a/impl/extension/jpa/src/test/java/transaction/manual/JPATransactionTest.java
+++ b/impl/extension/jpa/src/test/java/transaction/manual/JPATransactionTest.java
@@ -10,6 +10,8 @@ import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.TransactionRequiredException;
+import junit.framework.Assert;
+
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -21,6 +23,7 @@ import br.gov.frameworkdemoiselle.annotation.Name;
import br.gov.frameworkdemoiselle.transaction.JPATransaction;
import br.gov.frameworkdemoiselle.transaction.Transaction;
import br.gov.frameworkdemoiselle.transaction.TransactionContext;
+import br.gov.frameworkdemoiselle.transaction.TransactionException;
import br.gov.frameworkdemoiselle.util.Beans;
import br.gov.frameworkdemoiselle.util.NameQualifier;
@@ -81,6 +84,42 @@ public class JPATransactionTest {
assertEquals("desc-1", persisted1.getDescription());
assertEquals("desc-2", persisted2.getDescription());
}
+
+ @Test
+ public void commitWithException() {
+ Transaction transaction = transactionContext.getCurrentTransaction();
+
+ MyEntity1 entity1 = new MyEntity1();
+ entity1.setId(createId("id-7"));
+ entity1.setDescription("desc-7");
+
+ assertFalse(transaction.isActive());
+ transaction.begin();
+ assertTrue(transaction.isActive());
+
+ em1.persist(entity1);
+ transaction.commit();
+ em1.clear();
+
+ entity1 = new MyEntity1();
+ entity1.setId(createId("id-7"));
+ entity1.setDescription("desc-7");
+
+ assertFalse(transaction.isActive());
+ transaction.begin();
+ assertTrue(transaction.isActive());
+
+ em1.persist(entity1);
+
+ try {
+ transaction.commit();
+ Assert.fail();
+ }
+ catch(TransactionException te) {
+ te.printStackTrace();
+ //success
+ }
+ }
@Test(expected = TransactionRequiredException.class)
public void checkNoTransactionAutomaticallyLoaded() {
diff --git a/impl/extension/jta/src/main/java/br/gov/frameworkdemoiselle/transaction/JTATransaction.java b/impl/extension/jta/src/main/java/br/gov/frameworkdemoiselle/transaction/JTATransaction.java
index c24099b..c8f2d6c 100644
--- a/impl/extension/jta/src/main/java/br/gov/frameworkdemoiselle/transaction/JTATransaction.java
+++ b/impl/extension/jta/src/main/java/br/gov/frameworkdemoiselle/transaction/JTATransaction.java
@@ -77,7 +77,7 @@ public class JTATransaction implements Transaction {
return getDelegate().getStatus() != STATUS_NO_TRANSACTION;
} catch (SystemException cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
@@ -91,7 +91,7 @@ public class JTATransaction implements Transaction {
|| getDelegate().getStatus() == STATUS_ROLLEDBACK;
} catch (SystemException cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
@@ -104,7 +104,7 @@ public class JTATransaction implements Transaction {
getDelegate().begin();
} catch (Exception cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
@@ -117,7 +117,7 @@ public class JTATransaction implements Transaction {
getDelegate().commit();
} catch (Exception cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
@@ -130,7 +130,7 @@ public class JTATransaction implements Transaction {
getDelegate().rollback();
} catch (SystemException cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
@@ -143,7 +143,7 @@ public class JTATransaction implements Transaction {
getDelegate().setRollbackOnly();
} catch (SystemException cause) {
- throw new DemoiselleException(cause);
+ throw new TransactionException(cause);
}
}
}
diff --git a/impl/extension/jta/src/test/java/jtatransaction/interceptor/InterceptorJTATransactionTest.java b/impl/extension/jta/src/test/java/jtatransaction/interceptor/InterceptorJTATransactionTest.java
index 9c66e23..52be7f8 100644
--- a/impl/extension/jta/src/test/java/jtatransaction/interceptor/InterceptorJTATransactionTest.java
+++ b/impl/extension/jta/src/test/java/jtatransaction/interceptor/InterceptorJTATransactionTest.java
@@ -8,6 +8,8 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TransactionRequiredException;
+import junit.framework.Assert;
+
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -19,6 +21,7 @@ import test.Tests;
import br.gov.frameworkdemoiselle.DemoiselleException;
import br.gov.frameworkdemoiselle.transaction.JTATransaction;
import br.gov.frameworkdemoiselle.transaction.TransactionContext;
+import br.gov.frameworkdemoiselle.transaction.TransactionException;
import br.gov.frameworkdemoiselle.util.Beans;
@RunWith(Arquillian.class)
@@ -79,6 +82,23 @@ public class InterceptorJTATransactionTest {
assertFalse(transactionContext.getCurrentTransaction().isActive());
}
+
+ @Test
+ public void commitWithException() {
+
+ TransactionalBusiness business = Beans.getReference(TransactionalBusiness.class);
+
+ business.commitWithException();
+
+ try {
+ business.commitWithException();
+ Assert.fail();
+ }
+ catch(TransactionException te) {
+ te.printStackTrace();
+ //sucess
+ }
+ }
@Test(expected = TransactionRequiredException.class)
public void checkNoTransactionAutomaticallyLoaded() {
diff --git a/impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java b/impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java
index 70640c3..764ab5b 100644
--- a/impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java
+++ b/impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java
@@ -35,6 +35,16 @@ public class TransactionalBusiness {
em1.flush();
em2.flush();
}
+
+ @Transactional
+ public void commitWithException() {
+ MyEntity1 entity1 = new MyEntity1();
+ entity1.setId(createId("id-1"));
+ entity1.setDescription("desc-1");
+
+ em1.joinTransaction();
+ em1.persist(entity1);
+ }
public void checkNoTransactionAutomaticallyLoaded() {
MyEntity1 entity = new MyEntity1();
diff --git a/impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java b/impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java
index 3024066..1caf9a7 100644
--- a/impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java
+++ b/impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java
@@ -9,6 +9,8 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TransactionRequiredException;
+import junit.framework.Assert;
+
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.spec.WebArchive;
@@ -20,6 +22,7 @@ import test.Tests;
import br.gov.frameworkdemoiselle.transaction.JTATransaction;
import br.gov.frameworkdemoiselle.transaction.Transaction;
import br.gov.frameworkdemoiselle.transaction.TransactionContext;
+import br.gov.frameworkdemoiselle.transaction.TransactionException;
import br.gov.frameworkdemoiselle.util.Beans;
@RunWith(Arquillian.class)
@@ -97,6 +100,47 @@ public class ManualJTATransactionTest {
assertEquals("desc-1", persisted1.getDescription());
assertEquals("desc-2", persisted2.getDescription());
}
+
+ @Test
+ public void commitWithException() {
+ Transaction transaction = transactionContext.getCurrentTransaction();
+
+ MyEntity1 entity1 = new MyEntity1();
+ entity1.setId(createId("id-1"));
+ entity1.setDescription("desc-1");
+
+ assertFalse(transaction.isActive());
+
+ transaction.begin();
+ assertTrue(transaction.isActive());
+
+ em1.joinTransaction();
+
+ em1.persist(entity1);
+
+ transaction.commit();
+ em1.clear();
+
+ entity1 = new MyEntity1();
+ entity1.setId(createId("id-1"));
+ entity1.setDescription("desc-1");
+
+ assertFalse(transaction.isActive());
+ transaction.begin();
+ assertTrue(transaction.isActive());
+
+ em1.joinTransaction();
+ em1.persist(entity1);
+
+ try {
+ transaction.commit();
+ Assert.fail();
+ }
+ catch(TransactionException e) {
+ e.printStackTrace();
+ //success
+ }
+ }
@Test(expected = TransactionRequiredException.class)
public void checkNoTransactionAutomaticallyLoaded() {
--
libgit2 0.21.2