Announcement Announcement Module
Collapse
No announcement yet.
Exception handling with transaction AOP Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exception handling with transaction AOP

    Hello,

    I have the follownig configuration in my springConfig.xml file :
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    
    <beans>	
    	<!-- ========================= Start of PERSISTENCE DEFINITIONS ========================= -->
    	<!-- DataSource Definition -->
    	<bean id="dataSource"
          		class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    		<property name="driverClassName">
    			<value>oracle.jdbc.driver.OracleDriver</value>
    		</property>
    		<property name="url">
    			<value>URL</value>
    		</property>
    		<property name="username">
    			<value>USERNAME</value>
    		</property>
    		<property name="password">
    			<value>PASSWORD</value>
    		</property>
    	</bean>
    	
    	<!-- Hibernate SessionFactory Definition -->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    		<property name="mappingResources">
    			<list>
    				<value>MAPPING_RESOURCES</value>
    			</list>
    		</property>		
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
    				<prop key="hibernate.show_sql">true</prop>
    				<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
    				<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
    			</props>
    		</property>	
    		<property name="dataSource">
    			<ref bean="dataSource"/>
    		</property>
    	</bean>
    	
    	<!-- Spring Data Access Exception Translator Defintion -->
    	<bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator"> 
    		<property name="dataSource"><ref bean="dataSource"/></property> 
    	</bean>
    
    	<!-- Hibernate Template Defintion -->
    	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    		<property name="sessionFactory"><ref bean="sessionFactory"/></property> 
    		<property name="jdbcExceptionTranslator"><ref bean="jdbcExceptionTranslator"/></property> 
    	</bean>
    	
    	<!-- ErrMsg DAO object&#58; Hibernate implementation -->
    	<bean id="errMsgDao" class="ErrMsgDAOHibernateImpl">
    		<property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property>
    	</bean>
    	
    	<!-- ========================= Start of SERVICE DEFINITIONS ========================= -->
    	
    	<!-- Hibernate Transaction Manager Definition -->
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory"><ref local="sessionFactory"/></property>
    	</bean>
    	
    	<!-- ErrrorMessage Service Defintion -->
    	<bean id="errorMessageServiceTarget"
    			class="ErrorMessageServiceHibernateImpl">
    		<property name="errMsgDao"><ref local="errMsgDao"/></property>
    	</bean>
    	
    	<!-- Transactional proxy for the ErrrorMessage Service -->
    	<bean id="errorMessageService"
    			class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref local="transactionManager"/></property>
    		<property name="target"><ref local="errorMessageServiceTarget"/></property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
    				<prop key="save*">PROPAGATION_REQUIRED</prop>
    				<prop key="update*">PROPAGATION_REQUIRED</prop>
    				<prop key="delete*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    	</bean>
    </beans>
    And in my ErrorMessageServiceHibernateImpl, I have the following code :
    Code:
    public void update&#40;Cwd01 errMsg&#41; throws Exception &#123;
    	try &#123;
    		this.getErrMsgDao&#40;&#41;.updateErrMsg&#40;errMsg&#41;;
    	&#125; catch&#40;DataIntegrityViolationException dive&#41; &#123;
    		throw dive;
    	&#125; catch &#40;Exception e&#41; &#123;
    		throw e
    	&#125;
    &#125;
    But when I make an update with a field too large (I try to set a 300 characters String in a 250 database field), I don't go into the DataIntegerityViolationException of my business service, but well in my JSF-bean that has called this service.

    How is it possible ?

    I have the following error :
    Code:
    org.springframework.dao.DataIntegrityViolationException&#58; &#40;Hibernate operation&#58; Could not execute JDBC batch update&#41;&#58; data integrity violated by SQL 'update CWD01 set NUMVER=?, REFMAJ=?, DATCRT=?, DATMAJ=?, HEUMAJ=?, USRMAJ=?, PGMMAJ=?, STAANN=?, LIBMSG_1=?, LIBMSG_2=?, LIBMSG_3=?, LIBMSG_4=?, NUMREF=?, SWIAUD=? where NUMMSG=?'; nested exception is java.sql.BatchUpdateException&#58; ORA-01401&#58; inserted value too large for column
    
    java.sql.BatchUpdateException&#58; ORA-01401&#58; inserted value too large for column
    
    	at oracle.jdbc.dbaccess.DBError.throwBatchUpdateException&#40;DBError.java&#58;430&#41;
    	at oracle.jdbc.driver.OraclePreparedStatement.executeBatch&#40;OraclePreparedStatement.java&#58;2948&#41;
    	at org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch&#40;DelegatingPreparedStatement.java&#58;231&#41;
    	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch&#40;BatchingBatcher.java&#58;57&#41;
    	at org.hibernate.jdbc.AbstractBatcher.executeBatch&#40;AbstractBatcher.java&#58;174&#41;
    	at org.hibernate.engine.ActionQueue.executeActions&#40;ActionQueue.java&#58;226&#41;
    	at org.hibernate.engine.ActionQueue.executeActions&#40;ActionQueue.java&#58;137&#41;
    	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions&#40;AbstractFlushingEventListener.java&#58;274&#41;
    	at org.hibernate.event.def.DefaultFlushEventListener.onFlush&#40;DefaultFlushEventListener.java&#58;27&#41;
    	at org.hibernate.impl.SessionImpl.flush&#40;SessionImpl.java&#58;730&#41;
    	at org.hibernate.impl.SessionImpl.managedFlush&#40;SessionImpl.java&#58;324&#41;
    	at org.hibernate.transaction.JDBCTransaction.commit&#40;JDBCTransaction.java&#58;86&#41;
    	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit&#40;HibernateTransactionManager.java&#58;488&#41;
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit&#40;AbstractPlatformTransactionManager.java&#58;435&#41;
    	at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning&#40;TransactionAspectSupport.java&#58;258&#41;
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke&#40;TransactionInterceptor.java&#58;67&#41;
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed&#40;ReflectiveMethodInvocation.java&#58;144&#41;
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke&#40;JdkDynamicAopProxy.java&#58;174&#41;
    	at $Proxy56.update&#40;Unknown Source&#41;
    	at com.cwsoft.emmngt.view.bean.ErrorMessageBean.updateConfirm&#40;ErrorMessageBean.java&#58;194&#41;
    	at sun.reflect.NativeMethodAccessorImpl.invoke0&#40;Native Method&#41;
    	at sun.reflect.NativeMethodAccessorImpl.invoke&#40;NativeMethodAccessorImpl.java&#58;39&#41;
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke&#40;DelegatingMethodAccessorImpl.java&#58;25&#41;
    	at java.lang.reflect.Method.invoke&#40;Method.java&#58;324&#41;
    	at com.sun.faces.el.MethodBindingImpl.invoke&#40;MethodBindingImpl.java&#58;126&#41;
    	at com.sun.faces.application.ActionListenerImpl.processAction&#40;ActionListenerImpl.java&#58;72&#41;
    	at javax.faces.component.UICommand.broadcast&#40;UICommand.java&#58;312&#41;
    	at javax.faces.component.UIViewRoot.broadcastEvents&#40;UIViewRoot.java&#58;266&#41;
    	at javax.faces.component.UIViewRoot.processApplication&#40;UIViewRoot.java&#58;380&#41;
    	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute&#40;InvokeApplicationPhase.java&#58;75&#41;
    	at com.sun.faces.lifecycle.LifecycleImpl.phase&#40;LifecycleImpl.java&#58;200&#41;
    	at com.sun.faces.lifecycle.LifecycleImpl.execute&#40;LifecycleImpl.java&#58;90&#41;
    	at javax.faces.webapp.FacesServlet.service&#40;FacesServlet.java&#58;197&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter&#40;ApplicationFilterChain.java&#58;237&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter&#40;ApplicationFilterChain.java&#58;157&#41;
    	at org.extremecomponents.table.filter.ExportFilter.doFilter&#40;ExportFilter.java&#58;87&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter&#40;ApplicationFilterChain.java&#58;186&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter&#40;ApplicationFilterChain.java&#58;157&#41;
    	at com.cwsoft.commons.webapp.filter.SecurityFilter.doFilter&#40;SecurityFilter.java&#58;66&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter&#40;ApplicationFilterChain.java&#58;186&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter&#40;ApplicationFilterChain.java&#58;157&#41;
    	at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter&#40;ReplyHeaderFilter.java&#58;75&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter&#40;ApplicationFilterChain.java&#58;186&#41;
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter&#40;ApplicationFilterChain.java&#58;157&#41;
    	at org.apache.catalina.core.StandardWrapperValve.invoke&#40;StandardWrapperValve.java&#58;214&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardContextValve.invokeInternal&#40;StandardContextValve.java&#58;198&#41;
    	at org.apache.catalina.core.StandardContextValve.invoke&#40;StandardContextValve.java&#58;152&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke&#40;CustomPrincipalValve.java&#58;66&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;102&#41;
    	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke&#40;SecurityAssociationValve.java&#58;150&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;102&#41;
    	at org.jboss.web.tomcat.security.JaccContextValve.invoke&#40;JaccContextValve.java&#58;54&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;102&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardHostValve.invoke&#40;StandardHostValve.java&#58;137&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.valves.ErrorReportValve.invoke&#40;ErrorReportValve.java&#58;118&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;102&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.StandardEngineValve.invoke&#40;StandardEngineValve.java&#58;109&#41;
    	at org.apache.catalina.core.StandardValveContext.invokeNext&#40;StandardValveContext.java&#58;104&#41;
    	at org.apache.catalina.core.StandardPipeline.invoke&#40;StandardPipeline.java&#58;520&#41;
    	at org.apache.catalina.core.ContainerBase.invoke&#40;ContainerBase.java&#58;929&#41;
    	at org.apache.coyote.tomcat5.CoyoteAdapter.service&#40;CoyoteAdapter.java&#58;160&#41;
    	at org.apache.coyote.http11.Http11Processor.process&#40;Http11Processor.java&#58;799&#41;
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection&#40;Http11Protocol.java&#58;705&#41;
    	at org.apache.tomcat.util.net.TcpWorkerThread.runIt&#40;PoolTcpEndpoint.java&#58;577&#41;
    	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run&#40;ThreadPool.java&#58;683&#41;
    	at java.lang.Thread.run&#40;Thread.java&#58;534&#41;
    Thanks in advance for your help.
    Blaise

  • #2
    As you can see from the stacktrace, the exception is not being thrown on the update operation but on the commit. But the commit is invoked after your update()-Method has been left; too late to catch the exception there.

    Maybe it helps, if you perform a flush() inside your hibernate DAO, to force this error to occur earlier.

    Regards,
    Andreas

    Comment


    • #3
      First of all, thanks for your reply.

      But could you explain me why the exception occures during the commit, and not during the update ? The update should normaly already create an exception. Am I wrong ?

      And could you also explain me what to do to perform a flush inside the Hibernate DAO ? I don't understand it !?

      Thanks in advance...

      Comment


      • #4
        Hibernate (as other ORM libraries) does not necessarily issue SQL to the database the moment you fire an update query. It might be that it waits until before commit to issue all SQL operations in a bunch. This is happening here.

        Note that delaying the actual SQL generation might be used for optimizing database load. For example, you might change an instance and then delete it a little bit later (in the same transaction). No need to perform an UPDATE, the DELETE alone would be just fine.

        The hibernate Session has a flush() method which is by default automatically invoked before commit (can be adjusted though). This method takes care that any outstanding operations are actually sent to the database. If you invoke flush() inside your DAO method (so inside your catch block) you might be able to catch the exception in the place you expect.

        Just be aware that there still might be some other constraints that will be checked only at commit time. So it is no guarantee that a successful flush will lead to a successful commit.

        Regards,
        Andreas

        Comment

        Working...
        X