Variables in External config in Grails - grails

I have an external and internal config in my grails application. Here it is:
Config.groovy
grails {
server = 'abc.com'
}
testing {
test1 = ${grails.server}
}
External config:
grails {
server = 'xyz.com'
}
testing {
test1 = ${grails.server}
}
I want to set the value for test1 to be equal to the overridden value of grails.server but what I see is for test1 the original value is of 'grails.server' is assigned and not the overridden value as in external config.
So at the end I get for test1 the original value obtained from the config file
ie.'abc.com' and not the value overidden in the external config i.e.xyz.com.

If you want test1 to refer to a property like grails.server you'd do the following:
grails {
server = 'xyz.com'
}
test {
test1 = ${grails.server}
}
Surround any property name in the ${} expression and it will return the value of that property. Now your question is confusing because you talk about overriding a property, but it's unclear which property are you overriding. If it's grails.server then this answer is fine. But what's also confusing is the use of test because test is an environment, but I think you are trying to make an abstract example that doesn't imply environments.
Updated: How did you specify your external config files? Did you use grails.config.defaults.locations or grails.config.locations? If you used grails.config.locations that will allow your external config to override Config.groovy, but if you used grails.config.defaults.locations then Config.groovy overrides your external configuration.

Related

How to customize an existing Grails plugin functionality, modifying behavior of doWithSpring method

I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.

Maximum recursion getting shared service

