Commit 610b7e18556dabcbf73f78f42f6a6b201ea4a39c
1 parent
b39acb64
Exists in
master
OPEN - issue FWK-167: Restaurar exceção "TransactionException" e
dispara-la em caso de exceção durante as operações básicas (commit, rollback, etc.) https://demoiselle.atlassian.net/browse/FWK-167
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,6 +51,7 @@ public interface Transaction extends Serializable { | ||
| 51 | * Indicates whether the given transaction is still active. | 51 | * Indicates whether the given transaction is still active. |
| 52 | * | 52 | * |
| 53 | * @return a boolean | 53 | * @return a boolean |
| 54 | + * @throws TransactionException if an unexpected error occurs | ||
| 54 | */ | 55 | */ |
| 55 | boolean isActive(); | 56 | boolean isActive(); |
| 56 | 57 | ||
| @@ -58,29 +59,38 @@ public interface Transaction extends Serializable { | @@ -58,29 +59,38 @@ public interface Transaction extends Serializable { | ||
| 58 | * Indicates whether the given transaction is already marked to be rolled back. | 59 | * Indicates whether the given transaction is already marked to be rolled back. |
| 59 | * | 60 | * |
| 60 | * @return a boolean | 61 | * @return a boolean |
| 62 | + * @throws TransactionException if an unexpected error occurs | ||
| 61 | */ | 63 | */ |
| 62 | boolean isMarkedRollback(); | 64 | boolean isMarkedRollback(); |
| 63 | 65 | ||
| 64 | /** | 66 | /** |
| 65 | * Create a new transaction and associate it with the current thread. | 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 | void begin(); | 71 | void begin(); |
| 68 | 72 | ||
| 69 | /** | 73 | /** |
| 70 | * Complete the transaction associated with the current thread. When this method completes, the thread is no longer | 74 | * Complete the transaction associated with the current thread. When this method completes, the thread is no longer |
| 71 | * associated with a transaction. | 75 | * associated with a transaction. |
| 76 | + * | ||
| 77 | + * @throws TransactionException if the transaction can't be commited | ||
| 72 | */ | 78 | */ |
| 73 | void commit(); | 79 | void commit(); |
| 74 | 80 | ||
| 75 | /** | 81 | /** |
| 76 | * Roll back the transaction associated with the current thread. When this method completes, the thread is no longer | 82 | * Roll back the transaction associated with the current thread. When this method completes, the thread is no longer |
| 77 | * associated with a transaction. | 83 | * associated with a transaction. |
| 84 | + * | ||
| 85 | + * @throws TransactionException if the transaction can't be rolled back | ||
| 78 | */ | 86 | */ |
| 79 | void rollback(); | 87 | void rollback(); |
| 80 | 88 | ||
| 81 | /** | 89 | /** |
| 82 | * Modify the transaction associated with the current thread such that the only possible outcome of the transaction | 90 | * Modify the transaction associated with the current thread such that the only possible outcome of the transaction |
| 83 | * is to roll back the transaction. | 91 | * is to roll back the transaction. |
| 92 | + * | ||
| 93 | + * @throws TransactionException if an unexpected error occurs | ||
| 84 | */ | 94 | */ |
| 85 | void setRollbackOnly(); | 95 | void setRollbackOnly(); |
| 86 | } | 96 | } |
impl/core/src/main/java/br/gov/frameworkdemoiselle/transaction/TransactionException.java
0 → 100644
| @@ -0,0 +1,64 @@ | @@ -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,6 +129,7 @@ public class ConnectionProducer implements Serializable { | ||
| 129 | } else { | 129 | } else { |
| 130 | try { | 130 | try { |
| 131 | connection = producer.create(name).getConnection(); | 131 | connection = producer.create(name).getConnection(); |
| 132 | + setTransactionIsolationLevel(connection); | ||
| 132 | disableAutoCommit(connection); | 133 | disableAutoCommit(connection); |
| 133 | 134 | ||
| 134 | cache.put(name, connection); | 135 | cache.put(name, connection); |
| @@ -143,6 +144,14 @@ public class ConnectionProducer implements Serializable { | @@ -143,6 +144,14 @@ public class ConnectionProducer implements Serializable { | ||
| 143 | return connection; | 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 | private void disableAutoCommit(Connection connection) { | 155 | private void disableAutoCommit(Connection connection) { |
| 147 | try { | 156 | try { |
| 148 | connection.setAutoCommit(false); | 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,7 +94,7 @@ public class JDBCTransaction implements Transaction { | ||
| 94 | status = getProducer().getStatus(connection); | 94 | status = getProducer().getStatus(connection); |
| 95 | status.setActive(false); | 95 | status.setActive(false); |
| 96 | } catch (Exception cause) { | 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,7 +112,7 @@ public class JDBCTransaction implements Transaction { | ||
| 112 | status = getProducer().getStatus(connection); | 112 | status = getProducer().getStatus(connection); |
| 113 | status.setActive(false); | 113 | status.setActive(false); |
| 114 | } catch (Exception cause) { | 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,6 +46,8 @@ import javax.persistence.EntityTransaction; | ||
| 46 | import br.gov.frameworkdemoiselle.annotation.Priority; | 46 | import br.gov.frameworkdemoiselle.annotation.Priority; |
| 47 | import br.gov.frameworkdemoiselle.internal.producer.EntityManagerProducer; | 47 | import br.gov.frameworkdemoiselle.internal.producer.EntityManagerProducer; |
| 48 | import br.gov.frameworkdemoiselle.util.Beans; | 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 | * Represents the strategy destinated to manage JPA transactions. | 53 | * Represents the strategy destinated to manage JPA transactions. |
| @@ -59,6 +61,8 @@ public class JPATransaction implements Transaction { | @@ -59,6 +61,8 @@ public class JPATransaction implements Transaction { | ||
| 59 | private static final long serialVersionUID = 1L; | 61 | private static final long serialVersionUID = 1L; |
| 60 | 62 | ||
| 61 | private EntityManagerProducer producer; | 63 | private EntityManagerProducer producer; |
| 64 | + | ||
| 65 | + private ResourceBundle bundle; | ||
| 62 | 66 | ||
| 63 | private EntityManagerProducer getProducer() { | 67 | private EntityManagerProducer getProducer() { |
| 64 | if (producer == null) { | 68 | if (producer == null) { |
| @@ -67,6 +71,14 @@ public class JPATransaction implements Transaction { | @@ -67,6 +71,14 @@ public class JPATransaction implements Transaction { | ||
| 67 | 71 | ||
| 68 | return producer; | 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 | public Collection<EntityManager> getDelegate() { | 83 | public Collection<EntityManager> getDelegate() { |
| 72 | return getProducer().getCache().values(); | 84 | return getProducer().getCache().values(); |
| @@ -75,23 +87,58 @@ public class JPATransaction implements Transaction { | @@ -75,23 +87,58 @@ public class JPATransaction implements Transaction { | ||
| 75 | @Override | 87 | @Override |
| 76 | public void begin() { | 88 | public void begin() { |
| 77 | EntityTransaction transaction; | 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 | @Override | 111 | @Override |
| 88 | public void commit() { | 112 | public void commit() { |
| 89 | EntityTransaction transaction; | 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,25 +146,37 @@ public class JPATransaction implements Transaction { | ||
| 99 | @Override | 146 | @Override |
| 100 | public void rollback() { | 147 | public void rollback() { |
| 101 | EntityTransaction transaction; | 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 | @Override | 164 | @Override |
| 112 | public void setRollbackOnly() { | 165 | public void setRollbackOnly() { |
| 113 | EntityTransaction transaction; | 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 | @Override | 182 | @Override |
| @@ -125,14 +184,19 @@ public class JPATransaction implements Transaction { | @@ -125,14 +184,19 @@ public class JPATransaction implements Transaction { | ||
| 125 | boolean active = false; | 184 | boolean active = false; |
| 126 | 185 | ||
| 127 | EntityTransaction transaction; | 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 | return active; | 201 | return active; |
| 138 | } | 202 | } |
| @@ -142,14 +206,19 @@ public class JPATransaction implements Transaction { | @@ -142,14 +206,19 @@ public class JPATransaction implements Transaction { | ||
| 142 | boolean rollbackOnly = false; | 206 | boolean rollbackOnly = false; |
| 143 | 207 | ||
| 144 | EntityTransaction transaction; | 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 | return rollbackOnly; | 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,4 +47,5 @@ malformed-jpql=Consulta JPQL mal formada para pagina\u00E7\u00E3o de dados. | ||
| 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 | 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 | entity-manager-scope-not-defined=N\u00E3o foi poss\u00EDvel ler o escopo configurado para o Entity Manager, usando o escopo padr\u00E3o [{0}] | 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 | 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]) | 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 | \ No newline at end of file | 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,6 +8,8 @@ import static junit.framework.Assert.assertTrue; | ||
| 8 | import javax.inject.Inject; | 8 | import javax.inject.Inject; |
| 9 | import javax.persistence.EntityManager; | 9 | import javax.persistence.EntityManager; |
| 10 | 10 | ||
| 11 | +import junit.framework.Assert; | ||
| 12 | + | ||
| 11 | import org.jboss.arquillian.container.test.api.Deployment; | 13 | import org.jboss.arquillian.container.test.api.Deployment; |
| 12 | import org.jboss.arquillian.junit.Arquillian; | 14 | import org.jboss.arquillian.junit.Arquillian; |
| 13 | import org.jboss.shrinkwrap.api.spec.WebArchive; | 15 | import org.jboss.shrinkwrap.api.spec.WebArchive; |
| @@ -18,6 +20,7 @@ import org.junit.runner.RunWith; | @@ -18,6 +20,7 @@ import org.junit.runner.RunWith; | ||
| 18 | import test.Tests; | 20 | import test.Tests; |
| 19 | import br.gov.frameworkdemoiselle.annotation.Name; | 21 | import br.gov.frameworkdemoiselle.annotation.Name; |
| 20 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; | 22 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; |
| 23 | +import br.gov.frameworkdemoiselle.transaction.TransactionException; | ||
| 21 | 24 | ||
| 22 | @RunWith(Arquillian.class) | 25 | @RunWith(Arquillian.class) |
| 23 | public class JPATransactionTest { | 26 | public class JPATransactionTest { |
| @@ -74,6 +77,20 @@ public class JPATransactionTest { | @@ -74,6 +77,20 @@ public class JPATransactionTest { | ||
| 74 | assertEquals("desc-1", entity1.getDescription()); | 77 | assertEquals("desc-1", entity1.getDescription()); |
| 75 | assertEquals("desc-2", entity2.getDescription()); | 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 | @Test | 95 | @Test |
| 79 | public void rollbackWithSuccess() { | 96 | public void rollbackWithSuccess() { |
impl/extension/jpa/src/test/java/transaction/interceptor/TransactionalBusiness.java
| @@ -42,6 +42,15 @@ public class TransactionalBusiness { | @@ -42,6 +42,15 @@ public class TransactionalBusiness { | ||
| 42 | em1.persist(entity1); | 42 | em1.persist(entity1); |
| 43 | em2.persist(entity2); | 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 | @Transactional | 55 | @Transactional |
| 47 | public void rollbackWithSuccess() throws Exception { | 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,6 +10,8 @@ import javax.inject.Inject; | ||
| 10 | import javax.persistence.EntityManager; | 10 | import javax.persistence.EntityManager; |
| 11 | import javax.persistence.TransactionRequiredException; | 11 | import javax.persistence.TransactionRequiredException; |
| 12 | 12 | ||
| 13 | +import junit.framework.Assert; | ||
| 14 | + | ||
| 13 | import org.jboss.arquillian.container.test.api.Deployment; | 15 | import org.jboss.arquillian.container.test.api.Deployment; |
| 14 | import org.jboss.arquillian.junit.Arquillian; | 16 | import org.jboss.arquillian.junit.Arquillian; |
| 15 | import org.jboss.shrinkwrap.api.spec.WebArchive; | 17 | import org.jboss.shrinkwrap.api.spec.WebArchive; |
| @@ -21,6 +23,7 @@ import br.gov.frameworkdemoiselle.annotation.Name; | @@ -21,6 +23,7 @@ import br.gov.frameworkdemoiselle.annotation.Name; | ||
| 21 | import br.gov.frameworkdemoiselle.transaction.JPATransaction; | 23 | import br.gov.frameworkdemoiselle.transaction.JPATransaction; |
| 22 | import br.gov.frameworkdemoiselle.transaction.Transaction; | 24 | import br.gov.frameworkdemoiselle.transaction.Transaction; |
| 23 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; | 25 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; |
| 26 | +import br.gov.frameworkdemoiselle.transaction.TransactionException; | ||
| 24 | import br.gov.frameworkdemoiselle.util.Beans; | 27 | import br.gov.frameworkdemoiselle.util.Beans; |
| 25 | import br.gov.frameworkdemoiselle.util.NameQualifier; | 28 | import br.gov.frameworkdemoiselle.util.NameQualifier; |
| 26 | 29 | ||
| @@ -81,6 +84,42 @@ public class JPATransactionTest { | @@ -81,6 +84,42 @@ public class JPATransactionTest { | ||
| 81 | assertEquals("desc-1", persisted1.getDescription()); | 84 | assertEquals("desc-1", persisted1.getDescription()); |
| 82 | assertEquals("desc-2", persisted2.getDescription()); | 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 | @Test(expected = TransactionRequiredException.class) | 124 | @Test(expected = TransactionRequiredException.class) |
| 86 | public void checkNoTransactionAutomaticallyLoaded() { | 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,7 +77,7 @@ public class JTATransaction implements Transaction { | ||
| 77 | return getDelegate().getStatus() != STATUS_NO_TRANSACTION; | 77 | return getDelegate().getStatus() != STATUS_NO_TRANSACTION; |
| 78 | 78 | ||
| 79 | } catch (SystemException cause) { | 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,7 +91,7 @@ public class JTATransaction implements Transaction { | ||
| 91 | || getDelegate().getStatus() == STATUS_ROLLEDBACK; | 91 | || getDelegate().getStatus() == STATUS_ROLLEDBACK; |
| 92 | 92 | ||
| 93 | } catch (SystemException cause) { | 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,7 +104,7 @@ public class JTATransaction implements Transaction { | ||
| 104 | getDelegate().begin(); | 104 | getDelegate().begin(); |
| 105 | 105 | ||
| 106 | } catch (Exception cause) { | 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,7 +117,7 @@ public class JTATransaction implements Transaction { | ||
| 117 | getDelegate().commit(); | 117 | getDelegate().commit(); |
| 118 | 118 | ||
| 119 | } catch (Exception cause) { | 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,7 +130,7 @@ public class JTATransaction implements Transaction { | ||
| 130 | getDelegate().rollback(); | 130 | getDelegate().rollback(); |
| 131 | 131 | ||
| 132 | } catch (SystemException cause) { | 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,7 +143,7 @@ public class JTATransaction implements Transaction { | ||
| 143 | getDelegate().setRollbackOnly(); | 143 | getDelegate().setRollbackOnly(); |
| 144 | 144 | ||
| 145 | } catch (SystemException cause) { | 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,6 +8,8 @@ import javax.persistence.EntityManager; | ||
| 8 | import javax.persistence.PersistenceContext; | 8 | import javax.persistence.PersistenceContext; |
| 9 | import javax.persistence.TransactionRequiredException; | 9 | import javax.persistence.TransactionRequiredException; |
| 10 | 10 | ||
| 11 | +import junit.framework.Assert; | ||
| 12 | + | ||
| 11 | import org.jboss.arquillian.container.test.api.Deployment; | 13 | import org.jboss.arquillian.container.test.api.Deployment; |
| 12 | import org.jboss.arquillian.junit.Arquillian; | 14 | import org.jboss.arquillian.junit.Arquillian; |
| 13 | import org.jboss.shrinkwrap.api.spec.WebArchive; | 15 | import org.jboss.shrinkwrap.api.spec.WebArchive; |
| @@ -19,6 +21,7 @@ import test.Tests; | @@ -19,6 +21,7 @@ import test.Tests; | ||
| 19 | import br.gov.frameworkdemoiselle.DemoiselleException; | 21 | import br.gov.frameworkdemoiselle.DemoiselleException; |
| 20 | import br.gov.frameworkdemoiselle.transaction.JTATransaction; | 22 | import br.gov.frameworkdemoiselle.transaction.JTATransaction; |
| 21 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; | 23 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; |
| 24 | +import br.gov.frameworkdemoiselle.transaction.TransactionException; | ||
| 22 | import br.gov.frameworkdemoiselle.util.Beans; | 25 | import br.gov.frameworkdemoiselle.util.Beans; |
| 23 | 26 | ||
| 24 | @RunWith(Arquillian.class) | 27 | @RunWith(Arquillian.class) |
| @@ -79,6 +82,23 @@ public class InterceptorJTATransactionTest { | @@ -79,6 +82,23 @@ public class InterceptorJTATransactionTest { | ||
| 79 | assertFalse(transactionContext.getCurrentTransaction().isActive()); | 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 | @Test(expected = TransactionRequiredException.class) | 103 | @Test(expected = TransactionRequiredException.class) |
| 84 | public void checkNoTransactionAutomaticallyLoaded() { | 104 | public void checkNoTransactionAutomaticallyLoaded() { |
impl/extension/jta/src/test/java/jtatransaction/interceptor/TransactionalBusiness.java
| @@ -35,6 +35,16 @@ public class TransactionalBusiness { | @@ -35,6 +35,16 @@ public class TransactionalBusiness { | ||
| 35 | em1.flush(); | 35 | em1.flush(); |
| 36 | em2.flush(); | 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 | public void checkNoTransactionAutomaticallyLoaded() { | 49 | public void checkNoTransactionAutomaticallyLoaded() { |
| 40 | MyEntity1 entity = new MyEntity1(); | 50 | MyEntity1 entity = new MyEntity1(); |
impl/extension/jta/src/test/java/jtatransaction/manual/ManualJTATransactionTest.java
| @@ -9,6 +9,8 @@ import javax.persistence.EntityManager; | @@ -9,6 +9,8 @@ import javax.persistence.EntityManager; | ||
| 9 | import javax.persistence.PersistenceContext; | 9 | import javax.persistence.PersistenceContext; |
| 10 | import javax.persistence.TransactionRequiredException; | 10 | import javax.persistence.TransactionRequiredException; |
| 11 | 11 | ||
| 12 | +import junit.framework.Assert; | ||
| 13 | + | ||
| 12 | import org.jboss.arquillian.container.test.api.Deployment; | 14 | import org.jboss.arquillian.container.test.api.Deployment; |
| 13 | import org.jboss.arquillian.junit.Arquillian; | 15 | import org.jboss.arquillian.junit.Arquillian; |
| 14 | import org.jboss.shrinkwrap.api.spec.WebArchive; | 16 | import org.jboss.shrinkwrap.api.spec.WebArchive; |
| @@ -20,6 +22,7 @@ import test.Tests; | @@ -20,6 +22,7 @@ import test.Tests; | ||
| 20 | import br.gov.frameworkdemoiselle.transaction.JTATransaction; | 22 | import br.gov.frameworkdemoiselle.transaction.JTATransaction; |
| 21 | import br.gov.frameworkdemoiselle.transaction.Transaction; | 23 | import br.gov.frameworkdemoiselle.transaction.Transaction; |
| 22 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; | 24 | import br.gov.frameworkdemoiselle.transaction.TransactionContext; |
| 25 | +import br.gov.frameworkdemoiselle.transaction.TransactionException; | ||
| 23 | import br.gov.frameworkdemoiselle.util.Beans; | 26 | import br.gov.frameworkdemoiselle.util.Beans; |
| 24 | 27 | ||
| 25 | @RunWith(Arquillian.class) | 28 | @RunWith(Arquillian.class) |
| @@ -97,6 +100,47 @@ public class ManualJTATransactionTest { | @@ -97,6 +100,47 @@ public class ManualJTATransactionTest { | ||
| 97 | assertEquals("desc-1", persisted1.getDescription()); | 100 | assertEquals("desc-1", persisted1.getDescription()); |
| 98 | assertEquals("desc-2", persisted2.getDescription()); | 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 | @Test(expected = TransactionRequiredException.class) | 145 | @Test(expected = TransactionRequiredException.class) |
| 102 | public void checkNoTransactionAutomaticallyLoaded() { | 146 | public void checkNoTransactionAutomaticallyLoaded() { |