transacao.xml 12.2 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.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 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 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, você poderá escolher entre as estratégias JPA, 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 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.
			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.
<!-- 		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 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
			a estratégia JPA. 
		</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>
			É 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>
		<!-- 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 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>
			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-jpa</literal> e <literal>demoiselle-jta</literal> sejam adicionadas ao projeto, pois o framework da prioridade
			máxima à estratégia criada no projeto.
		</para>
<!-- 	<para>
			Basta agora definir no arquivo <filename>demoiselle.properties</filename> a sua estratégia:
		</para>
		<programlisting>
			frameworkdemoiselle.transaction.class=projeto.MegaTransaction
		</programlisting>-->
	</section> 
	
	<section>
		<title>Escolhendo estratégias 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>JTATransaction</literal> e <literal>JPATransaction</literal> (importante notar que apenas uma estratégia pode estar ativa por vez):
		</para>
		<programlisting>frameworkdemoiselle.transaction.class=projeto.MyTransaction</programlisting>
		<programlisting>frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JTATransaction</programlisting>
		<programlisting>frameworkdemoiselle.transaction.class=br.gov.frameworkdemoiselle.transaction.JPATransaction</programlisting>
	</section>
	
</chapter>