SCBCD/JPA - transactionRequiredException

5 respostas
jbjares

Olá Amigos do GUJ,
Após ti rar uma folginha voltei a estudar para a certificação de SCBCD, estou no quinto capítulo do Enterprise Java JavaBeans 3.0 quinta edicao da O’Reilly.
Estou tentando ao máximo botar em prática os exemplos do livro. Sendo que não estou conseguindo simular uma exception que segundo o livro diz ser lançada quando o método merge, da EntityManager, é invocado em um contexto persistente do tipo transaction-scoped, ou seja um contexto persistente que tem seu ciclo de vida ligado ao ciclo de vida da transação e é gerenciado pelo container, injetado no Bean através da anotação @PersistenceContext.

"The transactionRequiredException is thrown if this method is invoked on a transaction-scoped persistence context" O'Reilly Pag. 59 (pdf)

Bean:

@Stateless
public class TravelAgentBean implements TravelAgentRemote {

    @PersistenceContext EntityManager manager;

    public void updateCabin(Cabin cabin) {
    	Cabin copy = manager.merge(cabin);
    }

}

Persistence.xml:

<persistence 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_1_0.xsd"
    version="1.0">

   <persistence-unit name="titan" >
	  <jta-data-source>java:jpaDS</jta-data-source>
	  <jar-file>packaged-entity-0.0.0.jar</jar-file>
      <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true" />
      </properties>
      
   </persistence-unit>
</persistence>
Enfim, até aqui acho que tudo se aplica. Estou invocando o método merge em um  transaction-scoped persistence context (Me corrijam se estiver errado). E a exception não é lançada, achei estranho e fui na API, achei a informação da API mais completa:

"TransactionRequiredException - if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction.? API (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html)


O que entendi (mais uma vez me corrijam se estiver errado) foi que a exception é lançada se o método for invocado pela EntityManager gerenciada pelo container aquela injetada pela anotação @PersistenceContext com seu tipo configurado para  PersistenceContextType.TRANSACTION (o livro não fala sobre isso) e se não existir nem uma transação. 
Não consegui simular esse cenário. A minha dúvida é: Quando ocorrerá essa situação de não existir a transação  que ela é gerenciada pelo container. Como posso simular esse cenário?

Oque imaginei foi configurar o tipo de transação do PersistenceContext para TRANSACTION e definir meu persistence-unit como RESOURCE_LOCAL e meu datasource como non-jta-datasource conforme segue o código abaixo, mas também não consegui simular.

Bean:

@Stateless
public class TravelAgentBean implements TravelAgentRemote {



    @PersistenceContext(type=PersistenceContextType.TRANSACTION) EntityManager manager;

    public void updateCabin(Cabin cabin) {
		Cabin copy = manager.merge(cabin);
	}
}

persistence.xml

<persistence 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_1_0.xsd"
    version="1.0">

   <persistence-unit name="titan" transaction-type="RESOURCE_LOCAL" >
	  <non-jta-data-source>java:jpaDS</non-jta-data-source>
	  <jar-file>packaged-entity-0.0.0.jar</jar-file>
      <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true" />
      </properties>
      
   </persistence-unit>
</persistence>

Enfim, pessoal se tiverem uma luz ficarei grato. Abraço!

5 Respostas

zoren

o método que invoca esse merge inicia alguma transação??

eu já recebi esse erro do spring com jpa ao tentar salvar algum dado no banco sem iniciar uma transação

jbjares

No primeiro exemplo de código postado sim, o próprio container gerencia as transações. Já no segundo eu excluí o uso do JTA e estou dizendo ao cointainer que eu irei gerenciar o controle de transações programaticamente, mas ainda assim o fluxo da aplicação segue normal. A única diferença do primeiro exemplo citado para o segundo é que o primeiro obviamente persiste os dados e o segundo não. Exception que é bom nada! AuhAUuahua :slight_smile:
Abraço!

W

PersistenceContextType.TRANSACTION é o valor default do atributo type em @PersistenceContext, talvez por isso o livro não tenha falado nada ainda, e por que a outra opção(PersistenceContextType.EXTENDED) só pode ser usada com Stateful Session Beans.

É só você anotar o método que você está utilizando para testar o merge com @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
E utiliza a primeira versão do seu persistence.xml, RESOURCE_LOCAL é para usar JPA fora do container.

=)

W

Nunca vi ninguém ficar contente com uma exception, mas agora acho que aparece aí rsrs

jbjares

AUhuahuahUAHuhauHauahuAH :slight_smile:

Will_HRock,
Desculpa a demora em responder essa semana que passou foi de cronograma apertado (normal né? AuhAUhauHAHAUA). Então valeu pela força, sua resposta fechou meu entendimento. O que seria de nós sem as exceptions hein? Felizes?? Auhauha :slight_smile: Pode ser!!!

Abraço,

Criado 6 de janeiro de 2010
Ultima resposta 18 de jan. de 2010
Respostas 5
Participantes 3