Commit 7fb2f7419903f224fe834664005827b4db4ecd28

Authored by Emerson Oliveira
2 parents 52cf553d 11cbecea
Exists in master

Merge branch 'master' of git@github.com:demoiselle/framework.git

impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/Transaction.java
... ... @@ -51,6 +51,7 @@ public interface Transaction extends Serializable {
51 51 * Indicates whether the given transaction is still active.
52 52 *
53 53 * @return a boolean
  54 + * @throws TransactionException if an unexpected error occurs
54 55 */
55 56 boolean isActive();
56 57  
... ... @@ -58,29 +59,38 @@ public interface Transaction extends Serializable {
58 59 * Indicates whether the given transaction is already marked to be rolled back.
59 60 *
60 61 * @return a boolean
  62 + * @throws TransactionException if an unexpected error occurs
61 63 */
62 64 boolean isMarkedRollback();
63 65  
64 66 /**
65 67 * Create a new transaction and associate it with the current thread.
  68 + *
  69 + * @throws TransactionException if the transaction can't be started
66 70 */
67 71 void begin();
68 72  
69 73 /**
70 74 * Complete the transaction associated with the current thread. When this method completes, the thread is no longer
71 75 * associated with a transaction.
  76 + *
  77 + * @throws TransactionException if the transaction can't be commited
72 78 */
73 79 void commit();
74 80  
75 81 /**
76 82 * Roll back the transaction associated with the current thread. When this method completes, the thread is no longer
77 83 * associated with a transaction.
  84 + *
  85 + * @throws TransactionException if the transaction can't be rolled back
78 86 */
79 87 void rollback();
80 88  
81 89 /**
82 90 * Modify the transaction associated with the current thread such that the only possible outcome of the transaction
83 91 * is to roll back the transaction.
  92 + *
  93 + * @throws TransactionException if an unexpected error occurs
84 94 */
85 95 void setRollbackOnly();
86 96 }
... ...
impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/TransactionException.java 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +/*
  2 + * Demoiselle Framework
  3 + * Copyright (C) 2010 SERPRO
  4 + * ----------------------------------------------------------------------------
  5 + * This file is part of Demoiselle Framework.
  6 + *
  7 + * Demoiselle Framework is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public License version 3
  9 + * as published by the Free Software Foundation.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public License version 3
  17 + * along with this program; if not, see <http://www.gnu.org/licenses/>
  18 + * or write to the Free Software Foundation, Inc., 51 Franklin Street,
  19 + * Fifth Floor, Boston, MA 02110-1301, USA.
  20 + * ----------------------------------------------------------------------------
  21 + * Este arquivo é parte do Framework Demoiselle.
  22 + *
  23 + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou
  24 + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação
  25 + * do Software Livre (FSF).
  26 + *
  27 + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
  28 + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou
  29 + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português
  30 + * para maiores detalhes.
  31 + *
  32 + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título
  33 + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/>
  34 + * ou escreva para a Fundação do Software Livre (FSF) Inc.,
  35 + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
  36 + */
  37 +package br.gov.frameworkdemoiselle.transaction;
  38 +
  39 +import br.gov.frameworkdemoiselle.DemoiselleException;
  40 +
  41 +
  42 +/**
  43 + * Represents exceptions that occur during framework managed transactions. A transaction
  44 + * exception will be thrown when a transaction can't be started, commited or rolled back.
  45 + *
  46 + * @author serpro
  47 + *
  48 + */
  49 +public class TransactionException extends DemoiselleException {
  50 +
  51 + private static final long serialVersionUID = 1L;
  52 +
  53 + public TransactionException(String message, Throwable cause) {
  54 + super(message, cause);
  55 + }
  56 +
  57 + public TransactionException(Throwable cause) {
  58 + super(cause);
  59 + }
  60 +
  61 + public TransactionException(String message) {
  62 + super(message);
  63 + }
  64 +}
... ...
impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java
... ... @@ -129,6 +129,7 @@ public class ConnectionProducer implements Serializable {
129 129 } else {
130 130 try {
131 131 connection = producer.create(name).getConnection();
  132 + setTransactionIsolationLevel(connection);
132 133 disableAutoCommit(connection);
133 134  
134 135 cache.put(name, connection);
... ... @@ -143,6 +144,14 @@ public class ConnectionProducer implements Serializable {
143 144 return connection;
144 145 }
145 146  
  147 + private void setTransactionIsolationLevel(Connection connection) {
  148 + try {
  149 + connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
  150 + } catch (SQLException cause) {
  151 + getLogger().debug(getBundle().getString("set-autocommit-failed"));
  152 + }
  153 + }
  154 +
146 155 private void disableAutoCommit(Connection connection) {
147 156 try {
148 157 connection.setAutoCommit(false);
... ...
impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/transaction/JDBCTransaction.java
... ... @@ -94,7 +94,7 @@ public class JDBCTransaction implements Transaction {
94 94 status = getProducer().getStatus(connection);
95 95 status.setActive(false);
96 96 } catch (Exception cause) {
97   - throw new DemoiselleException(cause);
  97 + throw new TransactionException(cause);
98 98 }
99 99 }
100 100 }
... ... @@ -112,7 +112,7 @@ public class JDBCTransaction implements Transaction {
112 112 status = getProducer().getStatus(connection);
113 113 status.setActive(false);
114 114 } catch (Exception cause) {
115   - throw new DemoiselleException(cause);
  115 + throw new TransactionException(cause);
116 116 }
117 117 }
118 118 }
... ...
impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/transaction/JPATransaction.java
... ... @@ -46,6 +46,8 @@ import javax.persistence.EntityTransaction;
46 46 import br.gov.frameworkdemoiselle.annotation.Priority;
47 47 import br.gov.frameworkdemoiselle.internal.producer.EntityManagerProducer;
48 48 import br.gov.frameworkdemoiselle.util.Beans;
  49 +import br.gov.frameworkdemoiselle.util.NameQualifier;
  50 +import br.gov.frameworkdemoiselle.util.ResourceBundle;
49 51  
50 52 /**
51 53 * Represents the strategy destinated to manage JPA transactions.
... ... @@ -59,6 +61,8 @@ public class JPATransaction implements Transaction {
59 61 private static final long serialVersionUID = 1L;
60 62  
61 63 private EntityManagerProducer producer;
  64 +
  65 + private ResourceBundle bundle;
62 66  
63 67 private EntityManagerProducer getProducer() {
64 68 if (producer == null) {
... ... @@ -67,6 +71,14 @@ public class JPATransaction implements Transaction {
67 71  
68 72 return producer;
69 73 }
  74 +
  75 + private ResourceBundle getBundle() {
  76 + if (bundle==null) {
  77 + bundle = Beans.getReference(ResourceBundle.class , new NameQualifier("demoiselle-jpa-bundle"));
  78 + }
  79 +
  80 + return bundle;
  81 + }
70 82  
71 83 public Collection<EntityManager> getDelegate() {
72 84 return getProducer().getCache().values();
... ... @@ -75,23 +87,58 @@ public class JPATransaction implements Transaction {
75 87 @Override
76 88 public void begin() {
77 89 EntityTransaction transaction;
78   - for (EntityManager entityManager : getDelegate()) {
79   - transaction = entityManager.getTransaction();
80   -
81   - if (!transaction.isActive()) {
82   - transaction.begin();
  90 +
  91 + try {
  92 + for (EntityManager entityManager : getDelegate()) {
  93 + transaction = entityManager.getTransaction();
  94 +
  95 + if (!transaction.isActive()) {
  96 + transaction.begin();
  97 + }
83 98 }
84 99 }
  100 + catch(Exception e) {
  101 + /*
  102 + Precisamos marcar para rollback todos os EntityManagers que conseguimos iniciar
  103 + antes da exceção ser disparada.
  104 + */
  105 + setRollbackOnly();
  106 +
  107 + throw new TransactionException(e);
  108 + }
