transacao.xml 9.95 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 o tratamento adequado das transações
		para quem é de direito. 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.internal.interceptor.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>
		<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 injetá-la em sua classe.
		</para>
		<programlisting role="JAVA"><![CDATA[public class Simples {

	@Inject
	private Transaction transaction;
	
}]]></programlisting>
	</section>

	<section>
		<title>Escolha a estratégia 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ê pode optar também 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 e não defina qual estratégia deseja utilizar, o framework lançará uma exceção lhe avisando sobre isto!
		</para>
	</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 de transações para o <literal>javax.persistence.EntityManager</literal> da
			especificação JPA. Você deve escolher esta estratégia quando você estiver fazendo a persistência
			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.
			Basta definir no arquivo <filename>demoiselle.properties</filename> a seguinte configuração:
		</para>
		<programlisting>
			frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JPATransaction
		</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-jpa</artifactId>
		<scope>compile</scope>
	</dependency>]]></programlisting></tip>
	</section>

	<section>
		<title>Estratégia JTA</title>
		<para>
			Esta estratégia, também está disponível através de uma extensão: <literal>demoiselle-jta</literal> e é
			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 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>
			É 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-AS6 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>

	</section>

	<section>
		<title>Crie a sua 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>
		<programlisting role="JAVA"><![CDATA[package projeto;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Alternative;
import br.gov.frameworkdemoiselle.transaction.Transaction;

@Alternative
@SessionScoped
public class MegaTransaction 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>
			Basta agora definir no arquivo <filename>demoiselle.properties</filename> a sua estratégia:
		</para>
		<programlisting>
			frameworkdemoiselle.transaction.class=projeto.MegaTransaction
		</programlisting>
	</section>
	
</chapter>