transacao.xml 13.6 KB
<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
   "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
<chapter id="transacao">

	<title>Transação</title>

	<para>
		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.
	</para>
	<para>
		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 <emphasis>Demoiselle Framework</emphasis> 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!
	</para>
	<para>
		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.   
    </para>
    
    <section>
    	<title>Configurando</title>
    	<para>
    		Para um correto funcionamento do Demoiselle é necessário inserir o interceptador de transação no arquivo <filename>src/main/WEB-INF/beans.xml</filename>.
    	</para>
		<programlisting role="XML"><![CDATA[<beans xmlns="http://java.sun.com/xml/ns/javaee" 
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
			               http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
			               
	   <interceptors>
	   		<class>br.gov.frameworkdemoiselle.transaction.TransactionalInterceptor</class>
	   </interceptors>
</beans>]]></programlisting>
    </section>

	<section>
		<title>Métodos transacionais</title>
		<para>
			Vamos começar pelo mais importante: como declarar os métodos como transacionais? Como informar ao
			<emphasis>Demoiselle Framework</emphasis> que o método deve participar da sessão transacional?
			A resposta é muito simples: anote seu método com <literal>@Transactional</literal>.
		</para>
		<programlisting role="JAVA"><![CDATA[@Transactional
public void inserir() { }]]></programlisting>
		<para>
			Se você desejar que todos os métodos de sua classe sejam transacionais, anote diretamente a classe:
		</para>
		<programlisting role="JAVA"><![CDATA[@Transactional
public class Simples {
 	public void inserir() { }
	public void alterar() { }
	public void excluir() { }
}]]></programlisting>
		<para>
			Neste exemplo, os métodos <function>inserir()</function>, <function>alterar()</function> e
			<function>excluir()</function> da classe <literal>Simples</literal> participarão do contexto transacional.
		</para>
	</section>

	<section>
		<title>E se acontecer uma Exception?</title>
		<para>
			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 <link linkend="excecao">Exceção</link>).
		</para>
		<programlisting role="JAVA"><![CDATA[@ApplicationException(rollback = false)
public class AbacaxiException {
}]]></programlisting>
	</section>

	<section>
		<title>O objeto Transaction</title>
		<para>
			Para ter acesso à instância da transação corrente, basta injetar <literal>TransactionContext</literal> em sua classe e obter a transação corrente.
		</para>
		<programlisting role="JAVA"><![CDATA[public class Simples {
	@Inject
	private TransactionContext transactionContext;

	public void experimento() {
		Transaction transaction = transactionContext.getCurrentTransaction();
	}
}]]></programlisting>
	</section>

	<section>
		<title>A estratégia mais adequada</title>
		<para>
			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. 
		</para>
		<para>
			Você também pode optar por não utilizar controle de transação. Neste caso, basta não utilizar a anotação <literal>@Transactional</literal>. Contudo,
			caso você a utilize, você poderá escolher entre as estratégias JPA, JDBC, JTA (ambas fornecidas pelo <literal>Framework</literal>) e uma estratégia que você
			pode criar ou importar para seu projeto.
		</para>
		<para>
			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!
		</para>
	</section>

	<section>
		<title>Estratégia JDBC</title>
		<para>
			Esta estratégia, que está disponível na extensão <literal>demoiselle-jdbc</literal>, delega o
			controle das transações para o <literal>java.sql.Connection</literal> 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 <literal>Connection</literal>
			acessa apenas uma base de dados, não há como fazer o controle transacional de base de dados distintas.
		</para>
		<para>
			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 <literal>demoiselle-jdbc</literal>, que o 
			Demoiselle fará a seleção por essa estratégia de forma automática.
		</para>

	<tip><para>Para utilizar a estratégia de transação JDBC, inclua a dependência para extensão JDBC 
	no arquivo pom.xml.</para>  
	 <programlisting role="XML"><![CDATA[<dependency>
	<groupId>br.gov.frameworkdemoiselle</groupId>
	<artifactId>demoiselle-jdbc</artifactId>
	<scope>compile</scope>
</dependency>]]></programlisting></tip>
	</section>

	<section>
		<title>Estratégia JPA</title>
		<para>
			Esta estratégia, que está disponível na extensão <literal>demoiselle-jpa</literal>, delega o
			controle das transações para o <literal>javax.persistence.EntityManager</literal> 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 <literal>EntityManager</literal>
			acessa apenas uma unidade de persistência, não há como fazer o controle transacional de unidades distintas.
		</para>
		<para>
			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 <literal>demoiselle-jpa</literal>, que o 
			Demoiselle fará a seleção por essa estratégia de forma automática.
		</para>
		
	<tip><para>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.</para>  
	 <programlisting role="XML"><![CDATA[<dependency>
	<groupId>br.gov.frameworkdemoiselle</groupId>
	<artifactId>demoiselle-jpa</artifactId>
	<scope>compile</scope>
</dependency>]]></programlisting></tip>
	</section>

	<section>
		<title>Estratégia JTA</title>
		<para>
			Esta estratégia, também disponível através de uma extensão (<literal>demoiselle-jta</literal>), é
			responsável por delegar o controle de transação para um container JEE. Com a <literal>JTATransaction</literal>
			é possível incluir várias unidades de persistência de uma mesma aplicação no mesmo contexto transacional.
			Isso mesmo, o famoso <emphasis>Two-Phase Commit (2PC)</emphasis>.
		</para>
		<para>
			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 <literal>demoiselle-jta</literal>, 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. 
		</para>				
		<!-- 
			defina no
			arquivo <filename>demoiselle.properties</filename> a seguinte configuração:
		</para>
		<programlisting>frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JTATransaction</programlisting>
		-->	
		<para>
			Feito isto, o controle transacional será delegado para a transação acessível via JNDI com o nome
			<literal>UserTransaction</literal>. A estratégia acessa o objeto da seguinte maneira:
			<literal>Beans.getReference(UserTransaction.class)</literal>. Portanto, para você utilizar esta estratégia,
			você precisa de um container JEE ou de um servidor JTA qualquer.
		</para>
		<para>
			Caso você esteja persistindo os dados com JPA, é preciso também informar no arquivo <filename>persistence.xml</filename>
			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:
		</para>
