It turns out that in this configuration, the MULTITENANT setup creates the DATASOURCE_NAME map as follows:
datasources.JOAO=[map of properties]
datasources.PEDRO=[map of properties]
...
datasources.ANTONIO=[map of properties]
These dataSources are collected by the plugin in:
class: DatabaseMigrationGrailsPlugin
And in line 100, there is the following method:
/ code /
private Set getDataSourceNames() {
def dataSources = config.getProperty('dataSources', Map, [:])
if (!dataSources) {
return ['dataSource']
}
Set dataSourceNames = dataSources.keySet()
if (!dataSourceNames.contains('dataSource')) {
dataSourceNames = ['dataSource'] + dataSourceNames
}
return dataSourceNames
}
/ code /
In this method, the if block:
/code/
if (!dataSourceNames.contains('dataSource')) {
dataSourceNames = ['dataSource'] + dataSourceNames
}
/code/
cannot exist in this configuration, as it creates a false entry in the dataSources set and breaks the UPDATE_ALL_ON_START functionality.
In my solution, I simply removed this piece of code (the if condition above).
A second point related to my configuration:
The class DatabaseMigrationTransactionManager also collects the databases to retrieve the TransactionManager linked to each of these tenants.
In line 27 of this class:
/code/
PlatformTransactionManager getTransactionManager() {
String dataSource = this.dataSource ?: "dataSource"
String beanName = "transactionManager"
if (dataSource != "dataSource") {
beanName += "_${dataSource}"
}
applicationContext.getBean(beanName, PlatformTransactionManager)
}
/code/
The method retrieves the transaction managers, and in my configuration, it retrieves by the object's name:
"transactionManager_JOAO"
"transactionManager_PEDRO"
...
"transactionManager_ANTONIO"
However, at some point, the dataSource name becomes degenerated into the following form:
Note that I force the elimination of the 'dataSource' substring in the following if block:
/code/
if (dataSource.startsWith('dataSource')) {
dataSource = dataSource.substring(dataSource.indexOf('_') + 1)
}
/code/
Hello! When activating a MULTITENANT (DATABASE) project, where the configuration is as follows:
SO:
Where I downloaded the source code from the 5.x branch, compiled it, and distributed it to my local Maven repository: /code/
> ./gradlew publishToMavenLocal -x groovydoc
/code/
I added this compilation to my project: build.gradle /code/ buildscript { dependencies { classpath 'org.grails.plugins:database-migration:5.0.0-SNAPSHOT' } } sourceSets { main { resources { srcDir 'grails-app/migrations' } } } ... dependencies { ... implementation('org.grails.plugins:database-migration:5.0.0-SNAPSHOT') } /code/
tenantresolver: org.grails.datastore.mapping.multitenancy.TenantResolver (SUBDOMAIN) application.properties:
Configurações da Aplicação
grails.gorm.reactor.events=false grails.gorm.multiTenancy.mode=DATABASE grails.gorm.multiTenancy.tenantResolverClass=org.grails.datastore.mapping.multitenancy.TenantResolver (SUBDOMAIN) grails.plugin.databasemigration.updateAllOnStart=true grails.plugin.databasemigration.updateOnStartFileName=changelog.groovy grails.plugin.databasemigration.changelogFileName=changelog.groovy
Default
dataSource.url=jdbc:postgresql://localhost:5432/pnd dataSource.driverClassName=org.postgresql.Driver dataSource.username=pnd dataSource.password=pnd dataSource.pooled=true dataSource.jmxExport=true dataSource.dbCreate=none
Cliente: joao
dataSources.JOAO.dbCreate=none dataSources.JOAO.password=joao dataSources.JOAO.url=jdbc:postgresql://localhost:5432/joao dataSources.JOAO.username=joao
Cliente: pedro
dataSources.PEDRO.dbCreate=none dataSources.PEDRO.password=pedro dataSources.PEDRO.url=jdbc:postgresql://localhost:5432/pedro dataSources.PEDRO.username=pedro
Cliente: antonio
dataSources.ANTONIO.dbCreate=none dataSources.ANTONIO.password=antonio dataSources.ANTONIO.url=jdbc:postgresql://localhost:5432/antonio dataSources.ANTONIO.username=antonio
Cliente: jose
dataSources.JOSE.dbCreate=none dataSources.JOSE.password=jose dataSources.JOSE.url=jdbc:postgresql://localhost:5432/jose dataSources.JOSE.username=jose
It turns out that in this configuration, the MULTITENANT setup creates the DATASOURCE_NAME map as follows: datasources.JOAO=[map of properties]
datasources.PEDRO=[map of properties]
...
datasources.ANTONIO=[map of properties]
These dataSources are collected by the plugin in: class: DatabaseMigrationGrailsPlugin
And in line 100, there is the following method: / code / private Set getDataSourceNames() {
def dataSources = config.getProperty('dataSources', Map, [:])
if (!dataSources) {
return ['dataSource']
}
Set dataSourceNames = dataSources.keySet()
if (!dataSourceNames.contains('dataSource')) {
dataSourceNames = ['dataSource'] + dataSourceNames
}
return dataSourceNames
}
/ code /
In this method, the if block: /code/ if (!dataSourceNames.contains('dataSource')) { dataSourceNames = ['dataSource'] + dataSourceNames } /code/ cannot exist in this configuration, as it creates a false entry in the dataSources set and breaks the UPDATE_ALL_ON_START functionality. In my solution, I simply removed this piece of code (the if condition above).
A second point related to my configuration:
The class DatabaseMigrationTransactionManager also collects the databases to retrieve the TransactionManager linked to each of these tenants. In line 27 of this class: /code/ PlatformTransactionManager getTransactionManager() { String dataSource = this.dataSource ?: "dataSource" String beanName = "transactionManager" if (dataSource != "dataSource") { beanName += "_${dataSource}" } applicationContext.getBean(beanName, PlatformTransactionManager) } /code/ The method retrieves the transaction managers, and in my configuration, it retrieves by the object's name: "transactionManager_JOAO" "transactionManager_PEDRO" ... "transactionManager_ANTONIO"
However, at some point, the dataSource name becomes degenerated into the following form:
"dataSource_JOAO" "dataSource_PEDRO" ... "dataSource_ANTONIO"
Where it should simply be:
"JOAO" "PEDRO" ... "ANTONIO"
My homemade solution was to modify the method as follows:
/code/ PlatformTransactionManager getTransactionManager() { String dataSource = this.dataSource ?: "dataSource" String beanName = "transactionManager" if (dataSource.startsWith('dataSource')) { dataSource = dataSource.substring(dataSource.indexOf('') + 1) } if (dataSource != "dataSource") { beanName += "_${dataSource}" } applicationContext.getBean(beanName, PlatformTransactionManager) } /code/
Note that I force the elimination of the 'dataSource' substring in the following if block: /code/ if (dataSource.startsWith('dataSource')) { dataSource = dataSource.substring(dataSource.indexOf('_') + 1) } /code/