Spring (@Transact) - try catch sem funcionamento

Olá bom dia, levando em conta o fluxo mvc temos o seguinte cenário:

View -> Controller -> BO -> DAO -> Generic DAO

Ok, assunto batido, mas me deparei com uma situação que resolvi pedi um auxilio aos Srs., bom o projeto tem Spring e hibernate atualmente o @Transact está dentro do generic dao mas para utilizar o roll back das transações do spring coloquei o transact dentro do BO levando em conta que dentro do Generic DAO não tenho try catch, dai veio a surpresa, a transação funcionou mas o try catch de dentro do BO não… forcei uma excessão e ele simplesmente passou direto enviando a excessao para a view sem tratamento. Gostaria de saber se há algum parametro dentro do transact para que ele leve em conta o try catch, o codigo do BO é parecido com o abaixo:

	@SuppressWarnings ({ "unchecked", "finally" })
	@Override
        @Transact
	public ArrayList remover(Usuario e) {		
		try {			
			objDao.remover(e);
			arrRet = new ArrayList();
			arrRet.add(0, 1);
			arrRet.add(1, Mensagens.getMensagem(1));
		} catch (IndexOutOfBoundsException ex) {
			objLog.gravarLog("CLASSE " + this + " | MÉTODO - remover() | DESCRIÇÃO - MANIPULAÇÃO DO arrRet PARA MONTAGEM DE RETORNO", ex);			
			arrRet = new ArrayList();
			arrRet.add(0, 0);
			arrRet.add(1, Mensagens.getMensagem(10) + Mensagens.getBarra() + Mensagens.getRodape());
		} catch (DataIntegrityViolationException ex) {							
			objLog.gravarLog("CLASSE " + this + " | MÉTODO - remover() | DESCRIÇÃO - ERRO DE DEPENDÊNCIA", ex);
			arrRet = new ArrayList();
			arrRet.add(0, 0);
			arrRet.add(1, Mensagens.getMensagem(30) + Mensagens.getBarra() + Mensagens.getRodape());			
		} catch (Exception ex) {			
			objLog.gravarLog("CLASSE " + this + " | MÉTODO - remover() | DESCRIÇÃO - SEM DESCRIÇÃO", ex);			
			arrRet = new ArrayList();
			arrRet.add(0, 0);
			arrRet.add(1, Mensagens.getMensagem(20) + Mensagens.getBarra() + Mensagens.getRodape());
		} finally {
			return arrRet;	
		}		
	}

de que pacote é esse @transact? posta tambem o xml de configuração do seu transaction manager :slight_smile:

Desculpe como estou no trabalho e o projeto esta em casa escrevi erroneamente o nome da anotação, não é transact e sim Transactional do Spring (import org.springframework.transaction.annotation.Transactional), segue como solicitado o arquivo web.xml

