minor additions to Flyway support...ability to optionally upgrade databases on application startup

This commit is contained in:
Vishwas Babu AJ
2013-04-03 21:56:08 +05:30
parent af8219de29
commit 2ae603dcc2
10 changed files with 197 additions and 43 deletions
@@ -36,6 +36,7 @@ CREATE TABLE `tenants` (
`schema_server_port` varchar(10) NOT NULL DEFAULT '3306', `schema_server_port` varchar(10) NOT NULL DEFAULT '3306',
`schema_username` varchar(100) NOT NULL DEFAULT 'root', `schema_username` varchar(100) NOT NULL DEFAULT 'root',
`schema_password` varchar(100) NOT NULL DEFAULT 'mysql', `schema_password` varchar(100) NOT NULL DEFAULT 'mysql',
`auto_update` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
+3
View File
@@ -191,6 +191,9 @@ task deployPentahoReports() {
war { war {
it.dependsOn deployPentahoReports it.dependsOn deployPentahoReports
from ('../mifosng-db/migrations') {
into "WEB-INF/classes/sql"
}
} }
license { license {
@@ -15,10 +15,11 @@ public class MifosPlatformTenant {
private final String schemaUsername; private final String schemaUsername;
private final String schemaPassword; private final String schemaPassword;
private final String timezoneId; private final String timezoneId;
private final boolean autoUpdateEnabled;
public MifosPlatformTenant(final Long id, final String name, final String schemaName, final String schemaServer, public MifosPlatformTenant(final Long id, final String name, final String schemaName, final String schemaServer,
final String schemaServerPort, final String schemaUsername, final String schemaPassword, String timezoneId) { final String schemaServerPort, final String schemaUsername, final String schemaPassword, String timezoneId,
final boolean autoUpdateEnabled) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.schemaName = schemaName; this.schemaName = schemaName;
@@ -27,7 +28,14 @@ public class MifosPlatformTenant {
this.schemaUsername = schemaUsername; this.schemaUsername = schemaUsername;
this.schemaPassword = schemaPassword; this.schemaPassword = schemaPassword;
this.timezoneId = timezoneId; this.timezoneId = timezoneId;
this.autoUpdateEnabled = autoUpdateEnabled;
}
public String databaseURL() {
String url = new StringBuilder("jdbc:mysql://").append(schemaServer).append(':').append(schemaServerPort).append('/')
.append(schemaName).toString();
return url;
} }
public Long getId() { public Long getId() {
@@ -39,15 +47,7 @@ public class MifosPlatformTenant {
} }
public String getSchemaName() { public String getSchemaName() {
return schemaName; return this.schemaName;
}
public String getSchemaServer() {
return schemaServer;
}
public String getSchemaServerPort() {
return schemaServerPort;
} }
public String getSchemaUsername() { public String getSchemaUsername() {
@@ -57,9 +57,13 @@ public class MifosPlatformTenant {
public String getSchemaPassword() { public String getSchemaPassword() {
return schemaPassword; return schemaPassword;
} }
public String getTimezoneId() { public String getTimezoneId() {
return timezoneId; return timezoneId;
} }
public boolean isAutoUpdateEnabled() {
return this.autoUpdateEnabled;
}
} }
@@ -0,0 +1,65 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.core.domain;
public class Tenant {
private final Long id;
private final String name;
private final String schemaName;
private final String schemaServer;
private final String schemaServerPort;
private final String schemaUsername;
private final String schemaPassword;
private final String timezoneId;
public Tenant(final Long id, final String name, final String schemaName, final String schemaServer,
final String schemaServerPort, final String schemaUsername, final String schemaPassword, String timezoneId) {
this.id = id;
this.name = name;
this.schemaName = schemaName;
this.schemaServer = schemaServer;
this.schemaServerPort = schemaServerPort;
this.schemaUsername = schemaUsername;
this.schemaPassword = schemaPassword;
this.timezoneId = timezoneId;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getSchemaName() {
return schemaName;
}
public String getSchemaServer() {
return schemaServer;
}
public String getSchemaServerPort() {
return schemaServerPort;
}
public String getSchemaUsername() {
return schemaUsername;
}
public String getSchemaPassword() {
return schemaPassword;
}
public String getTimezoneId() {
return timezoneId;
}
}
@@ -0,0 +1,13 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.core.service;
public interface ITenantUpgradeService {
void upgradeAllTenants();
}
@@ -0,0 +1,46 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.core.service;
import java.util.List;
import javax.annotation.PostConstruct;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.googlecode.flyway.core.Flyway;
/**
* A JDBC implementation of {@link TenantDetailsService} for loading a tenants
* details by a <code>tenantIdentifier</code>.
*/
@Service
public class TenantUpgradeService implements ITenantUpgradeService {
private final TenantDetailsService tenantDetailsService;
@Autowired
public TenantUpgradeService(TenantDetailsService detailsService) {
this.tenantDetailsService = detailsService;
}
@Override
@PostConstruct
public void upgradeAllTenants() {
List<MifosPlatformTenant> tenants = tenantDetailsService.findAllTenants();
for (MifosPlatformTenant tenant : tenants) {
if (tenant.isAutoUpdateEnabled()) {
Flyway flyway = new Flyway();
flyway.setDataSource(tenant.databaseURL(), tenant.getSchemaUsername(), tenant.getSchemaPassword());
flyway.setLocations("sql");
flyway.migrate();
}
}
}
}
@@ -27,7 +27,7 @@ import org.springframework.stereotype.Service;
*/ */
@Service @Service
public class TomcatJdbcDataSourcePerTenantService implements DataSourcePerTenantService { public class TomcatJdbcDataSourcePerTenantService implements DataSourcePerTenantService {
private final Map<Long, DataSource> tenantToDataSourceMap = new ConcurrentHashMap<Long, DataSource>(1); private final Map<Long, DataSource> tenantToDataSourceMap = new ConcurrentHashMap<Long, DataSource>(1);
private final DataSource tenantDataSource; private final DataSource tenantDataSource;
@@ -61,24 +61,23 @@ public class TomcatJdbcDataSourcePerTenantService implements DataSourcePerTenant
// see // see
// http://www.tomcatexpert.com/blog/2010/04/01/configuring-jdbc-pool-high-concurrency // http://www.tomcatexpert.com/blog/2010/04/01/configuring-jdbc-pool-high-concurrency
StringBuilder jdbcUrlBuilder = new StringBuilder("jdbc:mysql://").append(tenant.getSchemaServer()).append(':') String jdbcUrl = tenant.databaseURL();
.append(tenant.getSchemaServerPort()).append('/').append(tenant.getSchemaName());
PoolConfiguration poolConfiguration = new PoolProperties(); PoolConfiguration poolConfiguration = new PoolProperties();
poolConfiguration.setDriverClassName("com.mysql.jdbc.Driver"); poolConfiguration.setDriverClassName("com.mysql.jdbc.Driver");
poolConfiguration.setName(tenant.getSchemaName() + "_pool"); poolConfiguration.setName(tenant.getSchemaName() + "_pool");
poolConfiguration.setUrl(jdbcUrlBuilder.toString()); poolConfiguration.setUrl(jdbcUrl);
poolConfiguration.setUsername(tenant.getSchemaUsername()); poolConfiguration.setUsername(tenant.getSchemaUsername());
poolConfiguration.setPassword(tenant.getSchemaPassword()); poolConfiguration.setPassword(tenant.getSchemaPassword());
poolConfiguration.setInitialSize(5); poolConfiguration.setInitialSize(5);
//poolConfiguration.setMaxActive(5); // poolConfiguration.setMaxActive(5);
//poolConfiguration.setMinIdle(1); // poolConfiguration.setMinIdle(1);
//poolConfiguration.setMaxIdle(4); // poolConfiguration.setMaxIdle(4);
//poolConfiguration.setSuspectTimeout(60); // poolConfiguration.setSuspectTimeout(60);
//poolConfiguration.setTimeBetweenEvictionRunsMillis(30000); // poolConfiguration.setTimeBetweenEvictionRunsMillis(30000);
//poolConfiguration.setMinEvictableIdleTimeMillis(60000); // poolConfiguration.setMinEvictableIdleTimeMillis(60000);
poolConfiguration.setTestOnBorrow(true); poolConfiguration.setTestOnBorrow(true);
poolConfiguration.setValidationQuery("SELECT 1"); poolConfiguration.setValidationQuery("SELECT 1");
@@ -7,6 +7,7 @@ package org.mifosplatform.infrastructure.security.service;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource; import javax.sql.DataSource;
@@ -33,23 +34,17 @@ public class JdbcTenantDetailsService implements TenantDetailsService {
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
} }
@Override
public MifosPlatformTenant loadTenantById(final String tenantIdentifier) {
try {
TenantMapper rm = new TenantMapper();
String sql = "select id, name, schema_name as schemaName, schema_server as schemaServer, schema_server_port as schemaServerPort, "
+ " schema_username as schemaUsername, schema_password as schemaPassword , timezone_id as timezoneId "
+ " from tenants t where t.identifier like ?";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { tenantIdentifier });
} catch (EmptyResultDataAccessException e) {
throw new InvalidTenantIdentiferException("The tenant identifier: " + tenantIdentifier + " is not valid.");
}
}
private static final class TenantMapper implements RowMapper<MifosPlatformTenant> { private static final class TenantMapper implements RowMapper<MifosPlatformTenant> {
private StringBuilder sqlBuilder = new StringBuilder(
"id, name, schema_name as schemaName, schema_server as schemaServer, schema_server_port as schemaServerPort, auto_update as autoUpdate, ")//
.append(" schema_username as schemaUsername, schema_password as schemaPassword , timezone_id as timezoneId ")//
.append(" from tenants t");//
public String schema() {
return sqlBuilder.toString();
}
@Override @Override
public MifosPlatformTenant mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { public MifosPlatformTenant mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
@@ -60,9 +55,33 @@ public class JdbcTenantDetailsService implements TenantDetailsService {
String schemaServerPort = rs.getString("schemaServerPort"); String schemaServerPort = rs.getString("schemaServerPort");
String schemaUsername = rs.getString("schemaUsername"); String schemaUsername = rs.getString("schemaUsername");
String schemaPassword = rs.getString("schemaPassword"); String schemaPassword = rs.getString("schemaPassword");
String timezoneId =rs.getString("timezoneId"); String timezoneId = rs.getString("timezoneId");
boolean autoUpdateEnabled = rs.getBoolean("autoUpdate");
return new MifosPlatformTenant(id, name, schemaName, schemaServer, schemaServerPort, schemaUsername, schemaPassword ,timezoneId);
return new MifosPlatformTenant(id, name, schemaName, schemaServer, schemaServerPort, schemaUsername, schemaPassword,
timezoneId, autoUpdateEnabled);
} }
} }
@Override
public MifosPlatformTenant loadTenantById(final String tenantIdentifier) {
try {
TenantMapper rm = new TenantMapper();
String sql = "select " + rm.schema() + " where t.identifier like ?";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { tenantIdentifier });
} catch (EmptyResultDataAccessException e) {
throw new InvalidTenantIdentiferException("The tenant identifier: " + tenantIdentifier + " is not valid.");
}
}
@Override
public List<MifosPlatformTenant> findAllTenants() {
TenantMapper rm = new TenantMapper();
String sql = "select " + rm.schema();
List<MifosPlatformTenant> mifosPlatformTenants = jdbcTemplate.query(sql, rm, new Object[] {});
return mifosPlatformTenants;
}
} }
@@ -5,10 +5,14 @@
*/ */
package org.mifosplatform.infrastructure.security.service; package org.mifosplatform.infrastructure.security.service;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant; import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
public interface TenantDetailsService { public interface TenantDetailsService {
MifosPlatformTenant loadTenantById(String tenantId); MifosPlatformTenant loadTenantById(String tenantId);
List<MifosPlatformTenant> findAllTenants();
} }
@@ -13,7 +13,7 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="tenantUpgradeService">
<property name="dataSource" ref="tenantAwareDataSource" /> <property name="dataSource" ref="tenantAwareDataSource" />
<property name="persistenceUnitName" value="jpa-pu" /> <property name="persistenceUnitName" value="jpa-pu" />
<property name="jpaVendorAdapter"> <property name="jpaVendorAdapter">