在运行时设置数据源值

时间:2013-07-28 19:52:24

标签: grails datasource appfog

所以基本上我正试图让我的项目在AppFog上运行。数据源信息存储在enviornment变量中,该变量本质上是JSON。我的目标是获取这些数据并从中设置我的数据源配置。

以下是我的尝试:

设置数据源配置的代码,这是POGO中的方法。 POGO被实例化,并且在DataSource.groovy的开头调用该方法:

import appfog.ParseDataSource
new ParseDataSource().setConfig()

dataSource {
...
}

class ParseDataSource {

    void setConfig() {
        String env = java.lang.System.getenv("VCAP_SERVICES")
        if (env) {
            def config = JSON.parse(env)
            config = config["mysql-5.1"][0].credentials
            grailsApplication.config.environments.production.dataSource.username = config.username
            grailsApplication.config.environments.production.dataSource.password = config.password
            grailsApplication.config.environments.production.dataSource.url = "jdbc:mysql://" + config.host + ":" + config.port + "/" + config.name
        }
    }
}

问题是grailsApplication始终为null。我已经尝试在resources.groovy中注册一个spring bean:

beans = {
    parseDataSource(appfog.ParseDataSource) {
        grailsApplication = ref('grailsApplication')
    }
}

class ParseDataSource {
    def grailsAPplication
    ...
}

我也试过通过Holders获取它:

    GrailsApplication grailsApplication = Holders.grailsApplication

无论哪种方式,它都是null,所以我没有做正确的事情。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我认为你让这个过于复杂。在构建它的过程中覆盖grails配置对象会导致操作顺序问题导致代码非常脆弱。

直接设置值似乎更直接:

DataSource.groovy中:

def configJson = JSON.parse(java.lang.System.getenv("VCAP_SERVICES"))
def mysqlConfig = configJson["mysql-5.1"][0].credentials

dataSource = {
    production = {
        username = mysqlConfig.username
        // etc.
    }
}

如果为了清楚起见想要在自己的类中继续解析,请创建values属性并在dataSource块中读取它们,而不是尝试将它们放在grails配置对象中:

配置解析:

class EnvironmentConfigParser {
    String username
    String password
    String url

    EnvironmentConfigParser() {
        def configJson = JSON.parse(java.lang.System.getenv("VCAP_SERVICES"))
        def mysqlConfig = configJson["mysql-5.1"][0].credentials

        username = mysqlConfig.username
        password = mysqlConfig.password
        url = "jdbc:mysql://${mysqlConfig.host}:${mysqlConfig.port}/${mysqlConfig.name}"
    }
}

在Datasource.groovy中:

def parser = new EnvironmentConfigParser()

dataSource = {
    production = {
        username = parser.username
        // etc
    }
}

答案 1 :(得分:0)

如果您在应用程序中的任何位置注入bean grailsApplication,您应该能够以您注入resources.groovy的方式访问parseDataSource

在您的特殊情况下,您需要在datasource.groovy中使用该bean。您正在实例化POGO,这不会帮助您向POGO注入grailsApplication。另一方面,您实际上无法将POGO注入datasource.groovy之类的

def parseDataSource

因为它(datasource)是bootstrap期间的配置对象。

最好的方法仍然是metaClass pogo BootStrap并使grailsApplication可用。 Burt的确如此shown it here

我还在考虑BeanPostProcessor在这种情况下是否有用,但我不确定是否会实现每个环境的配置。但是,如果它有助于实现您的业务需求,您可以尝试一下。它通常如下:

//src/groovy
import org.springframework.beans.factory.config.BeanPostProcessor
class DatasourcePostProcessor implements BeanPostProcessor{
    def parseDataSource
    @Override
    Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean
    }

    @Override
    Object postProcessAfterInitialization(Object bean, String beanName) {
        if(beanName == 'dataSource') {
           //Set values to dataSource bean as required
           parseDataSource.setConfig(bean) 
        }
        return bean
    }
}

//resources.groovy
parseDataSource(ParseDataSource){
    grailsApplication = ref('grailsApplication')
}

datasourcePostProcessor(DatasourcePostProcessor){
    parseDataSource = ref('parseDataSource')
}