Converting Java -> Grails ... How do I load these properties? - grails

I'm converting a Java web app to Grails (1.2.1). In my Java app, I have a singleton that loads properties from a ".properties" file. I've seen I can put that loading into the "Config.groovy" conf file. If my properties are loaded in Config.groovy, how do I load them in my Java file? Here is how I'm doing it when the Config was loaded in java ...
Long interval = ConfigSingleton.getInstance().getGlobalCacheRefreshInterval();
Thanks, - Dave

Adapted from the Grails User Guide:
You can add your own configuration in grails-app/conf/Config.groovy, for example:
globalCacheRefreshInterval = 120
Then later in your application you can access these settings in one of two ways. The most common is via the GrailsApplication object, which is available as a variable in controllers and tag libraries:
Long interval = grailsApplication.config.globalCacheRefreshInterval
The other way involves getting a reference to the ConfigurationHolder class that holds a reference to the configuration object:
def config = org.codehaus.groovy.grails.commons.ConfigurationHolder.config
Long interval = config.globalCacheRefreshInterval
If you want to acess this configuration from a Java class, you can use:
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
...
Map config = ConfigurationHolder.getFlatConfig();
Long interval = (Long) config.get("globalCacheRefreshInterval");
Attention for the correct type in your Config.groovy. In the case above, your configuration property must be defined as a Long:
globalCacheRefreshInterval = 120L

You should also checkout the ConfigSlurper class (this is what grails uses to load its config file).

Dave if what you need is to load the properties file as it is without having to move them to the Config.groovy manually, you can the following inside the Config.groovy file:
grails.config.locations = [
"file:" + "/pathWhereFileLives/fileName.properties"
]
This will load all the properties you have in the file in the Grails configuration class. Something to be aware of is that if you have a property in the Config.groovy and the properties file with the same name, the one from the properties file will override the value of the one from Config.groovy
You can find more information about the Grails external configurations here.

Related

How to Modify Grails 5 Configuration by Adding Groovy Files

I have a large number of Grails 2.5 applications that I want to upgrade to Grails 5, but have been unable to get the configuration to work. In particular, I want my plugin to set up the data source and Spring Security configuration as it did in Grails 2.5.
In my Grails 2.5 applications, I was able to add files to the configuration by adding this code to the top of Config.groovy.
if (!grails.config.location || !(grails.config.location instanceof List)) {
grails.config.location = []
}
grails.config.location << ["classpath:jcc-server-config.properties"]
grails.config.location << ["classpath:SecurityConfig.groovy"]
But this doesn't work in Grails 5. I've tried adding an application.groovy file, but everything defined in the application.yml seems to be set in stone. Has anybody found a way to add a Groovy file to the Grails configuration that will override or add to the settings in application.yml? YAML will not do because I have logic embedded in the configuration to make it work correctly in different environments.
Thanks.
Did you remember to include the external-config dependency? i.e.
implementation 'dk.glasius:external-config:3.0.0'
Re' your question on accessing config values this way, there should be no difference, in my apps I get to the config either via grailsApplication.config, or if grailsApplication isn't immediately available(e.g. classes under src), then with Holders, i.e. Holders.grailsApplication.config.

Add logging to an external pluggable script

As described in Can't call one closure from another, I am using a pluggable script from within a Grails app.
Unfortunately, I've found that I can't use log4j from within these scripts. I am forced to use println.
I tried using
import org.apache.commons.logging.LogFactory
def Log log = LogFactory.getLog(getClass())
but I got no output. When I print out the result of the call to getClass(), I get something like
myscript$_run_closure5
So I'm thinking the issue is that there is no configuration in my Grails Config.groovy file for this class.
Is there a way for me to programmatically add these pluggable scripts to the log4j configuration? Keep in mind that I do not know in advance what the names of the scripts are, so this has to happen at runtime.
Consider the following code:
import org.apache.log4j.Logger
// ...
Logger log = Logger.getLogger('MyPlugin')
new File( grailsApplication.config.externalFiles ).eachFile { file ->
Binding binding = new Binding()
binding.variables.log = log
GroovyShell shell = new GroovyShell(binding)
shell.evaluate(file)
strategies.put( binding.variables.key, binding.variables )
}
Explanation:
It is not obligatory to pass class name to getLogger, it can be actually any string. You just need to make sure that this string is matched in log4j.properties of the main program.
You pass once created log to plugin scripts via binding variable "log". Then plugin scripts can access it simply as log.info('test123')
My personal recommendation would be to use logback instead of log4j. Both libraries were developed by the same guy and it is stated that logback supersedes log4j.

Share config between two grails apps that share a common plugin