85 109 }
86 110  
87 111 @Override
88 112 public void commit() {
89 113 EntityTransaction transaction;
90   - for (EntityManager entityManager : getDelegate()) {
91   - transaction = entityManager.getTransaction();
92   -
93   - if (transaction.isActive()) {
94   - transaction.commit();
  114 +
  115 + int commitedEntityManagers = 0;
  116 + try {
  117 + for (EntityManager entityManager : getDelegate()) {
  118 + transaction = entityManager.getTransaction();
  119 +
  120 + if (transaction.isActive()) {
  121 + transaction.commit();
  122 + commitedEntityManagers++;
  123 + }
  124 + }
  125 + }
  126 + catch(Exception e) {
  127 + /*
  128 + Precisamos marcar para rollback todos os EntityManagers que conseguimos iniciar
  129 + antes da exceção ser disparada.
  130 + */
  131 + setRollbackOnly();
  132 +
  133 + /*
  134 + Esse erro pode ser bastante problemático, pois EntityManagers já encerrados com commit
  135 + não podem ser revertidos. Por isso anexamos uma mensagem recomendando ao usuário que considere o uso de JTA em sua aplicação.
  136 + */
  137 + if (commitedEntityManagers>0) {
  138 + throw new TransactionException(getBundle().getString("partial-rollback-problem"),e);
  139 + }
  140 + else {
  141 + throw new TransactionException(e);
95 142 }
96 143 }
97 144 }
... ... @@ -99,25 +146,37 @@ public class JPATransaction implements Transaction {
99 146 @Override
100 147 public void rollback() {
101 148 EntityTransaction transaction;
102   - for (EntityManager entityManager : getDelegate()) {
103   - transaction = entityManager.getTransaction();
104   -
105   - if (transaction.isActive()) {
106   - transaction.rollback();
  149 +
  150 + try {
  151 + for (EntityManager entityManager : getDelegate()) {
  152 + transaction = entityManager.getTransaction();
  153 +
  154 + if (transaction.isActive()) {
  155 + transaction.rollback();
  156 + }
107 157 }
108 158 }
  159 + catch(Exception e) {
  160 + throw new TransactionException(e);
  161 + }
109 162 }
110 163  
111 164 @Override
112 165 public void setRollbackOnly() {
113 166 EntityTransaction transaction;
114   - for (EntityManager entityManager : getDelegate()) {
115   - transaction = entityManager.getTransaction();
116   -
117   - if (transaction.isActive()) {
118   - transaction.setRollbackOnly();
  167 +
  168 + try {
  169 + for (EntityManager entityManager : getDelegate()) {
  170 + transaction = entityManager.getTransaction();
  171 +
  172 + if (transaction.isActive()) {
  173 + transaction.setRollbackOnly();
  174 + }
119 175 }
120 176 }
  177 + catch(Exception e) {
  178 + throw new TransactionException(e);
  179 + }
121 180 }
122 181  
123 182 @Override
... ... @@ -125,14 +184,19 @@ public class JPATransaction implements Transaction {
125 184 boolean active = false;
126 185  
127 186 EntityTransaction transaction;
128   - for (EntityManager entityManager : getDelegate()) {
129   - transaction = entityManager.getTransaction();
130   -
131   - if (transaction.isActive()) {
132   - active = true;
133   - break;
  187 + try {
  188 + for (EntityManager entityManager : getDelegate()) {
  189 + transaction = entityManager.getTransaction();
  190 +
  191 + if (transaction.isActive()) {
  192 + active = true;
  193 + break;
  194 + }
134 195 }
135 196 }
  197 + catch (Exception e) {
  198 + throw new TransactionException(e);
  199 + }
136 200  
137 201 return active;
138 202 }
... ... @@ -142,14 +206,19 @@ public class JPATransaction implements Transaction {
142 206 boolean rollbackOnly = false;
143 207  
144 208 EntityTransaction transaction;
145   - for (EntityManager entityManager : getDelegate()) {
146   - transaction = entityManager.getTransaction();
147   -
148   - if (transaction.isActive() && transaction.getRollbackOnly()) {
149   - rollbackOnly = true;
150   - break;
  209 + try {
  210 + for (EntityManager entityManager : getDelegate()) {
  211 + transaction = entityManager.getTransaction();
  212 +
  213 + if (transaction.isActive() && transaction.getRollbackOnly()) {
  214 + rollbackOnly = true;
  215 + break;
  216 + }
151 217 }
152 218 }
  219 + catch(Exception e) {
  220 + throw new TransactionException(e);
  221 + }
153 222  
154 223 return rollbackOnly;
155 224 }
... ...
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.
47 47 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
48 48 entity-manager-scope-not-defined=N\u00E3o foi poss\u00EDvel ler o escopo configurado para o Entity Manager, usando o escopo padr\u00E3o [{0}]
49 49 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])
50   -defining-entity-manager-scope=Definindo escopo [{0}] para produtor de Entity Manager
51 50 \ No newline at end of file
  51 +defining-entity-manager-scope=Definindo escopo [{0}] para produtor de Entity Manager
  52 +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
... ...
impl/extension/jpa/src/test/java/transaction/interceptor/JPATransactionTest.java
... ... @@ -8,6 +8,8 @@ import static junit.framework.Assert.assertTrue;
8 8 import javax.inject.Inject;
9 9 import javax.persistence.EntityManager;
10 10  
  11 +import junit.framework.Assert;
  12 +
11 13 import org.jboss.arquillian.container.test.api.Deployment;
12 14 import org.jboss.arquillian.junit.Arquillian;
13 15 import org.jboss.shrinkwrap.api.spec.WebArchive;
... ... @@ -18,6 +20,7 @@ import org.junit.runner.RunWith;
18 20 import test.Tests;
19 21 import br.gov.frameworkdemoiselle.annotation.Name;
20 22 import br.gov.frameworkdemoiselle.transaction.TransactionContext;
  23 +import br.gov.frameworkdemoiselle.transaction.TransactionException;
21 24  
22 25 @RunWith(Arquillian.class)
23 26 public class JPATransactionTest {
... ... @@ -74,6 +77,20 @@ public class JPATransactionTest {
74 77 assertEquals("desc-1", entity1.getDescription());
75 78 assertEquals("desc-2", entity2.getDescription());
76 79 }
  80 +
  81 + @Test
  82 + public void commitWithException() {
  83 + tb.commitWithException();
  84 +
  85 + try {
  86 + tb.commitWithException();
  87 + Assert.fail();
  88 + }
  89 + catch(TransactionException te) {
  90 + te.printStackTrace();
  91 + //success
  92 + }
  93 + }
77 94  
78 95 @Test
79 96 public void rollbackWithSuccess() {
... ...
impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java
... ... @@ -42,6 +42,15 @@ public class TransactionalBusiness {
42 42 em1.persist(entity1);
43 43 em2.persist(entity2);
44 44 }
  45 +
  46 + @Transactional
  47 + public void commitWithException() {
  48 + MyEntity1 entity1 = new MyEntity1();
  49 + entity1.setId(createId("id-1"));
  50 + entity1.setDescription("desc-1");
  51 +
  52 + em1.persist(entity1);
  53 + }
45 54  
46 55 @Transactional
47 56 public void rollbackWithSuccess() throws Exception {
... ...
impl/extension/jpa/src/test/java/transaction/manual/JPATransactionTest.java
... ... @@ -10,6 +10,8 @@ import javax.inject.Inject;
10 10 import javax.persistence.EntityManager;
11 11 import javax.persistence.TransactionRequiredException;
12 12  
  13 +import junit.framework.Assert;
  14 +
13 15 import org.jboss.arquillian.container.test.api.Deployment;
14 16 import org.jboss.arquillian.junit.Arquillian;
15 17 import org.jboss.shrinkwrap.api.spec.WebArchive;
... ... @@ -21,6 +23,7 @@ import br.gov.frameworkdemoiselle.annotation.Name;
21 23 import br.gov.frameworkdemoiselle.transaction.JPATransaction;
22 24 import br.gov.frameworkdemoiselle.transaction.Transaction;
23 25 import br.gov.frameworkdemoiselle.transaction.TransactionContext;
  26 +import br.gov.frameworkdemoiselle.transaction.TransactionException;
24 27 import br.gov.frameworkdemoiselle.util.Beans;
25 28 import br.gov.frameworkdemoiselle.util.NameQualifier;
26 29  
... ... @@ -81,6 +84,42 @@ public class JPATransactionTest {
81 84 assertEquals("desc-1", persisted1.getDescription());
82 85 assertEquals("desc-2", persisted2.getDescription());
83 86 }
  87 +
  88 + @Test
  89 + public void commitWithException() {
  90 + Transaction transaction = transactionContext.getCurrentTransaction();
  91 +
  92 + MyEntity1 entity1 = new MyEntity1();
  93 + entity1.setId(createId("id-7"));
  94 + entity1.setDescription("desc-7");
  95 +
  96 + assertFalse(transaction.isActive());
  97 + transaction.begin();
  98 + assertTrue(transaction.isActive());
  99 +
  100 + em1.persist(entity1);
  101 + transaction.commit();
  102 + em1.clear();
  103 +
  104 + entity1 = new MyEntity1();
  105 + entity1.setId(createId("id-7"));
  106 + entity1.setDescription("desc-7");
  107 +
  108 + assertFalse(transaction.isActive());
  109 + transaction.begin();
  110 + assertTrue(transaction.isActive());
  111 +
  112 + em1.persist(entity1);
  113 +
  114 + try {
  115 + transaction.commit();
  116 + Assert.fail();
  117 + }
  118 + catch(TransactionException te) {
  119 + te.printStackTrace();
  120 + //success
  121 + }
  122 + }
84 123  
85 124 @Test(expected = TransactionRequiredException.class)
86 125 public void checkNoTransactionAutomaticallyLoaded() {
... ...
impl/extension/jta/src/main/java/br/gov/frameworkdemoiselle/transaction/JTATransaction.java
... ... @@ -77,7 +77,7 @@ public class JTATransaction implements Transaction {
77 77 return getDelegate().getStatus() != STATUS_NO_TRANSACTION;
78 78  
79 79 } catch (SystemException cause) {
80   - throw new DemoiselleException(cause);
  80 + throw new TransactionException(cause);
81 81 }
82 82 }
83 83  
... ... @@ -91,7 +91,7 @@ public class JTATransaction implements Transaction {
91 91 || getDelegate().getStatus() == STATUS_ROLLEDBACK;
92 92  
93 93 } catch (SystemException cause) {
94   - throw new DemoiselleException(cause);
  94 + throw new TransactionException(cause);
95 95 }
96 96 }
97 97  
... ... @@ -104,7 +104,7 @@ public class JTATransaction implements Transaction {
104 104 getDelegate().begin();
105 105  
106 106 } catch (Exception cause) {
107   - throw new DemoiselleException(cause);
  107 + throw new TransactionException(cause);
108 108 }
109 109 }
110 110  
... ... @@ -117,7 +117,7 @@ public class JTATransaction implements Transaction {
117 117 getDelegate().commit();
118 118  
119 119 } catch (Exception cause) {
120   - throw new DemoiselleException(cause);
  120 + throw new TransactionException(cause);
121 121 }
122 122 }
123 123  
... ... @@ -130,7 +130,7 @@ public class JTATransaction implements Transaction {
130 130 getDelegate().rollback();
131 131  
132 132 } catch (SystemException cause) {
133   - throw new DemoiselleException(cause);
  133 + throw new TransactionException(cause);
134 134 }
135 135 }
136 136  
... ... @@ -143,7 +143,7 @@ public class JTATransaction implements Transaction {
143 143 getDelegate().setRollbackOnly();
144 144  
145 145 } catch (SystemException cause) {
146   - throw new DemoiselleException(cause);
  146 + throw new TransactionException(cause);
147 147 }
148 148 }
149 149 }
... ...
impl/extension/jta/src/test/java/jtatransaction/interceptor/InterceptorJTATransactionTest.java
... ... @@ -8,6 +8,8 @@ import javax.persistence.EntityManager;
8 8 import javax.persistence.PersistenceContext;
9 9 import javax.persistence.TransactionRequiredException;
10 10  
  11 +import junit.framework.Assert;
  12 +
11 13 import org.jboss.arquillian.container.test.api.Deployment;
12 14 import org.jboss.arquillian.junit.Arquillian;
13 15 import org.jboss.shrinkwrap.api.spec.WebArchive;
... ... @@ -19,6 +21,7 @@ import test.Tests;
19 21 import br.gov.frameworkdemoiselle.DemoiselleException;
20 22 import br.gov.frameworkdemoiselle.transaction.JTATransaction;
21 23 import br.gov.frameworkdemoiselle.transaction.TransactionContext;
  24 +import br.gov.frameworkdemoiselle.transaction.TransactionException;
22 25 import br.gov.frameworkdemoiselle.util.Beans;
23 26  
24 27 @RunWith(Arquillian.class)
... ... @@ -79,6 +82,23 @@ public class InterceptorJTATransactionTest {
79 82 assertFalse(transactionContext.getCurrentTransaction().isActive());
80 83  
81 84 }
  85 +
  86 + @Test
  87 + public void commitWithException() {
  88 +
  89 + TransactionalBusiness business = Beans.getReference(TransactionalBusiness.class);
  90 +
  91 + business.commitWithException();
  92 +
  93 + try {
  94 + business.commitWithException();
  95 + Assert.fail();
  96 + }
  97 + catch(TransactionException te) {
  98 + te.printStackTrace();
  99 + //sucess
  100 + }
  101 + }
82 102  
83 103 @Test(expected = TransactionRequiredException.class)
84 104 public void checkNoTransactionAutomaticallyLoaded() {
... ...
impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java
... ... @@ -35,6 +35,16 @@ public class TransactionalBusiness {
35 35 em1.flush();
36 36 em2.flush();
37 37 }
  38 +
  39 + @Transactional
  40 + public void commitWithException() {
  41 + MyEntity1 entity1 = new MyEntity1();
  42 + entity1.setId(createId("id-1"));
  43 + entity1.setDescription("desc-1");
  44 +
  45 + em1.joinTransaction();
  46 + em1.persist(entity1);
  47 + }
38 48  
39 49 public void checkNoTransactionAutomaticallyLoaded() {
40 50 MyEntity1 entity = new MyEntity1();
... ...
impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java
... ... @@ -9,6 +9,8 @@ import javax.persistence.EntityManager;
9 9 import javax.persistence.PersistenceContext;
10 10 import javax.persistence.TransactionRequiredException;
11 11  
  12 +import junit.framework.Assert;
  13 +
12 14 import org.jboss.arquillian.container.test.api.Deployment;
13 15 import org.jboss.arquillian.junit.Arquillian;
14 16 import org.jboss.shrinkwrap.api.spec.WebArchive;
... ... @@ -20,6 +22,7 @@ import test.Tests;
20 22 import br.gov.frameworkdemoiselle.transaction.JTATransaction;
21 23 import br.gov.frameworkdemoiselle.transaction.Transaction;
22 24 import br.gov.frameworkdemoiselle.transaction.TransactionContext;
  25 +import br.gov.frameworkdemoiselle.transaction.TransactionException;
23 26 import br.gov.frameworkdemoiselle.util.Beans;
24 27  
25 28 @RunWith(Arquillian.class)
... ... @@ -97,6 +100,47 @@ public class ManualJTATransactionTest {
97 100 assertEquals("desc-1", persisted1.getDescription());
98 101 assertEquals("desc-2", persisted2.getDescription());
99 102 }
  103 +
  104 + @Test
  105 + public void commitWithException() {
  106 + Transaction transaction = transactionContext.getCurrentTransaction();
  107 +
  108 + MyEntity1 entity1 = new MyEntity1();
  109 + entity1.setId(createId("id-1"));
  110 + entity1.setDescription("desc-1");
  111 +
  112 + assertFalse(transaction.isActive());
  113 +
  114 + transaction.begin();
  115 + assertTrue(transaction.isActive());
  116 +
  117 + em1.joinTransaction();
  118 +
  119 + em1.persist(entity1);
  120 +
  121 + transaction.commit();
  122 + em1.clear();
  123 +
  124 + entity1 = new MyEntity1();
  125 + entity1.setId(createId("id-1"));
  126 + entity1.setDescription("desc-1");
  127 +
  128 + assertFalse(transaction.isActive());
  129 + transaction.begin();
  130 + assertTrue(transaction.isActive());
  131 +
  132 + em1.joinTransaction();
  133 + em1.persist(entity1);
  134 +
  135 + try {
  136 + transaction.commit();
  137 + Assert.fail();
  138 + }
  139 + catch(TransactionException e) {
  140 + e.printStackTrace();
  141 + //success
  142 + }
  143 + }
100 144  
101 145 @Test(expected = TransactionRequiredException.class)
102 146 public void checkNoTransactionAutomaticallyLoaded() {
... ...