Transação
Esta funcionalidade utiliza os recursos do CDI para interceptar e delegar adequadamente o tratamento das transações.
Em outras palavras, não reinventamos a roda. Criamos algumas estratégias de delegação e
controle de transação com base no que está sendo mais utilizado no mercado, algumas mais simples de configurar,
outras mais completas para utilizar.
Além de plugar e usar as estratégias prontas que fizemos para você, é possível também criar a sua. Vai que você
precise de algo que não pensamos ainda. O importante é que você tenha opções, e uma das opções também é não
utilizar a nossa solução. Caso você esteja utilizando o Demoiselle Framework em conjunto
com outro framework (tais como o JBoss Seam, Spring ou Google Guice) que ofereça o controle de transação,
você pode usá-lo também. Viva a liberdade de escolha!
Neste capítulo apresentaremos para você como usar a nossa solução de controle de transação, as estratégias
prontas que oferecemos e a criação de sua própria estratégia.
Configurando
Para um correto funcionamento do Demoiselle é necessário inserir o interceptador de transação no arquivo src/main/WEB-INF/beans.xml.
br.gov.frameworkdemoiselle.transaction.TransactionalInterceptor
]]>Métodos transacionais
Vamos começar pelo mais importante: como declarar os métodos como transacionais? Como informar ao
Demoiselle Framework que o método deve participar da sessão transacional?
A resposta é muito simples: anote seu método com @Transactional.
Se você desejar que todos os métodos de sua classe sejam transacionais, anote diretamente a classe:
Neste exemplo, os métodos inserir(), alterar() e
excluir() da classe Simples participarão do contexto transacional.
E se acontecer uma Exception?
Caso ocorra uma exceção na execução de um método transacional, o mecanismo fará rollback na transação
automaticamente. É possível mudar este comportamento utilizando exceções de aplicação (para maiores detalhes ver Exceção).
O objeto Transaction
Para ter acesso à instância da transação corrente, basta injetar TransactionContext em sua classe e obter a transação corrente.
A estratégia mais adequada
Para o controle transacional funcionar corretamente é preciso escolher a estratégia mais adequada para o seu
caso. Não existe a bala de prata, você tem que avaliar a melhor estratégia para o seu projeto.
Você também pode optar por não utilizar controle de transação. Neste caso, basta não utilizar a anotação @Transactional. Contudo,
caso você a utilize, você poderá escolher entre as estratégias JPA, JDBC, JTA (ambas fornecidas pelo Framework) e uma estratégia que você
pode criar ou importar para seu projeto.
A forma de selecionar cada uma dessas estratégias é descrita abaixo. Caso tente utilizar o controle de transação e não selecione nenhuma estratégia,
o framework lançará uma exceção lhe avisando sobre isto!
Estratégia JDBC
Esta estratégia, que está disponível na extensão demoiselle-jdbc, delega o
controle das transações para o java.sql.Connection da
especificação JDBC. Você deve escolher esta estratégia quando estiver persistindo dados
com JDBC e utilizando apenas uma base de dados em sua aplicação. Como um Connection
acessa apenas uma base de dados, não há como fazer o controle transacional de base de dados distintas.
A transação JDBC é simples de configurar e não exige nenhum recurso externo à sua aplicação.
Para utilizá-la basta que seu projeto adicione no arquivo pom.xml dependência à extensão demoiselle-jdbc, que o
Demoiselle fará a seleção por essa estratégia de forma automática.
Para utilizar a estratégia de transação JDBC, inclua a dependência para extensão JDBC
no arquivo pom.xml.br.gov.frameworkdemoiselledemoiselle-jdbccompile
]]>Estratégia JPA
Esta estratégia, que está disponível na extensão demoiselle-jpa, delega o
controle das transações para o javax.persistence.EntityManager da
especificação JPA. Você deve escolher esta estratégia quando estiver persisteindo dados
com JPA e utilizando apenas uma base de dados em sua aplicação. Como um EntityManager
acessa apenas uma unidade de persistência, não há como fazer o controle transacional de unidades distintas.
A transação JPA é simples de configurar e não exige nenhum recurso externo à sua aplicação.
Para utilizá-la basta que seu projeto adicione no arquivo pom.xml dependência à extensão demoiselle-jpa, que o
Demoiselle fará a seleção por essa estratégia de forma automática.
Caso não esteja utilizando o arquétipo JSF-JPA fornecidos pelo Demoiselle, confira se a dependência para a
extensão está indicada corretamente no arquivo pom.xml.br.gov.frameworkdemoiselledemoiselle-jpacompile
]]>Estratégia JTA
Esta estratégia, também disponível através de uma extensão (demoiselle-jta), é
responsável por delegar o controle de transação para um container JEE. Com a JTATransaction
é possível incluir várias unidades de persistência de uma mesma aplicação no mesmo contexto transacional.
Isso mesmo, o famoso Two-Phase Commit (2PC).
A estratégia JTA não serve apenas para persistência em banco de dados, serve também para integrar com
tecnologias que façam acesso ao contexto JTA, como é o caso do EJB. Para ativar esta estratégia basta
que seu projeto adicione no arquivo pom.xml a dependência à extensão demoiselle-jta, que o
Demoiselle fará a seleção por essa estratégia de forma automática, pois essa estratégia tem prioridade em relação
à estratégia JPA e JDBC.
Feito isto, o controle transacional será delegado para a transação acessível via JNDI com o nome
UserTransaction. A estratégia acessa o objeto da seguinte maneira:
Beans.getReference(UserTransaction.class). Portanto, para você utilizar esta estratégia,
você precisa de um container JEE ou de um servidor JTA qualquer.
Caso você esteja persistindo os dados com JPA, é preciso também informar no arquivo persistence.xml
o endereço da conexão JTA gerenciada. Veja um exemplo utilizando o servidor de aplicações JBoss AS7 e com o
provider Hibernate (embutido no JBoss AS) como implementação JPA:
java:jboss/datasources/ExampleDS]]>Caso não esteja utilizando o arquétipo JSF-JPA fornecidos pelo Demoiselle, confira se a dependência para a
extensão está indicada corretamente, no arquivo pom.xml.br.gov.frameworkdemoiselledemoiselle-jtacompile
]]>
Caso você esteja persistindo os dados com JDBC, é preciso informar no arquivo demoiselle.properties
o endereço da conexão JTA gerenciada. Veja um exemplo utilizando o servidor de aplicações JBoss AS7:
Criando sua própria estratégia
Caso nenhuma das estratégias oferecidas sirva para você, crie a sua. Basta escrever uma
classe não-final que implemente a interface Transaction do pacote
br.gov.frameworkdemoiselle.transaction. É preciso que sua classe não possua construtores explícitos ou
que possua um construtor público sem parâmetros. É possível fazer injeções nesta classe.
Pronto, é só isso! Agora, os métodos anotados com @Transactional irão utilizar a estratégia criada em seu projeto de forma automática,
mesmo que as extensões demoiselle-jdbc, demoiselle-jpa e demoiselle-jta sejam adicionadas ao
projeto, pois o framework dará prioridade máxima à estratégia criada no projeto.
Escolhendo a estratégia manualmente
Existem alguns casos nos quais você vai ter que definir a estratégia manualmente. Um exemplo é quando seu projeto implementa mais do que uma estratégia
de transação. Outra situação pode acontecer em casos de teste, nos quais você queira utilizar estratégia diferente. Nesses casos você deve definir no
arquivo demoiselle.properties qual estratégia será utilizada. Veja alguns exemplos de definição de estratégias própria,
JDBCTransaction, JPATransaction e JTATransaction. É importante notar que apenas uma estratégia
pode estar ativa por vez:
frameworkdemoiselle.transaction.class=projeto.MyTransaction
frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JDBCTransaction
frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JPATransaction
frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JTATransaction