Gerência de Transações
Introdução
- Gerência de Transações é uma das coisas muito
bem resolvidas em J2EE
- Tão forte que pode, por sí só, justificar o uso
de EJBs
- A grande vantagem da gerência transional em J2EE é que ela
"esconde" os detalhes de baixo-nível
- O desenvolvedor pode assumir que qualquer recurso transacional será
adequadamente tratado pela plataforma
- Usando demarcações transacionais declarativas (deisponível
par EJBs)
- Usando demarcações transacionais programáticas
(JTA)
- Um Container J2EE deve prover os seguintes serviços transacionais:
- Capacidade de coordenar transações sobre recursos da camada
EIS (Enterprise Information Systems). Ex.: SGBDs, Sistemas Legado,
etc.
- Capacidade para trabalhar com gerência de transações
declarativas
- Disponibilizar a JTA (Java Transaction API) e a interface UserTransaction
para gerência transacional programática
- O Container deve manipular protocolos transacionais de baixo-nível
- X/Open XA usado pelos gerentes de recursos transacionais usados em aplicações
J2EE
- O Container é responsável por propagar contextos
transacionais entre componentes J2EE
- Mesmo em cenários distribuídos (diferentes JVMs)
- Deve usar as facetas transacionais de IIOP (Internet Inter-ORB Protocol)
- Isto torna a especificação independente de fabricante
Transações Locais e Globais (Distribuídas)
- Qualquer componente J2EE pode tratar diretamente com os recursos transacionais
usando suas APIs específicas. Por exemplo:
- SGBDs através do JDBC, ou JDO
- A isto dá-se o nome de transações Locais
- Pode ser necessário caso o recurso não seja suportado
pelo serviço de gerencia transacional do container.
- Não é uma boa abrodagem pois o gerente transacional J2EE
não tratará, de nenhuma forma, este contexto
- Todo trabalho deve ser feito pelo desenvolvedor
- ALTAMENTE DESENCORAJADO
- Para qualquer recurso suportado pelo container deve-se usar a JTA ou EJBs
- Isto dá acesso ao contexto transacional global
- Acesso a vários recursos
- Multi-protocolos
- O container passa a fazer o trabalho pesado
- O desenvolvedor apenas demarca o enquadramento transacional
- Protocolo Two-phase-commit é
usado
Níveis de isolamento
- Vários níveis de isolamento de transação disponíveis (no deployment descriptor)
- Esses níveis dizem quanto de outras transações as suas estarão vendo
durante a execução
- Existe uma relação inversamente proporcional entre altos níveis de isolamento e o
nível de concorrência
- Se você quiser mais isolamento, mais locks serão usados pelo BD, haverá menos
concorrência e os tempos de espera crescerão
- Para entender os níveis de isolamento, precisamos entender três situações que podem
ocorrer:
- Problema 1: Transação A modifica uma linha; transação B lê a mesma linha;
transação A faz rollback e a linha desaparece. Esta situação chama-se dirty read.
- Problema 2: Transação A lê uma linha; transação B modifica a linha; transação A
lê a linha novamente e vê valores diferentes. Esta situação chama-se non-repeatable read.
- Problema 3: Transação A seleciona um conjunto de linhas satisfazendo um critério de
pesquisa (cláusula WHERE); Transação B insere linhas que também satisfazem a pesquisa;
Transação A repete a pesquisa e recebe novos dados. Esta situação chama-se phantom read.
- No EJB, 4 níveis de isolamento são possíveis:
- TRANSACTION_READ_UNCOMMITTED
- Permite dirty reads, non-repeatable reads e phantom reads
- TRANSACTION_READ_COMMITTED
- Permite non-repeatable reads e phantom reads
- TRANSACTION_REPEATABLE_READ
- TRANSACTION_SERIALIZABLE
- Não permite as situações acima
Demarcação transacional em J2EE
- Uma demarcação transacional é basicamente a definição
do ponto onde ela se inicia e o ponto onde ela termina
- Comandos de demarcação
- Begin: inicia uma nova transação
- Commit: aplica todas as operações/mudanças
requisitadas e termina a transação
- Rollback: desfaz todas as operações/mudanças
requisitadas e termina a transação
- Em J2EE as trnasações podem ser demarcadas de três maneiras
- Declarativa
- O container manipula a demarcação transacional
- Programática
- Os EJBs manipulam a demarcação transacional
- Iniciada pelo cliente
- Código cliente manipula a demarcação transacional
(ex. cliente WEB)
Container-Managed Transactions
- Declarativamente são definidas as demarcações transacionais
nos descritores
- As demarcações são definidas no nível de método
- Elimina a necessidade de código transacional nos EJBs
- Responsabilidades do desenvolvedor
- Definir os atributos transacionais de cada método
- Manipular exceções adequadamente chamando EJBContext.setRollbackOnly()
- Responsabilidades do Container
- Considerar o estado transacional no início e fim de cada chamada
de método
- Manipular o contexto transacional adequadamente a partir do atributo
- Rollback a transação caso o desenvolvedor tenha
explicitado isto ou uma EJBException tenha sido lançada
Atributos Transacionais
- NotSupported
- O método EJB numca fará parte de uma transação
- Caso o método seja chamado num contexto transacional, a transação
é suspensa
- A eventual falha do método não surtirá efeito na
transação
- Deve ser usado quando um método não é essencial
(ex: logging)