<?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">    
        <!-- CONFIGURANDO O SPRING -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/applicationContext.xml
            </param-value>
        </context-param>
          
		<filter>
			<filter-name>oemInViewFilter</filter-name>
			<filter-class>
				org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
			</filter-class>
			<init-param>
				<param-name>sessionFactoryBeanName</param-name>
				<param-value>sessionFactory</param-value>
			</init-param>
		
		</filter>
		
		<filter-mapping>
			<filter-name>oemInViewFilter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>
      	      
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
                	     
        <listener>
            <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
        </listener>
        
        <!-- CONFIGURANDO O BLAZEDS -->
        <context-param>
            <param-name>flex.class.path</param-name>
            <param-value>/WEB-INF/flex/hotfixes</param-value>
        </context-param>
     
        <!-- CONFIGURANDO O MESSAGEBROKER SERVLET -->
        <servlet>
            <servlet-name>MessageBrokerServlet</servlet-name>
            <display-name>MessageBrokerServlet</display-name>
            <servlet-class>
                flex.messaging.MessageBrokerServlet
            </servlet-class>
            <init-param>
                <param-name>services.configuration.file</param-name>
                <param-value>/WEB-INF/flex/services-config.xml</param-value>
            </init-param>
            <init-param>
                <param-name>flex.write.path</param-name>
                <param-value>/WEB-INF/flex</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>MessageBrokerServlet</servlet-name>
            <url-pattern>/messagebroker/*</url-pattern>
        </servlet-mapping>     
		

     
        <display-name>BLA BLA BLA</display-name>
        
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
     
    </web-app>

certo. cole aqui o conteudo do applicationContext.xml pra gente ver, embora eu acredite que voce tenha esquecido do atributo rollbackFor :smiley:

edit: acho que nao tinha lido direiti sua duvida. Voce quis dizer que quando a exceção é capturada ai em cima, ela nao da rollback? desculpa, mas nao entendi sua duvida :shock:

A duvida é exatamente sobre a exception, ele não entra no try catch, vamos supor que eu va adicionar uma entidade com o atributo nome unique, dai eu va adicionar um cliente so que o cliente ja existe no banco isso caracteriza uma DataIntegrityViolationException só que ele não entra no try, ele não consegue gravar vai pro return e retorna a excessão para a view, se eu colocar o @Transactional no BO e colocar o try no controlador (Uma camada acima) ai sim ele captura, ou seja, se caso eu colocar o @transactional na camada X nesta mesma camada eu não consigo capturar nenhuma exception, a solução seria passar para a camada DAO Generico que se acontecer alguma excessão está sendo tratada na camada de cima, porém perco a utilidade do Roll Back devido o try estar em outra camada. Segue o arquivo applicationContext.xml com as configurações do spring como solicitado.

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:aop="http://www.springframework.org/schema/aop"    
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:tx="http://www.springframework.org/schema/tx"        
        xsi:schemaLocation="                
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
        default-lazy-init="true"> <!-- INICIALIZAÇÃO TARDIA -->          
	    
        
        <!-- DEFINE OS PACOTES/SUBPACOTES QUE SERAO SCANEADOS PELO SPRING -->
	    <context:component-scan base-package="controlador" />
  	    <context:component-scan base-package="modelo" />
   	    <context:component-scan base-package="util" /> 
    	
        <!-- CARREGA ARQUIVO DE CONFIGURACAO JDBC-->        
        <context:property-placeholder location="classpath:util/jdbc.properties" />      
		<tx:annotation-driven />
				
		<bean id="IBaseDAO" class="modelo.interfaces.base.IBaseDAO" p:sessionFactory-ref="sessionFactory" />
          				
        <!-- CONFIGURACAO DO DATASOURCE -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName">
                <value>${jdbc.driverClassName}</value>
            </property>
            <property name="url">
                <value>${jdbc.url}</value>
            </property>
            <property name="username">
                <value>${jdbc.username}</value>
            </property>
            <property name="password">
                <value>${jdbc.password}</value>
            </property>
        </bean>
        
     	<!-- TRANSACTION MANAGER -->
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">        
            <property name="sessionFactory">
                <ref local="sessionFactory"/>
            </property>
        </bean>          
     
        <!-- CONFIGURACAO DO SESSIONFACTORY DO HIBERNATE -->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">     
            <property name="dataSource">
                <ref local="dataSource" />
            </property>   
	        	
            <!-- CONFIGURACAO DO HIBERNATE -->
            <property name="hibernateProperties">
	
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                </props>
            </property>
			
			<property name="packagesToScan" value="modelo.dto" />	    
     
            <property name="eventListeners">
                <map>
                    <entry key="merge">
                        <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
                    </entry>
                </map>
            </property>                 
        </bean>        

   
  
</beans>

Vamos supor o ambiente perfeito:

ObjetoBO.salvar(objeto);

class ObjetoBO {

      @Transactional(rollbackFor=Exception.class)
      public void salvar(Objeto objeto) {
           try {
                 ObjetoDAO.salvar(objeto);
           } catch(Exception e) {
                  // se você capturar alguma exception aqui, e não propogar, o TransactionManager vai pensar que está tudo ok, e irá comitar. Se quiser fazer algum tratamento, faca aqui e depois lance a exceção normalmente com um throws :)
           }
      }
}


class ObjetoDAO {

      @Transactional(rollbackFor=Exception.class)
      public void salvar(Objeto objeto) {
           GenericDAO.salvar(objeto);
            // você não pode dar catch de exceção aqui
      }
}

class GenericDAO {

       EntityManager entityManager;

      @Transactional(rollbackFor=Exception.class)
      public void salvar(Objeto objeto) {
           entityManager.persist(objeto);
           // você não pode dar catch de exceção aqui
      }
}

lembrando que o default de transactional é:

Analisando o codigo que me enviou você quiz dizer que o que faltou para que o meu codigo capturasse as exceptions foi colocar dentro do transaction o parametro rollbackFor=Exception.class que quer dizer que dentro daquela transação poderá acontecer exceptions do tipo Exception que é um dos tipos mais genericos de excessão… é isso mesmo ??

Cristiano estou passando exatamente pelo msm problema, como resolveu??