Help Spring Propagando Transacao 2 Projetos Diferentes

5 respostas
fabioebner
Pessoal, estou com o seguinte problema, tenho 2 projetos (Projeto1 e Projeto2) eles podem, tanto rodar separadamente, como o Projeto1 dentro do Projeto2, ate ai perfeito, porem qual e o problema nao sei como posso fazer para propagar a minha transacao entre eles, eu coloquei no meu projeto 1
@Transactional(readOnly = false, propagation = Propagation.MANDATORY, rollbackFor = {UnsupportedOperationException.class})
	public TbTabela1 novo(String nome, String descricao) {
		TbTabela1 tabela1 = new TbTabela1();

       tabela1.setNmTabela1(nome);
       tabela1.setDsTabela1(descricao);

		tabela1DAO.save(tabela1);
		System.out.println("passou");
        if( 1 == 1){
         //   throw new UnsupportedOperationException();
        }
		return tabela1;
	}
significa que eu preciso de uma transacao ja aberta, o coloquei no meu Projeto2
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {UnsupportedOperationException.class})
    public TbTabela2 novo(String nome, String descricao){
        TbTabela2 tabela2 = new TbTabela2();

        tabela2.setNmTabela2(nome);
        tabela2.setDsTabela2(descricao);

        tabela2DAO.save(tabela2);

        br.entity.Main.main(null);

        System.out.println("passou");
        return tabela2;
    }

porem nao esta funcionando, qdo eu rodo o meu projeto 2 ele da erro qdo chega no primeiro :

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

nao sei se tem q refernciar alguma coisa no xml do projeto 1 falando q utiliza o projeto2 ou alguma outra coisa

alguem pode me ajudar??

valeu

5 Respostas

Leozin

É que é o seguinte cara.

Todo bean que você cria como @Transactional DEVE ser criado pelo Spring.

Além disso, o maior problema está nessa linha aqui:

br.entity.Main.main(null);

O que tu pode tentar é fazer isso:

- Colocar o teu segundo projeto no mesmo classpath do primeiro * Se for no eclipse, botão direito no teu projeto > Properties > Java Build Path. Clique na aba Project e clique em Add. - Adicionar uma propriedade na classe que tem a transação required
private ClasseQueTemMandatory classeMandatory;
- No teu applicationContext.xml (ou sei lá, beans.xml ou o nome que tu achou legal), declarar a classe que terá a Transaction mandatory
<bean id="umNome" class="ClasseQueTemRequired">
    <property name="classeMandatory" ref="outruNome" />
  </bean>

  <bean id=outroNome class="ClasseQueTemMandatory" />
- Pra finalizar, ao invéz de chamar o método main, chame o método "novo" diretamente na ClasseQueTemMandatory

Vê aí se dá certo.

Abraço

leosouzabh

aproveitando o assunto vai ai uma duvida!
Sempre usei transação por aspecto criando um tx:advice no meu application-context.xml
Esta forma que o fabioebner esta trabalhando com transação é uma forma digamos que manual de controlar as transações ?

fabioebner

Leozin entendi voutentar fazer isso… porem tenho uma duvida no meu Main e aonde eu dou o Context cx = … antes de chamar a classe q tem o MANDATORY eu nao tenho q ler o meu xml?? por isso chamei a main pq como estou so testando e nela q eu chamo isso entendeu??

abracos

fabioebner

mulhekao… consegui. fiz aquilo q vc falou q ao invez de chamar a main chamar direto a classe q insere. porem tive q no meu applicationContext.xml do projeto 1 mapear as classes para o hibernate do projeto2… mas foi certinho, ele propagou, qdo eu dei rollback no projeto1 ele voltou no projeto 2 tbm…
perfeito :slight_smile:

valeu

Leozin
leosouzabh:
aproveitando o assunto vai ai uma duvida! Sempre usei transação por aspecto criando um tx:advice no meu application-context.xml Esta forma que o fabioebner esta trabalhando com transação é uma forma digamos que manual de controlar as transações ?

Não, manual seria se tu usasse um TransactionTemplate.

Essa maneira que ele faz é quase igual a tua. A diferença é que ele define quais os métodos que serão transacionais usando as anotações, você usa pointcuts do aop. Eu até me arriscaria a dizer que tanto o @Transactional e aop-based são declarativos, mas como o @Transactional tu precisa alterar a classe, então deixa de ser declarativo.

Se o sistema é pequeno, usar anotações eu acho que é mais sussa. Mas se tiver várias classes transacionais, acho que usar aop fica mais enxuto. Só um detalhe: você pode combinar as transações, por exemplo:

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" />

<aop:config>
  <!-- Todos os métodos das classes do pacote com.empresa.business -->
  <aop:pointcut id="businessMethods" expression="execution(* com.company.business.*.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="businessMethods"/>
</aop:config>

<tx:advice transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="create" />
    <!--
      Detalhe: Por padrão, os valores de transação, quando não especificados, independente se serão por AOP ou anotações, serão esses:
        propagation = required
        isolation = default
        read-only = false
        timeout = -1
     -->
  </tx:attributes>
</tx:manager>

Imagina que em uma das classes você quer que ela não seja transacional. O que você pode fazer é ativar com que as transações possam ser configuradas por Annotations

<tx:annotation-driven transaction-manager="txManager" />

Aí é só ir na tua classe e colocar um

@Transactional(propagation=Propagation.NOT_SUPPORTED)

E pronto :P

Criado 4 de agosto de 2009
Ultima resposta 4 de ago. de 2009
Respostas 5
Participantes 3