Commit 7fb2f7419903f224fe834664005827b4db4ecd28
Exists in
master
Merge branch 'master' of git@github.com:demoiselle/framework.git
Showing
13 changed files
with
333 additions
and
41 deletions
Show diff stats
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() { | ... | ... |