Tuesday, October 12, 2021

Grails 4: How to load datasource configuration from external file in grails 4 In Grails, how do I put my DB username and password in an external property file

I'm trying to take certain database configurations from variables and put them into an external properties file.

I am writing a grails 4.0.11 application. My datasource written in application.groovy file.

I want to load datasource configuration like username,password,DB from an external file. Is there any way to do it in grails 4+ versions.

Here is my datasource configuration in application.groovy using static database name and other properties like username, password etc:-
hibernate {
    cache {
        queries = false
        use_second_level_cache = true
        use_query_cache = true
    }
}

dataSource {
    pooled = true
    jmxExport = true
    dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
    driverClassName = "org.mariadb.jdbc.Driver"
    username = 'root'
    password = ''
    dbCreate = "update"
    url = "jdbc:mysql://localhost/db2?useUnicode=yes" +
            "&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true" +
            "&useLegacyDatetimeCode=false&serverTimezone=UTC"
    properties = {
        jmxEnabled = true
        initialSize = 5
        maxActive = 50
        minIdle = 5
        maxIdle = 25
        maxWait = 10000
        maxAge = 10 * 60000
        timeBetweenEvictionRunsMillis = 5000
        minEvictableIdleTimeMillis = 60000
        validationQuery = "SELECT 1"
        validationQueryTimeout = 3
        validationInterval = 15000
        testOnBorrow = true
        testWhileIdle = true
        testOnReturn = false
        ignoreExceptionOnPreLoad = true
        jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
        defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED // safe default
        abandonWhenPercentageFull = 100 // settings are active only when pool is full
        removeAbandonedTimeout = 120
        removeAbandoned = true
        logAbandoned = false // causes stacktrace recording overhead, use only for debugging
    }
}
Yes, what we can do that is to put database configurations to a file named db_name.properties under [src/main/webapp] directory with following contents:

db_name=some_data_base_name
db_user=root_user
db_password=some_password

Keeping these information will not load automatically. We have to do something magic to load these information into system.

We can define database configuration for grails 4 in 3 different ways -

1. grails-app/conf/config/application.yml
2. grails-app/conf/application
3. grails-app/conf/application.groovy


So from above list we can easily set our target file to load grails 4 application datasource information because we can write code inside groovy files.

First of all remove any datasource related block from above 2 files and add configuration to grails-app/conf/application.groovy file as early statement with some modification.

Now we will load database information from some properties file. We sill use Properties to load database information from file.

Check below code snippet:
import grails.util.BuildSettings

import java.sql.Connection

grails {
    gorm {
        failOnError = true
        'default' {
            mapping = {
                cache true
                version false
                autoTimestamp false
                id generator:'assigned'
                '*'(cascadeValidate: 'none')
            }
        }
    }
}
Properties ppt = new Properties()
File file = new File(BuildSettings.BASE_DIR.absolutePath + "/src/main/webapp/db.properties")
println("Setting up db name-${file.absolutePath}, exists=${file.exists() ? 1 : 0}")
if (file.exists()) {
    file.getCanonicalFile().withInputStream { InputStream stream ->
        ppt.load(stream)
    }
}
println(ppt)

hibernate {
    cache {
        queries = false
        use_second_level_cache = true
        use_query_cache = true
    }
}

dataSource {
    pooled = true
    jmxExport = true
    dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
    driverClassName = "org.mariadb.jdbc.Driver"
    username = 'root'
    password = ''
    dbCreate = "update"
    url = "jdbc:mysql://localhost/${ppt.get("db.name", "none_db_selected")}?useUnicode=yes" +
            "&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true" +
            "&useLegacyDatetimeCode=false&serverTimezone=UTC"
    properties = {
        jmxEnabled = true
        initialSize = 5
        maxActive = 50
        minIdle = 5
        maxIdle = 25
        maxWait = 10000
        maxAge = 10 * 60000
        timeBetweenEvictionRunsMillis = 5000
        minEvictableIdleTimeMillis = 60000
        validationQuery = "SELECT 1"
        validationQueryTimeout = 3
        validationInterval = 15000
        testOnBorrow = true
        testWhileIdle = true
        testOnReturn = false
        ignoreExceptionOnPreLoad = true
        jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
        defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED // safe default
        abandonWhenPercentageFull = 100 // settings are active only when pool is full
        removeAbandonedTimeout = 120
        removeAbandoned = true
        logAbandoned = false // causes stacktrace recording overhead, use only for debugging
    }
}
In above example I only set database name, you can set anything from that configuration file as I did for database name.

No comments:

Post a Comment