- Supports
- O método EJB não influencia a demarcação
transacional
- Caso um transação exista, ele fará parte dela
- Caso não, continuará normalmente
- Caso o método falhe a transação sofre um rollback
- É o atributo com menos overhead mas pode levar a resultados
inesperados

- Required
- É a melhor escolha para um método transacional
- Caso já exista um contexto transacional o método fará
parte dele
- Caso contrário, criará um novo
- Este atributo garante que qualquer coisa feita pelo EJB será
revertida caso necessário (inclusive para quem o chamou)

- RequiresNew
- Cria um novo contexto transacional sempre que o método for chamado
- Caso já exista uma transação, ela será
suspensa
- Deve ser usado quando o cliente não deve ter seu contexto transacional
influenciado pelo método
- O uso deste atributo leva a perda de performance

- Mandatory
- O método EJB não irá executar a menos que exista
um contexto transacional
- Neste caso é lançada uma exceção TransactionRequiredException
- A falha do método levará ao rollback no EJB e
no cliente

Exemplo
<?xml version='1.0' encoding="ISO-8859-1" ?>
<ejb-JAR>
...
<container-transaction>
<!-- Demarcação transacional declarativa -->
<method>
<ejb-name>EmployeeRecord</ejb-name>
<method-name>*</method-name>
</method>
<!-- NotSupported|Supports|Required|RequiresNew|Mandatory|Never -->
<trans-attribute>Required</trans-attribute>
</container-transaction>
...
</ejb-JAR>
Bean-Managed Transactions
- A demarcação transacional é feita dentro do EJB, programaticamente
- Somente para Session beans e Message-driven beans
- É usado quando o desenvolvedor quer ter um controle mais refinado
sobre a demarcação transacional do que é possível
com o CMT
- Exemplo: definir duas transações dentro de um mesmo método
- Não é permitido usar demarcação híbrida!
- A granularidade está em nível de Bean, não de método
Rollback
- Ao executar um Rollback, o container garante a restauração
do estado de um EntityBean
- Para StatefulSessionBeans o container não tem como
associar automaticamente os valores das variáveis ao contexto transacional
- Para resolver isto a especificação provê a interface
javax.ejb.SessionSynchronization
- Com ela o desenvolvedor receberá "dicas" do andamento
da transação
- Método afterBegin() é
chamada antes de executar um método transacional
- Método beforeCompletion()
é chamado no momento do commit
- O EJB pode chamar o setRollbackOnly()
para evitar o commit
-
Método afterCompletion(boolean commited)
é chamado após o commit
- O EJB deve fazer o tratamento caso o commit tenha falhado
Usando JTA
- O JTA deve ser usado para demarcação de transações
globais BMT
- UM exemplo:
...
UserTransaction userTransaction = sessionContext.getUserTransaction();
try{
userTransaction.begin();
Connection c1 = ...; // conexão para uma fonte de dados
// executa algum trabalho
c1.close();
Connection c2 = ...; // conexão para outra fonte de dados
// executa algum trabalho
c2.close();
userTransaction.commit();
}catch (Exception e){
userTransaction.rollback();
}
...
Transações com SpringFramework
- Alternativa para tratamentos transacionais sem EJB (p/ próxima)
dacaprograma