Como tratar uma exceção após o commit do @Transactional?

7 respostas
bland

Olá pessoal!

De antemão, obrigado pela ajuda.

Fiz a busca dessa solução de várias formas. Encontrei diversas implementações, porém, nenhuma delas eu obtive sucesso. Por isso venho aqui buscar ajuda.

Estou utilizando Spring 3.0.3, Hibernate 3.3.2, JPA 2.0 e JSF 2.0. Tentarei sintetizar a forma como está a implementação, mas, para ficar mais claro, estou usando EntityManager para a parte da persistência.

Repositório:

public T add(T bean) {
		// Método que irá gerar a exceção
		getEntityManager().persist( bean );
		return bean;
	}

Serviço:

@Transactional( propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class )
	// Tentei apenas como @Transactional também e não funcionou
	public D save( D dto ) {

		D dtoSaved = null;
		
		E entity = getAssembler().toEntity( dto );
		
		E entitySaved = repository.add( entity );
		
		if ( entitySaved != null && entitySaved.getPk() != null ) {
			
			dtoSaved = getAssembler().toDTO( entitySaved );
		}

		return dtoSaved;
	}

Aspecto:

@Aspect
public class PersistenciaExceptionAspecto {

	@Pointcut( "execution(@org.springframework.transaction.annotation.Transactional * *(..) )" )
	public void transactionalMethod() {}
	
	@AfterThrowing( pointcut = "transactionalMethod()", throwing = "e" )
	public void afterThrowingFromTransactionalMethod( JoinPoint joinPoint, RuntimeException e ) {
		System.out.println( "Aspecto: PersistenciaExceptionAspecto - Lançada exception" );
	}

}

Tentei, também, fazendo configurações no application-context.xml, mas, como dito anteriormente, não consegui resolver o meu problema. Vamos ao problema para que fique ainda mais entendido.

Como pode ser visto acima, a implementação está realmente muito simples. Então eu tento fazer a persistência de uma entitade que tenha a unicidade em um determinado campo, forçando o lançamento de uma exceção (seja ela uma exceção checada ou não checada), mas mensagem “[color=red]Aspecto: PersistenciaExceptionAspecto - Lançada exception[/color]”, como consta no método afterThrowingFromTransactionalMethod do aspecto, não está sendo exibida no console da aplicação.

Eu não consigo mais enxergar onde posso estar errando, portanto, gostaria que vocês pudessem me ajudar a tentar sanar esse problema.

Um grande abraço a todos e obrigado.

7 Respostas

D

Você poderia postar seu arquivo de configuração do Spring por favor?

bland

Fala Daniel,

Obrigado pela tentativa de ajudar. Abaixo segue o meu arquivo de configuração do Spring.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="classpath:/connection.properties"/>
	</bean>

	<aop:aspectj-autoproxy />

	<!-- Indica ao spring que os beans estao representados por anotacoes -->
	<context:annotation-config />
	<context:component-scan base-package="com.newtest.*.repository.impl" />

	<!-- Configuracao do DataSource	-->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
		p:url="${connection.url}"
		p:driverClassName="${connection.driver}" 
		p:username="${connection.username}"
		p:password="${connection.password}" />

	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
			p:packagesToScan="com.newtest.*.domain.entity">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!--
		Gerencia as PersistenceUnits do JPA. Neste local deve ser indicado
		onde estao os arquivos que configuram as PersistenceUnits
	-->
	<bean id="persistenceUnitManager"
		class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
		<property name="defaultDataSource" ref="dataSource" />
	</bean>
	
	<!-- Gerenciador da criacao e manutencao dos EntityManager -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitManager" ref="persistenceUnitManager" />
		<property name="persistenceUnitName" value="development"/>
	</bean>
	
	<!-- Gerenciador das transacoes dos servicos -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	
	<!--
		Indica ao spring que as transacoes serao demarcadas com anotacoes e
		aponta qual eh o gerenciador das transacoes
	-->
	<tx:annotation-driven transaction-manager="transactionManager" />

Grande abraço!

D

Eu trabalho com Spring 2.5, acho que se faz necessário colocar estas configurações:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

Isto necessário para a ação que está querendo.

bland

Fala Daniel,

Obrigado mais uma vez. Mas, o erro persiste cara. Coloquei as duas linhas que você falou e mesmo assim o problema persiste.

Deseja que eu poste mais alguma código ou até mesmo a aplicação inteira?

Muito obrigado pela sua ajuda.

Abraço.

D

O métodos que tem transação estão fora de um bean do Spring??

bland

Fala Daniel,

Cara, essa anotação eu criei numa classe abstrata que é pai de todos os meus serviços.

Ou seja, todos os CRUD’s irão extender dessa classe e ela terá todas as operações básicas.

Porque? Isso pode ser um problema?

Obrigado mais uma vez Rafael pela tentativa de ajuda.

Abraço.

bland

Fala Daniel,

Li novamente e vi que esqueci de comentar que os meus serviços (classes filhas da classe que tem essa anotação de transação) são todos gerenciados pelo Spring, usando a anotação @Service.

Bem, espero que você possa me ajudar. Mais uma vez, obrigado.

Abraço.

Criado 23 de setembro de 2010
Ultima resposta 24 de set. de 2010
Respostas 7
Participantes 2