I have a spring boot application with the following data source setup:
application.properties:
tomcat.jdbc.pool.url=jdbc:mysql://url/db
tomcat.jdbc.pool.username=username
tomcat.jdbc.pool.password=password
tomcat.jdbc.pool.initial-size=10
tomcat.jdbc.pool.test-on-borrow=true
tomcat.jdbc.pool.test-while-idle=true
tomcat.jdbc.pool.validation-query=SELECT 1
tomcat.jdbc.pool.driver-class-name=com.mysql.jdbc.Driver
tomcat.jdbc.pool.max_size=30
tomcat.jdbc.pool.min_size=7
DataSourceConfiguration.java
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class DataSourceConfiguration {
@Value("${tomcat.jdbc.pool.max_size}")
private int maxSize;
@Value("${tomcat.jdbc.pool.min_size}")
private int minSize;
@Value("${tomcat.jdbc.pool.initial-size}")
private int initialSize;
@Value("${tomcat.jdbc.pool.test-on-borrow}")
private boolean testOnBorrow;
@Value("${tomcat.jdbc.pool.test-while-idle}")
private boolean testWhileIdle;
@Value("${tomcat.jdbc.pool.username}")
private String username;
@Value("${tomcat.jdbc.pool.password}")
private String password;
@Value("${tomcat.jdbc.pool.url}")
private String url;
@Value("${tomcat.jdbc.pool.driver-class-name}")
private String driverClassName;
@Value("${tomcat.jdbc.pool.validation-query}")
private String validationQuery;
@Bean
@Primary
public DataSource dataSource() {
DataSource dataSource = new DataSource();
dataSource.setUrl(url);
dataSource.setPassword(password);
dataSource.setUsername(username);
dataSource.setDriverClassName(driverClassName);
dataSource.setValidationQuery(validationQuery);
dataSource.setInitialSize(initialSize);
dataSource.setMaxIdle(maxSize);
dataSource.setMinIdle(minSize);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setTestWhileIdle(testWhileIdle);
return dataSource;
}
}
And finally I have a repository that utilizes this datasource in a jdbcTemplate:
@Repository
public class PositionRepository {
private static JdbcTemplate jdbcTemplate;
public PositionRepository() {}
@Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
...
...
}
I confirmed that the datasource being passed to the JdbcTemplate constructor is indeed org.apache.tomcat.jdbc.pool.DataSource.
Every now and then, however, I get the following exception:
[2015-09-29 10:44:40.098] boot - 14124 INFO [http-nio-8888-exec-5] --- XmlBeanDefinitionReader: Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
[2015-09-29 10:44:40.302] boot - 14124 INFO [http-nio-8888-exec-5] --- SQLErrorCodesFactory: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]
[2015-09-29 10:44:40.308] boot - 14124 WARN [http-nio-8888-exec-5] --- SQLErrorCodesFactory: Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:305) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:329) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:214) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:134) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.java:97) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.support.JdbcAccessor.getExceptionTranslator(JdbcAccessor.java:99) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:416) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:471) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:481) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:521) [spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.myproj.somename.repositories.PositionRepository.runQueryForList(PositionRepository.java:34) [classes/:?]
at org.myproj.somename.repositories.PositionRepository.positionFindPaged(PositionRepository.java:52) [classes/:?]
at org.myproj.somename.repositories.PositionRepository$$FastClassBySpringCGLIB$$ce8ed984.invoke(<generated>) [spring-core-4.1.7.RELEASE.jar:?]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) [spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) [spring-tx-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) [spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.myproj.somename.repositories.PositionRepository$$EnhancerBySpringCGLIB$$a986c62b.positionFindPaged(<generated>) [spring-core-4.1.7.RELEASE.jar:?]
at org.myproj.somename.controllers.api.Positions.runPositions(Positions.java:148) [classes/:?]
at org.myproj.somename.controllers.api.Positions.runPositions(Positions.java:93) [classes/:?]
at org.myproj.somename.controllers.api.Positions.getPositions(Positions.java:61) [classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0]
at java.lang.reflect.Method.invoke(Method.java:483) ~[?:1.8.0]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-
embed-core-8.0.23.jar:8.0.23]
at ....
.....
.....
.....
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478) [tomcat-embed-core-8.0.23.jar:8.0.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.23.jar:8.0.23]
at java.lang.Thread.run(Thread.java:744) [?:1.8.0]
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0]
at java.lang.reflect.Constructor.newInstance(Constructor.java:408) ~[?:1.8.0]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.Util.getInstance(Util.java:372) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:958) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1236) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1231) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.getMetaData(ConnectionImpl.java:2938) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.getMetaData(ConnectionImpl.java:2933) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0]
at java.lang.reflect.Method.invoke(Method.java:483) ~[?:1.8.0]
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) ~[tomcat-jdbc-8.0.23.jar:?]
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108) ~[tomcat-jdbc-8.0.23.jar:?]
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81) ~[tomcat-jdbc-8.0.23.jar:?]
at com.sun.proxy.$Proxy83.getMetaData(Unknown Source) ~[?:?]
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:294) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
... 103 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 16,234 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0]
at java.lang.reflect.Constructor.newInstance(Constructor.java:408) ~[?:1.8.0]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1038) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3422) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3322) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3762) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2531) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2489) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1446) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:455) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:405) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
... 97 more
Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2914) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3332) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3322) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3762) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2531) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2489) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1446) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:455) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:405) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
... 97 more
[2015-09-29 10:44:40.344] boot - 14124 ERROR [http-nio-8888-exec-5] --- [dispatcherServlet]: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.RecoverableDataAccessException: StatementCallback; SQL [SELECT * FROM ( SELECT ticker, `type`, strike, expiration, SUM(premium) / COUNT(*) avg_premium, SUM(newquantity)*multiplier `position` FROM ( SELECT IF (ACTION = 'BOUGHT', quantity, -quantity) newquantity, e.ticker_eurex ticker, e.multiplier, tr.* FROM trade_record tr JOIN equity e ON tr.equity_id = e.id) a WHERE ( `expiration` >= '2015-09-29' ) and true and trade_date <= '2015-07-09' GROUP BY ticker, TYPE, strike, expiration ORDER BY expiration desc , strike asc , position desc LIMIT 0,100 ) z WHERE true AND position <> 0 ]; Communications link failure
The last packet successfully received from the server was 16,234 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 16,234 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.] with root cause
java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2914) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3332) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3322) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3762) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2531) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2489) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1446) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:455) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:405) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:471) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:481) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:521) ~[spring-jdbc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.myproj.somename.repositories.PositionRepository.runQueryForList(PositionRepository.java:34) ~[classes/:?]
at org.myproj.somename.repositories.PositionRepository.positionFindPaged(PositionRepository.java:52) ~[classes/:?]
at org.myproj.somename.repositories.PositionRepository$$FastClassBySpringCGLIB$$ce8ed984.invoke(<generated>) ~[spring-core-4.1.7.RELEASE.jar:?]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.myproj.somename.repositories.PositionRepository$$EnhancerBySpringCGLIB$$a986c62b.positionFindPaged(<generated>) ~[spring-core-4.1.7.RELEASE.jar:?]
at org.myproj.somename.controllers.api.Positions.runPositions(Positions.java:148) ~[classes/:?]
at org.myproj.somename.controllers.api.Positions.runPositions(Positions.java:93) ~[classes/:?]
at org.myproj.somename.controllers.api.Positions.getPositions(Positions.java:61) ~[classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0]
at java.lang.reflect.Method.invoke(Method.java:483) ~[?:1.8.0]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
.....
.....
....
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478) [tomcat-embed-core-8.0.23.jar:8.0.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.23.jar:8.0.23]
at java.lang.Thread.run(Thread.java:744) [?:1.8.0]
Could someone tell me what am I doing wrong. Isn't the whole point of using connection pooling to avoid this type of issues? Can I somehow tell tomcat-jdbc that I don't want exceptions unless it tried to reconnect X number of times? On top of that setTestOnBorrow and setTestOnIdle are both set to true.
Anyone has any ideas what's going on? Am I doing something wrong in my setup?
Cheers and thanks in advance!
P.S.
I truncated the exception at one point in order to fit within the max char limit of SO.
So long story short, I eventually ended up ditching jdbc-pool because it turned out to be an absolute waste of time. I decided to give HikariCP a shot with my Spring Boot backend and I couldn't be happier. It started handling the disconnection issues automatically and gracefully after a super basic setup.
If you're running Spring Boot all you need is to add this to your pom.xml
<!-- HikariCP DB Connection Pooling -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.1</version>
</dependency>
and then you just need to set the HikariCP properties accordingly. This is my setup and I had 0 problems with it
# hikariCP
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://localhost/some_db_name?useUnicode=true&characterEncoding=utf8&dumpQueriesOnException=true
spring.datasource.username=<your_username_here>
spring.datasource.password=<your_password_here>
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.pool-name=SpringBootHikariCP
spring.datasource.maximum-pool-size=8
spring.datasource.minimum-idle=5
spring.datasource.max-lifetime=2000000
spring.datasource.connection-timeout=30000
spring.datasource.idle-timeout=30000
spring.datasource.pool-prepared-statements=true
spring.datasource.max-open-prepared-statements=250
spring.datasource.validation-query=SELECT 1
spring.datasource.pool-prepared-statements=true
spring.datasource.pool-prepared-statements-cache-size=250
spring.datasource.pool-prepared-statements-cache-sql-limit=2048
spring.datasource.user-server-prepared-statements=true
And finally this was the corresponding DataSource configuration using the properties above
@EnableTransactionManagement
@Configuration
public class DataSourceConfiguration {
// HikariCP
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.pool-name}")
private String poolName;
@Value("${spring.datasource.connection-timeout}")
private int connectionTimeout;
@Value("${spring.datasource.max-lifetime}")
private int maxLifetime;
@Value("${spring.datasource.maximum-pool-size}")
private int maximumPoolSize;
@Value("${spring.datasource.minimum-idle}")
private int minimumIdle;
@Value("${spring.datasource.idle-timeout}")
private int idleTimeout;
@Value("${spring.datasource.validation-query}")
private String validationQuery;
@Value("${spring.datasource.pool-prepared-statements}")
private String cachePrepStmts;
@Value("${spring.datasource.pool-prepared-statements-cache-size}")
private String prepStmtCacheSize;
@Value("${spring.datasource.pool-prepared-statements-cache-sql-limit}")
private String prepStmtCacheSqlLimit;
@Value("${spring.datasource.user-server-prepared-statements}")
private String useServerPrepStmts;
@Bean
public DataSource primaryDataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
hikariConfig.setMaximumPoolSize(maximumPoolSize);
hikariConfig.setMinimumIdle(minimumIdle);
hikariConfig.setConnectionTimeout(connectionTimeout);
hikariConfig.setIdleTimeout(idleTimeout);
hikariConfig.setConnectionTestQuery(validationQuery);
hikariConfig.setPoolName("springHikariCP");
hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", cachePrepStmts);
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", prepStmtCacheSize);
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", prepStmtCacheSqlLimit);
hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", useServerPrepStmts);
HikariDataSource ds = new HikariDataSource(hikariConfig);
return ds;
}
}
That's what resolved the problem for me.