2013-07-28 69 views
1

所以基本上我試圖讓我的項目在AppFog上運行。數據源信息存儲在一個環境變量中,該變量本質上是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總是空。我試着註冊在resources.groovy一個Spring bean:

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

class ParseDataSource { 
    def grailsAPplication 
    ... 
} 

我還試圖通過持有人得到它:

GrailsApplication grailsApplication = Holders.grailsApplication 

無論哪種方式,爲空,所以我沒有做正確的事情。有任何想法嗎?

+0

使用'new'手動實例化的類不參與bean自動裝配。 – codelark

回答

0

您應該能夠訪問grailsApplication在resources.groovy中注入的方式,前提是您在應用程序中的某個地方注入了bean parseDataSource任何人工製品。

在你的特殊情況下,你需要豆在datasource.groovy。你正在實例化POGO,它不會幫助你向POGO注入grailsApplication。在另一方面,你不能真正注入到POGO像datasource.groovy

def parseDataSource

,因爲它(數據源)爲引導過程中配置對象。

最好的方法仍然是metaClass pogo BootStrap並使grailsApplication可用。伯特有這樣的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') 
} 
+0

在Bootstrap中執行它的問題是數據源已經在那個時候加載,因此更改配置將不起作用 –

+0

Yup在裁剪答案時錯過了該片段。感謝提醒我。:) – dmahapatro

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. 
    } 
} 

如果你想保持自己的類解析爲清晰起見,使值的屬性,並在閱讀在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}" 
    } 
} 

in Datasource。groovy:

def parser = new EnvironmentConfigParser() 

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

好..簡單而合乎邏輯。一個問題,BeanPostProcessor可以在這種情況下有用嗎? – dmahapatro

+0

也許吧,但是在實例化之後你會改變bean的配置,這在這種情況下看起來很迂迴。 – codelark

+0

'java.lang.System.getenv'可以縮寫爲'System.getenv'。請參閱:http://groovy.codehaus.org/Differences+from+Java –