<programlisting role="XML"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 
	xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
	http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

	<persistence-unit name="bookmark-ds" transaction-type="JTA">
	<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
	<properties>
		<property name="hibernate.show_sql" value="true" />
		<property name="hibernate.format_sql" value="false" />
		<property name="hibernate.hbm2ddl.auto" value="update" />
		<property name="hibernate.transaction.jta.platform"
			value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
	</properties>
	</persistence-unit>
</persistence>]]></programlisting>

	<tip><para>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.</para>  
	<programlisting role="XML"><![CDATA[<dependency>
	<groupId>br.gov.frameworkdemoiselle</groupId>
	<artifactId>demoiselle-jta</artifactId>
	<scope>compile</scope>
</dependency>]]></programlisting></tip>

		<para>
			Caso você esteja persistindo os dados com JDBC, é preciso informar no arquivo <filename>demoiselle.properties</filename>
			o endereço da conexão JTA gerenciada. Veja um exemplo utilizando o servidor de aplicações JBoss AS7:
		</para>
		
<programlisting role="XML"><![CDATA[frameworkdemoiselle.persistence.jndi.name=java:jboss/datasources/ExampleDS]]></programlisting>
	</section>
		
	<section>
		<title>Criando sua própria estratégia</title>
		<para>
			Caso nenhuma das estratégias oferecidas sirva para você, crie a sua. Basta escrever uma
			classe não-final que implemente a interface <literal>Transaction</literal> do pacote
			<literal>br.gov.frameworkdemoiselle.transaction</literal>. <!--Anote a classe com
			<literal>@SessionScoped</literal> e <literal>@Alternative</literal> para que o CDI saiba
			que se trata de uma estratégia.-->É 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.
		</para>
		<!-- import javax.enterprise.context.SessionScoped;
		import javax.enterprise.inject.Alternative;
		@Alternative
		@SessionScoped -->
		<programlisting role="JAVA"><![CDATA[package projeto;

import br.gov.frameworkdemoiselle.transaction.Transaction;

public class MyTransaction implements Transaction {
	public void begin() { }
	public void commit() { }
	public void rollback() { }
	public void setRollbackOnly() { }
	public int getStatus() { }
	public void setTransactionTimeout(int seconds) { }
	public boolean isActive() { }
	public boolean isMarkedRollback() { }
}]]></programlisting>
		<para>
			Pronto, é só isso! Agora, os métodos anotados com <literal>@Transactional</literal> irão utilizar a estratégia criada em seu projeto de forma automática,
			mesmo que as extensões <literal>demoiselle-jdbc</literal>, <literal>demoiselle-jpa</literal> e <literal>demoiselle-jta</literal> sejam adicionadas ao
			projeto, pois o framework dará prioridade máxima à estratégia criada no projeto.
		</para>
	</section> 
	
	<section>
		<title>Escolhendo a estratégia manualmente</title>
		<para>
			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 <filename>demoiselle.properties</filename> qual estratégia será utilizada. Veja alguns exemplos de definição de estratégias própria,
			<literal>JDBCTransaction</literal>, <literal>JPATransaction</literal> e <literal>JTATransaction</literal>. É importante notar que apenas uma estratégia
			pode estar ativa por vez:
		</para>
		<programlisting>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</programlisting>
	</section>
	
</chapter>