I have defined two classes (Environment and ConfigurationReader). Both are registered as shared dependencies.
The Environment class tries get the current environment, but for this, needs read a configuration file via ConfigurationReader.
The sequence diagram is:
The classes are:
class Environment
{
...
public function resolve()
{
$config = DI::getDefault()->getCfg();
$config->getValue('pepe', 'db_name');
}
...
}
class ConfigurationReader
{
...
public function getValue($aConfig, $aKey)
{
$path = $this->getFile($aConfig);
}
protected function getFile($aConfig)
{
$env = DI::getDefault()->getEnv();
$path = 'config/' . $env->getShortName() . '/' . $aConfig . '.yml';
return $path;
}
...
}
And are registered and created in the index.php:
...
$di = new FactoryDefault();
$di->setShared('env', function() use ($di) {
$env = new Services\Environment($di);
$env->resolve();
return $env;
});
$di->setShared('cfg', function() use ($di) {
return new Services\ConfigurationReader($di);
});
$di->getShared('cfg');
$di->getShared('env');
...
So, PHP crash at $config = DI::getDefault()->getCfg(); and says:
PHP Fatal error: Maximum recursion depth exceeded
Any ideas ?
A couple remarks
You're passing the di to the constructor, but end up getting it statically (DI::getDefault())
regarding the infinite loop, it's because cfg needs env who needs cfg who needs env etc.....
To have the framework automatically injecting the DI into your service you should either implement InjectionAwareInterface (https://docs.phalconphp.com/en/latest/reference/di.html#automatic-injecting-of-the-di-itself) or
extend the Component class (If you need event management too, use Plugin instead of Component ). Have a look at this discussion : https://forum.phalconphp.com/discussion/383/plugin-vs-component-what-s-the-difference-
Regarding your use case, you don't give enough context for an exhaustive answer, but I think you could simplify it as:
ConfigService: Unless you use configs from different env namespaces, you should pass the value of $env->getShortName() value to the service constructor (without getting it from the env service). In our apps the env is determined by nginx based on the domain name or other parameters and passed as an environment variable to php. Also, if you don't have hundreds of config files, and your app heavily relies on them, you should read and parse them once on instantiation and store the configs in the service (as associative array, config objects, or whatever you prefer). Add some cache layer to avoid wasting resource parsing all your files on each request. Phalcons provide The Config component to do so. It comes with file adapters (only ini and associative array format but you could easily implement your own yml adapter). If most of your app config relies on configurable values, that will probably be the first component you want to instantiate (or at least declare in the di). It shouldn't dependencies to other services.
EnvService: You can access your config values by calling the config service (If you have it to extend Component, you can do something like $this->cfg->getValue($key)).

Grails 2.4.4 - Set i18n to reference a different directory than /grails-app/i18n

I'm trying to achieve this:
I need grails to reference a different directory for the i18n properties files
I need this directory to be outside of the war file for easy editing while in production
That can be easily achieved by redefining the Grails' message bundle bean, specifying an external, absolute path:
beans = {
messageSource(org.springframework.context.support.ReloadableResourceBundleMessageSource) {
basename = "file:/some/absolute/path/messages"
}
}
If you only need this definition for a specific environment, say, production, you just declare that definition conditionally, like this:
beans = {
if (Environment.current == Environment.PRODUCTION) {
messageSource(org.springframework.context.support.ReloadableResourceBundleMessageSource) {
basename = "file:/some/absolute/path/messages"
}
}
}

Dart has a standard way to externalize settings like Java properties?

I'm looking for the right way to externalize the settings in my server Dart application.
In Java the common way would be a property file. Exists something similar in Dart?
You can just use a Dart script for your settings. No point in using a different format if there is no specific reason.
With a simple import you have it available in a typed way.
When the Resource class is implemented, I would just use a JSON file that is deployed with my program.
You could use a global variables, for example:
DB_URL = 'localhost:5432/mydb';
DB_PASS = 'my_pass';
then you could create a different configuration file for every enviroment. For example, for production you could create a production_config.dart which could contains:
loadConfig() {
DB_URL = '123.123.123.123:5432/mydb';
DB_PASS = 'my_prod_pass';
}
Then in your main function you could call production_config.loadConfig if environment is production, for example:
import 'production_config.dart' as prodConfig;
main(List<String> args) {
var ENV = getEnvFromArgs(args);
if(ENV == 'PROD') {
prodConfig.loadConfig();
}
//do other stuff here
}
In that way if you want to change from development to production you only need to pass an argument to your dart program for example:
dart myprogram.dart -env=PROD
The advantages of this approach are that you don't need to create a separate properties, json or yaml file for this, and you don't need to parse them. Furthermore the properties are type-ckecked.
I like putting configuration in a Dart class like what Günter Zöchbauer was talking about, but there is also the option of using the safe_config package. With this you enter the values in a yaml file. Quoting from the docs:
You define a subclass of Configuration with those properties:
class ApplicationConfiguration extends Configuration {
ApplicationConfiguration(String fileName) :
super.fromFile(File(fileName));
int port;
String serverHeader;
}
Your YAML file should contain those two, case-sensitive keys:
port: 8000
serverHeader: booyah/1
To read your configuration file:
var config = new ApplicationConfiguration("config.yaml");
print("${config.port}"); // -> 8000
print("${config.serverHeader}"); // -> "booyah/1"
See also an example from a setup in Aqueduct.
main() {
var env = const String.fromEnvironment("ENV", defaultValue: "local");
print("Env === " + env);
}
Give environment as option while running Dart App
pub serve --port=9002 --define ENV=dev
References:
http://blog.sethladd.com/2013/12/compile-time-dead-code-elimination-with.html
https://github.com/dart-lang/sdk/issues/27998

Grails' Config.groovy in plugins and dependent apps

I am making both a Grails plugin and several Grails apps that will use the plugin.
I want to define a few properties and give them defaults in the plugin, but allow apps to override their values (optional). This question surrounds the mechanical details of how to wire both plugin and child app alike in this manner.
Say I want my plugin (grails-myplugin) to define the following properties in its Config.groovy:
myplugin {
fizz {
whistles = true // Default for all child apps using this plugin
buzz = 3 // Default for all child apps using this plugin
}
}
grails.plugins.anotherPlugin.widget = 'auto'
grails.plugins.anotherPlugin.foo = '${myplugin.fizz.buzz}-40' // Hence, by default, is '3-40'
Now, I would like a child Grails app, say, myapp.war (which uses grails-myplugin) to override the 2 fizz properties:
// myapp's Config.groovy:
myplugin {
fizz {
// whistles property not defined here so this app uses the
// plugin's default of "true"
// Overrides the plugin's value of 3; this imples
// grails.plugins.somePlugin.foo is '12-40'
buzz = 12
}
}
A few issues here:
Have I placed everything correctly for the desired functionality?
With the above configuration, in grails-myplugin's Config.groovy, I have an error message:
Multiple markers at this line: - The type groovy.lang.MetaClass cannot be resolved. It is indirectly referenced from required .class files. - The type groovy.lang.GroovyObject cannot be resolved. It is indirectly referenced from required .class files.
The fact that I'm getting this error tells me that I'm ether trying to do something that is impossible in Grails, or that I'm just doing it wrong. Ideas?
Here you have how the quartz plugin resolved it:
https://github.com/grails-plugins/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
Take a look at loadQuartzConfig method.
Also be aware that grails plugin exclude some parts of it to avoid problems when installing. It's configured on the plugin file like this:
def pluginExcludes = [
'grails-app/jobs/**',
'src/docs/**',
'web-app/**'
]

Resources