Jiri Patera created AMQ-4836: -------------------------------- Summary: Calling Connection.commit() on a Connection with setAutoCommit(true) throws SQLException Key: AMQ-4836 URL: https://issues.apache.org/jira/browse/AMQ-4836 Project: ActiveMQ Issue Type: Bug Components: Message Store Affects Versions: 5.7.0 Environment: JDK 1.6.0_45, Firebird or HDB (SAP HANA DB) configured as a persistent storage Reporter: Jiri Patera
This issue is similar to AMQ-577 (resolved by adding a MSSQL JDBC URL parameter) and AMQ-711 (resolved as cannot reproduce) issues. The problem is that the JDBC API (the {{Connection}} class JavaDoc) states: {code} /** * Makes all changes made since the previous * commit/rollback permanent and releases any database locks * currently held by this <code>Connection</code> object. * This method should be * used only when auto-commit mode has been disabled. * * @exception SQLException if a database access error occurs, * this method is called while participating in a distributed transaction, * if this method is called on a closed conection or this * <code>Connection</code> object is in auto-commit mode * @see #setAutoCommit */ void commit() throws SQLException; {code} However, some JDBC drivers do not throw the {{SQLException}} when the {{Connection.commit()}} method is called on a {{Connection}} instance with {{setAutoCommit(true)}}. Some others do (Firebird, SAP-HANA, MSSQL without the JDBC URL parameter {{relaxAutoCommit=true}}). With these databases the following exceptions can be thrown on the Broker start-up: 1) {{DefaultJDBCAdapter.doDropTables(DefaultJDBCAdapter.java:148)}}: {code} Caused by: com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: Connection is currently in auto commit mode. at com.sap.db.jdbc.exceptions.SQLExceptionSapDB.createException(SQLExceptionSapDB.java:334) at com.sap.db.jdbc.exceptions.SQLExceptionSapDB.generateSQLException(SQLExceptionSapDB.java:113) at com.sap.db.jdbc.ConnectionSapDB.commit(ConnectionSapDB.java:351) at com.sap.db.jdbc.trace.Connection.commit(Connection.java:126) at org.apache.commons.dbcp.DelegatingConnection.commit(DelegatingConnection.java:334) at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.commit(PoolingDataSource.java:211) at org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doDropTables(DefaultJDBCAdapter.java:148) at org.apache.activemq.store.jdbc.adapter.OptimizedDefaultJDBCAdapter.doDropTables(OptimizedDefaultJDBCAdapter.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke(AbstractTraceInterceptor.java:113) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at com.sun.proxy.$Proxy12.doDropTables(Unknown Source) at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter.deleteAllMessages(JDBCPersistenceAdapter.java:526) ... 64 more {code} 2) {{DefaultJDBCAdapter.doCreateTables(DefaultJDBCAdapter.java:119)}} {code} Caused by: com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: Connection is currently in auto commit mode. at com.sap.db.jdbc.exceptions.SQLExceptionSapDB.createException(SQLExceptionSapDB.java:334) at com.sap.db.jdbc.exceptions.SQLExceptionSapDB.generateSQLException(SQLExceptionSapDB.java:113) at com.sap.db.jdbc.ConnectionSapDB.commit(ConnectionSapDB.java:351) at com.sap.db.jdbc.trace.Connection.commit(Connection.java:126) at org.apache.commons.dbcp.DelegatingConnection.commit(DelegatingConnection.java:334) at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.commit(PoolingDataSource.java:211) at org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doCreateTables(DefaultJDBCAdapter.java:119) at org.apache.activemq.store.jdbc.adapter.OptimizedDefaultJDBCAdapter.doCreateTables(OptimizedDefaultJDBCAdapter.java:62) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke(AbstractTraceInterceptor.java:113) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at com.sun.proxy.$Proxy12.doCreateTables(Unknown Source) at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter.deleteAllMessages(JDBCPersistenceAdapter.java:528) ... 64 more {code} This led us to a workaround where we simply override the 1) and 2) methods and replaced the following code in them: {code} c.getConnection().commit(); {code} With the following code (to prevent the exceptions from being thrown): {code} if (!c.getConnection().getAutoCommit()) { /* HACK */ c.getConnection().commit(); } {code} I believe that the ActiveMQ code should correspond to the JDBC API specification by calling the {{Connection.commit()}} method only on connections with {{setAutoCommit(false)}}. This approach is already implemented in the ActiveMQ code, for example, in the following method: {code} org.apache.activemq.store.jdbc.TransactionContext.commit() {code} -- This message was sent by Atlassian JIRA (v6.1#6144)