From deebf1604125aed87f7757cc7f2227fe8174dd32 Mon Sep 17 00:00:00 2001 From: Joshua Chaitin-Pollak Date: Mon, 20 Oct 2014 17:21:33 -0400 Subject: [PATCH 1/4] Initial attempt at Hikari support --- .../build.gradle | 1 + .../service/relational/DataSourceCreator.java | 1 + .../HikariCpPooledDataSourceCreator.java | 57 +++++++++++++++++++ .../PooledDataSourceCreatorsTest.java | 5 ++ 4 files changed, 64 insertions(+) create mode 100644 spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java diff --git a/spring-cloud-spring-service-connector/build.gradle b/spring-cloud-spring-service-connector/build.gradle index 9b68e47..732cd20 100644 --- a/spring-cloud-spring-service-connector/build.gradle +++ b/spring-cloud-spring-service-connector/build.gradle @@ -23,6 +23,7 @@ dependencies { exclude(group: 'commons-logging', module: 'commons-logging') } optional("commons-dbcp:commons-dbcp:$commonDbcpVersion") + optional("com.zaxxer:HikariCP-java6:2.1.0") optional("org.springframework.amqp:spring-rabbit:$springAmqpVersion") optional("org.springframework.data:spring-data-redis:$springDataRedisVersion") { exclude(group: 'org.springframework', module: 'spring-context-support') diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java index 654799f..b9b3765 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java @@ -39,6 +39,7 @@ public abstract class DataSourceCreator extend pooledDataSourceCreators.add(new BasicDbcpPooledDataSourceCreator()); pooledDataSourceCreators.add(new TomcatDbcpPooledDataSourceCreator()); pooledDataSourceCreators.add(new TomcatHighPerformancePooledDataSourceCreator()); + pooledDataSourceCreators.add(new HikariCpPooledDataSourceCreator()); } } diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java new file mode 100644 index 0000000..da7296d --- /dev/null +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java @@ -0,0 +1,57 @@ +package org.springframework.cloud.service.relational; + +import static org.springframework.cloud.service.Util.*; + +import java.util.logging.Logger; + +import javax.sql.DataSource; + +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.cloud.service.ServiceConnectorConfig; +import org.springframework.cloud.service.common.RelationalServiceInfo; + +import com.zaxxer.hikari.HikariDataSource; + +public class HikariCpPooledDataSourceCreator implements PooledDataSourceCreator { + + protected static Logger logger = Logger.getLogger(PooledDataSourceCreator.class.getName()); + + private static final String HIKARI_CLASSNAME = "com.zaxxer.hikari.HikariDataSource"; + + private DataSourceConfigurer configurer = new DataSourceConfigurer(); + + protected void setBasicDataSourceProperties(DataSource basicDataSource, RelationalServiceInfo serviceInfo, + ServiceConnectorConfig serviceConnectorConfig, + String driverClassName, String validationQuery) { + BeanWrapper target = new BeanWrapperImpl(basicDataSource); + target.setPropertyValue("driverClassName", driverClassName); + target.setPropertyValue("jdbcUrl", serviceInfo.getJdbcUrl()); + if (validationQuery != null) { + target.setPropertyValue("connectionTestQuery", validationQuery); + } + + if (serviceConnectorConfig == null) { + // choose sensible values so that we set max connection pool size to what + // free tier services on Cloud Foundry and Heroku allow + target.setPropertyValue("maximumPoolSize", 4); + target.setPropertyValue("connectionTimeout", 30000); + } + configurer.configure(basicDataSource, (DataSourceConfig)serviceConnectorConfig); + } + + + @Override + public DataSource create(RelationalServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig, + String driverClassName, String validationQuery) { + if (hasClass(HIKARI_CLASSNAME)) { + logger.info("Found HikariCP on the classpath. Using it for DataSource connection pooling."); + HikariDataSource ds = new HikariDataSource(); + setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery); + return ds; + } else { + return null; + } + } + +} diff --git a/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java index 5791980..c906a79 100644 --- a/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java +++ b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java @@ -35,6 +35,11 @@ public class PooledDataSourceCreatorsTest { assertPooledDataSource(new TomcatHighPerformancePooledDataSourceCreator()); } + @Test + public void pooledDataSourceCreationHikariCP() { + assertPooledDataSource(new HikariCpPooledDataSourceCreator()); + } + private void assertPooledDataSource(PooledDataSourceCreator testCreator) { DataSource ds = testCreator.create(mockMysqlServiceInfo, null, mysqlDataSourceCreator.getDriverClassName(mockMysqlServiceInfo), From 28aa69c64ac2c1dd58cf6ab5c83f2b534ca942dd Mon Sep 17 00:00:00 2001 From: Joshua Chaitin-Pollak Date: Tue, 4 Nov 2014 18:33:45 -0500 Subject: [PATCH 2/4] replaced spaces with tabs --- .../service/relational/DataSourceCreator.java | 48 ++++++------- .../HikariCpPooledDataSourceCreator.java | 67 +++++++++---------- .../PooledDataSourceCreatorsTest.java | 40 +++++------ 3 files changed, 77 insertions(+), 78 deletions(-) diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java index b9b3765..56cbc01 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/DataSourceCreator.java @@ -22,18 +22,18 @@ import org.springframework.jdbc.datasource.SimpleDriverDataSource; */ public abstract class DataSourceCreator extends AbstractServiceConnectorCreator { - protected static Logger logger = Logger.getLogger(DataSourceCreator.class.getName()); + protected static Logger logger = Logger.getLogger(DataSourceCreator.class.getName()); - private String driverSystemPropKey; - private String[] driverClasses; - private String validationQuery; + private String driverSystemPropKey; + private String[] driverClasses; + private String validationQuery; - private List> pooledDataSourceCreators = new ArrayList>(); + private List> pooledDataSourceCreators = new ArrayList>(); public DataSourceCreator(String driverSystemPropKey, String[] driverClasses, String validationQuery) { - this.driverSystemPropKey = driverSystemPropKey; - this.driverClasses = driverClasses; - this.validationQuery = validationQuery; + this.driverSystemPropKey = driverSystemPropKey; + this.driverClasses = driverClasses; + this.validationQuery = validationQuery; if (pooledDataSourceCreators.size() == 0) { pooledDataSourceCreators.add(new BasicDbcpPooledDataSourceCreator()); @@ -63,21 +63,21 @@ public abstract class DataSourceCreator extend } } - public String getDriverClassName(SI serviceInfo) { - String userSpecifiedDriver = System.getProperty(driverSystemPropKey); + public String getDriverClassName(SI serviceInfo) { + String userSpecifiedDriver = System.getProperty(driverSystemPropKey); - if (userSpecifiedDriver != null && !userSpecifiedDriver.isEmpty()) { - return userSpecifiedDriver; - } else { - for (String driver : driverClasses) { - try { - Class.forName(driver); - return driver; - } catch (ClassNotFoundException ex) { - // continue... - } - } - } - throw new CloudException("No suitable database driver found for " + serviceInfo.getId() + " service "); - } + if (userSpecifiedDriver != null && !userSpecifiedDriver.isEmpty()) { + return userSpecifiedDriver; + } else { + for (String driver : driverClasses) { + try { + Class.forName(driver); + return driver; + } catch (ClassNotFoundException ex) { + // continue... + } + } + } + throw new CloudException("No suitable database driver found for " + serviceInfo.getId() + " service "); + } } diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java index da7296d..3a9b404 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java @@ -15,43 +15,42 @@ import com.zaxxer.hikari.HikariDataSource; public class HikariCpPooledDataSourceCreator implements PooledDataSourceCreator { - protected static Logger logger = Logger.getLogger(PooledDataSourceCreator.class.getName()); + protected static Logger logger = Logger.getLogger(PooledDataSourceCreator.class.getName()); - private static final String HIKARI_CLASSNAME = "com.zaxxer.hikari.HikariDataSource"; - - private DataSourceConfigurer configurer = new DataSourceConfigurer(); + private static final String HIKARI_CLASSNAME = "com.zaxxer.hikari.HikariDataSource"; - protected void setBasicDataSourceProperties(DataSource basicDataSource, RelationalServiceInfo serviceInfo, - ServiceConnectorConfig serviceConnectorConfig, - String driverClassName, String validationQuery) { - BeanWrapper target = new BeanWrapperImpl(basicDataSource); - target.setPropertyValue("driverClassName", driverClassName); - target.setPropertyValue("jdbcUrl", serviceInfo.getJdbcUrl()); - if (validationQuery != null) { - target.setPropertyValue("connectionTestQuery", validationQuery); - } + private DataSourceConfigurer configurer = new DataSourceConfigurer(); - if (serviceConnectorConfig == null) { - // choose sensible values so that we set max connection pool size to what - // free tier services on Cloud Foundry and Heroku allow - target.setPropertyValue("maximumPoolSize", 4); - target.setPropertyValue("connectionTimeout", 30000); - } - configurer.configure(basicDataSource, (DataSourceConfig)serviceConnectorConfig); - } + protected void setBasicDataSourceProperties(DataSource basicDataSource, RelationalServiceInfo serviceInfo, + ServiceConnectorConfig serviceConnectorConfig, + String driverClassName, String validationQuery) { + BeanWrapper target = new BeanWrapperImpl(basicDataSource); + target.setPropertyValue("driverClassName", driverClassName); + target.setPropertyValue("jdbcUrl", serviceInfo.getJdbcUrl()); + if (validationQuery != null) { + target.setPropertyValue("connectionTestQuery", validationQuery); + } - - @Override - public DataSource create(RelationalServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig, - String driverClassName, String validationQuery) { - if (hasClass(HIKARI_CLASSNAME)) { - logger.info("Found HikariCP on the classpath. Using it for DataSource connection pooling."); - HikariDataSource ds = new HikariDataSource(); - setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery); - return ds; - } else { - return null; - } - } + if (serviceConnectorConfig == null) { + // choose sensible values so that we set max connection pool size to what + // free tier services on Cloud Foundry and Heroku allow + target.setPropertyValue("maximumPoolSize", 4); + target.setPropertyValue("connectionTimeout", 30000); + } + configurer.configure(basicDataSource, (DataSourceConfig)serviceConnectorConfig); + } + + @Override + public DataSource create(RelationalServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig, + String driverClassName, String validationQuery) { + if (hasClass(HIKARI_CLASSNAME)) { + logger.info("Found HikariCP on the classpath. Using it for DataSource connection pooling."); + HikariDataSource ds = new HikariDataSource(); + setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery); + return ds; + } else { + return null; + } + } } diff --git a/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java index c906a79..4456a56 100644 --- a/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java +++ b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/service/relational/PooledDataSourceCreatorsTest.java @@ -14,7 +14,7 @@ public class PooledDataSourceCreatorsTest { // Just to grab driver class name and validation query string private MysqlDataSourceCreator mysqlDataSourceCreator = new MysqlDataSourceCreator(); - + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -22,30 +22,30 @@ public class PooledDataSourceCreatorsTest { @Test public void pooledDataSourceCreationDbcp() { - assertPooledDataSource(new BasicDbcpPooledDataSourceCreator()); + assertPooledDataSource(new BasicDbcpPooledDataSourceCreator()); } - @Test - public void pooledDataSourceCreationTomcatDbcp() { - assertPooledDataSource(new TomcatDbcpPooledDataSourceCreator()); - } + @Test + public void pooledDataSourceCreationTomcatDbcp() { + assertPooledDataSource(new TomcatDbcpPooledDataSourceCreator()); + } + + @Test + public void pooledDataSourceCreationTomcatHighPerformance() { + assertPooledDataSource(new TomcatHighPerformancePooledDataSourceCreator()); + } + + @Test + public void pooledDataSourceCreationHikariCP() { + assertPooledDataSource(new HikariCpPooledDataSourceCreator()); + } - @Test - public void pooledDataSourceCreationTomcatHighPerformance() { - assertPooledDataSource(new TomcatHighPerformancePooledDataSourceCreator()); - } - - @Test - public void pooledDataSourceCreationHikariCP() { - assertPooledDataSource(new HikariCpPooledDataSourceCreator()); - } - private void assertPooledDataSource(PooledDataSourceCreator testCreator) { - DataSource ds = testCreator.create(mockMysqlServiceInfo, null, - mysqlDataSourceCreator.getDriverClassName(mockMysqlServiceInfo), - "select 1"); + DataSource ds = testCreator.create(mockMysqlServiceInfo, null, + mysqlDataSourceCreator.getDriverClassName(mockMysqlServiceInfo), + "select 1"); - Assert.assertNotNull("Failed to create datasource with " + testCreator.getClass().getSimpleName(), ds); + Assert.assertNotNull("Failed to create datasource with " + testCreator.getClass().getSimpleName(), ds); } } From ec5ced8de8fea437acee8e4d2a48e495e3a952c0 Mon Sep 17 00:00:00 2001 From: Joshua Chaitin-Pollak Date: Thu, 12 Mar 2015 03:45:17 -0400 Subject: [PATCH 3/4] hard-code connection parameters in an attempt to get Hikari working --- gradle.properties | 3 +-- .../src/main/java/org/springframework/cloud/Cloud.java | 2 +- .../service/relational/HikariCpPooledDataSourceCreator.java | 4 +++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1c405b7..49db2cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,2 @@ -version=1.1.2.BUILD-SNAPSHOT +version=1.1.2.AL2-SNAPSHOT group=org.springframework.cloud - diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java b/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java index 82aafeb..109f3f1 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java @@ -202,7 +202,7 @@ public class Cloud { * * *

- * If a there is only a single service of a given type (as defined by the {@link ServiceInfo.ServiceLabel} + * If a there is only a single service of a given type (as defined by the {link ServiceInfo.ServiceLabel} * annoation's value of the corresponding {@link ServiceInfo} class), that service is aliased * to the service type. Keys for such properties start in cloud.services.<service-type>. * For example, if there is only a single MySQL service bound to the application, the service properties diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java index 3a9b404..7e8b71d 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java @@ -34,8 +34,10 @@ public class HikariCpPooledDataSourceCreator i if (serviceConnectorConfig == null) { // choose sensible values so that we set max connection pool size to what // free tier services on Cloud Foundry and Heroku allow - target.setPropertyValue("maximumPoolSize", 4); + target.setPropertyValue("maximumPoolSize", 10); target.setPropertyValue("connectionTimeout", 30000); + target.setPropertyValue("idleTimeout", 30000); + target.setPropertyValue("maxLifetime", 55000); } configurer.configure(basicDataSource, (DataSourceConfig)serviceConnectorConfig); } From 23e14747a5135e31413a7e2f75461e143fd375b6 Mon Sep 17 00:00:00 2001 From: Joshua Chaitin-Pollak Date: Thu, 12 Mar 2015 11:09:54 -0400 Subject: [PATCH 4/4] disabled all default configuration settings --- gradle.properties | 1 + .../service/relational/HikariCpPooledDataSourceCreator.java | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 49db2cb..f3e3b15 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ version=1.1.2.AL2-SNAPSHOT group=org.springframework.cloud + diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java index 7e8b71d..a48406b 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/service/relational/HikariCpPooledDataSourceCreator.java @@ -34,10 +34,8 @@ public class HikariCpPooledDataSourceCreator i if (serviceConnectorConfig == null) { // choose sensible values so that we set max connection pool size to what // free tier services on Cloud Foundry and Heroku allow - target.setPropertyValue("maximumPoolSize", 10); - target.setPropertyValue("connectionTimeout", 30000); - target.setPropertyValue("idleTimeout", 30000); - target.setPropertyValue("maxLifetime", 55000); + //target.setPropertyValue("maximumPoolSize", 4); + //target.setPropertyValue("idleTimeout", 55000); } configurer.configure(basicDataSource, (DataSourceConfig)serviceConnectorConfig); }