所以基本上我正试图让我的项目在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,所以我没有做正确的事情。有什么想法吗?
答案 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')
}