We will have two apps that both need to use the same services/utilities/code/configuration.
We are using grailsApplication.config.* to configure things like URLs to external services. These are different depending on whether the app is running in dev/test/qa/staging/prod, so we have used the environments section in Config.groovy. We'll need the same URLs/environments configured for both applications.
In order to avoid duplication, we are trying to build a plugin that will hold all the shared stuff. This works for services and such, but Grails plugins do not include Config.groovy, resources.groovy so all the URL configuration and such can't be put in Config.groovy in the plugin.
Is there a nice way to put that configuration in a single place and have it available for both apps?
Perhaps we could put it in some place in the plugin and "import" it into the Config.groovy of both apps?
The grails.config.locations definition for external configuration files can include java.lang.Class objects to load configuration from pre-compiled Groovy scripts, as well as file: or classpath: URLs to parse Groovy or .properties files at runtime. So you should be able to create a configuration file in the plugin under src/groovy
{plugin}/src/groovy/com/example/CommonConfiguration.groovy
package com.example
environments {
production {
...
}
development {
...
}
}
and then in the applications' Config.groovy files include this class in grails.config.locations
grails.config.locations = [com.example.CommonConfiguration]
However this does mean that when the plugin's CommonConfiguration and the host app's Config.groovy both specify a value for the same property, the plugin would win. To redress the balance, you'd need to put a second external in grails.config.locations (which could be another Class or a URL)
grails.config.locations = [com.example.CommonConfiguration,
"file:app-config.groovy"]
and put app configuration in there (as later externals override earlier ones).
Given that you want to embed the configuration within the plugin you will need to make your plugin smart enough to read it's own configuration and merge that into the containing applications config. The following is based on Grails 1.3.7. The configuration holder may have changed since then (2.0 did a lot of house cleaning) but I am sure you can figure that part out. This example assumes that there is a configuration file called grails-app/conf/MyPluginConfig.groovy inside your plugin.
Inside your /MyPlugin.groovy you will add this merge of your configuration in the doWithSpring closure.
def doWithSpring = {
// get the current application configuration
def currentConfig = org.codehaus.groovy.grails.commons.ConfigurationHolder.config
GroovyClassLoader classLoader = new GroovyClassLoader(getClass().classLoader)
// get the plugin configuration
def pluginConfig = new ConfigSlurper(grails.util.GrailsUtil.environment).parse(classLoader.loadClass('MyPluginConfig'))
// merge the configurations
pluginConfig.merge(currentConfig)
// set the application configuration to the merged configuration
org.codehaus.groovy.grails.commons.ConfigurationHolder.config = pluginConfig
}
That's it in a nutshell. Hope this helps.
Also, take note that you can still override the values in your containing application because of the way the merge is done. The application configuration is merged into the plugin configuration. If the containing application defines something it will override the plugins value.

grails properties

I am having some big troubles using external properties with grails.
In config.groovy I have:
grails.config.locations = ["file:grails-app/conf/config.properties"]
this is my config.properties file:
test.prop.test=this is a test
and this is in my code:
println grailsApplication.config["test.prop.test"]
Has anyone any idea why this does not work?
If you want to access the config options using single string keys that include dots, as opposed to the multi-level grailsApplication.config.test.prop.test then you need to use flatConfig instead:
grailsApplication.flatConfig["test.prop.test"]
in external config
this.is.myname="My name is Hello!"
in your controller
import org.codehaus.groovy.grails.commons.ConfigurationHolder
String name= ConfigurationHolder.config.this.is.myname;
this is work for me...with using grails 2.1.1

How to use an external service as a source for Grails app configuration?

Section 3.4 of Grails documentation says that Grails app can be configured from an external source:
grails.config.locations = [
"classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy" ]
Also, it is possible to load config by specifying a class that is a config script:
grails.config.locations = [com.my.app.MyConfig]
My questions are:
Could you please give an example of how MyConfig class implementation could look like? It is not quite clear from the documentation.
If I want to use some external JSON REST service as a source for my config data, how can this be implemented?
Answer for second question: you can do that in BootStrap.groovy init closure, because basically, it allows you to execute any code:
// Inject grails app
def grailsApplication
def init = { servletContext ->
def externalValue = getItUsingRest(someUrl)
grailsApplication.config.my.custom.var = externalValue
}
Depending on version of grails you are using, you might need to use
org.codehaus.groovy.grails.commons.ConfigurationHolde.config
to get to config instead.
Your application configuration can actually be a Groovy script. So any class which looks like your Config.groovy can act as a configuration class. In our projects we tend to keep the configuration outside the grails application so that the application can be configured without recompiling everything.
Maybe this post of mine will give you a hint on how to use and load external configuration files.

Resources