How to get values from properties file in grails? - grails

How to get values from properties file please? and where should I put the file ?
Thank you
EDIT : I'm using grails 3.1.5 And I'm trying to get properties from a job class (quartz)

Either keep your properties directly in Config.groovy file.
Or you can create a .properties file to keep properties and add this file in Config.groovy
grails.config.locations = [ "classpath:grails-app-config.properties"]
and access it anywhere in application using
grailsApplication.config."propertyName"

We have a trait like this:
/**
* Load config from config locations given by property grails.config.locations.
* Based on http://grails.1312388.n4.nabble.com/Grails-3-External-config-td4658823.html
*/
trait ExternalConfigurationLoader implements EnvironmentAware {
#Override
void setEnvironment(Environment environment) {
loadExternalConfigLocations(environment)
}
void loadExternalConfigLocations(Environment environment) {
if (environment) {
def configLocations = findConfigLocationsFromApplicationGroovy()
DefaultResourceLocator resourceLocator = new DefaultResourceLocator()
for (String configLocation in configLocations) {
loadConfigLocation(configLocation, grails.util.Environment.current.name, environment, resourceLocator)
}
}
}
List<String> findConfigLocationsFromApplicationGroovy() {
def applicationGroovy = this.getClass().classLoader.getResource('application.groovy')
if (applicationGroovy) {
def applicationConfiguration = new ConfigSlurper(grails.util.Environment.current.name).parse(applicationGroovy)
return applicationConfiguration.grails.config.locations
}
[]
}
void loadConfigLocation(String configLocation, String currentEnvironmentName, Environment environment, ResourceLocator resourceLocator) {
def configurationResource = resourceLocator.findResourceForURI(configLocation)
if (configurationResource) {
log.debug "External config '$configLocation' found. Loading."
def configSlurper = new ConfigSlurper(currentEnvironmentName)
def config = configSlurper.parse(configurationResource.getURL())
environment.propertySources.addFirst(new MapPropertySource(configLocation, config))
} else {
log.debug "External config '$configLocation' not found."
}
}
}
Then we can add this trait to Application.groovy:
class Application extends GrailsAutoConfiguration implements ExternalConfigurationLoader {
and configure external config files in application.groovy:
grails.config.locations = ["classpath:myapp-config.groovy", "file:dev-config.groovy"]
If using Tomcat, you can then put myapp-config.groovy in Tomcats lib folder.
Note: this variant only supports external config files of type .groovy but you can extend it to support .yml or .properties if you prefer that. Also note that this example has some issues with overriding values from environment block in application.yml, so if you plan to override dataSource you will need to move the default configuration of dataSource from application.yml to application.groovy first.
There is also a plugin in the making that is adding similar support for grails.config.locations. See https://github.com/sbglasius/external-config

Related

using log4j2 configuration builder to initialize logger after startup

I created a custom log4j configuration using ConfigurationBuilder and want to initialize this configuration and start using log4j afterwards, in otherwards without having a configuration file when the project initializes...
according to this page under Reconfigure Log4j Using ConfigurationBuilder with the Configurator, it says -
An alternative to a custom ConfigurationFactory is to configure with the Configurator. Once a Configuration object has been constructed, it can be passed to one of the Configurator.initialize methods to set up the Log4j configuration. Using the Configurator in this manner allows the application control over when Log4j is initialized. However, should any logging be attempted before Configurator.initialize() is called then the default configuration will be used for those log events.
So this should be possible.
This is my code - its almost exactly as it is on that page with a few adjustments -
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(DEBUG);
builder.setConfigurationName("RollingBuilder");
//create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE")
.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout"))
.addAttribute("pattern", "%d{dd/MMM/yyyy HH:mm:ss,SSS}- %c{1}: %m%n");
builder.add(appenderBuilder);
//create a rolling file appender
LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
.addAttribute("pattern", "%d [%t] %-5level: %msg%n");
ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
.addComponent(builder.newComponent("TimeBasedTriggeringPolicy")
.addAttribute("interval", "1")
.addAttribute("modulate", "true"));
ComponentBuilder rolloverStrategy = builder.newComponent("DefaultRolloverStrategy")
.addAttribute("max", "4");
appenderBuilder = builder.newAppender("RollingFile", "RollingFile")
.addAttribute("fileName", "logs/app-info.log")
.addAttribute("filePattern", "logs/app-info-%d{yyyy-MM-dd}--%i.log")
.add(layoutBuilder)
.addComponent(triggeringPolicy)
.addComponent(rolloverStrategy);
builder.add(appenderBuilder);
//create a new logger
builder.add(builder.newLogger("root", Level.DEBUG)
.add(builder.newAppenderRef("RollingFile"))
.addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.DEBUG)
.add(builder.newAppenderRef("RollingFile")));
LoggerContext ctx = Configurator.initialize(builder.build());
However, when I call that code, then do log statements right after, I get the error -
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to show Log4j2 internal initialization logging.
So obviously it thinks I dont have a configuration file... does anyone know how I can get my Logger to recognize this configuration file I created in code?
from Log4j 2 docs
Here is how Log4j finds the available ConfigurationFactories:
A system property named "log4j.configurationFactory" can be set with the name of the ConfigurationFactory to be used.
ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)
can be called with the instance of the ConfigurationFactory to be
used. This must be called before any other calls to Log4j.
A ConfigurationFactory implementation can be added to the classpath
and configured as a plugin in the "ConfigurationFactory" category.
The Order annotation can be used to specify the relative priority
when multiple applicable ConfigurationFactories are found.
In a test I've arranged this:
public class Log4j2Example {
static {
System.setProperty("log4j.configurationFactory", CustomConfigurationFactory.class.getName());
}
private static final Logger LOG = LogManager.getLogger(Log4j2Example.class);
public static void main(String[] args) {
LOG.debug("This Will Be Printed On Debug");
LOG.info("This Will Be Printed On Info");
LOG.warn("This Will Be Printed On Warn");
LOG.error("This Will Be Printed On Error");
LOG.fatal("This Will Be Printed On Fatal");
LOG.info("Appending string: {}.", "Hello, World");
}
}
The ConfigurationFactory implemented:
#Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
#Order(50)
public class CustomConfigurationFactory extends ConfigurationFactory {
---8<----
}
If you set the value of log4j.configurationFactory property before log4j2 start, it's done.
If you prefer using the Configurator instead of using a custom ConfigurationFactory, you have to make sure that your initialization is applied before any call to LogManager.getLogger(...). For instance, you could use a static initialization block
public class MyApplication {
public static final Logger log;
static {
createCustomConfiguration();
log = LogManager.getLogger(MyApplication.class);
}
public static void createCustomConfiguration() {
// your initialization code
}
public static void main(String[] args) {
log.info("Log and roll!");
// do stuff
}
}

encrypt some texts in Grails Config and DataSource files

I need a trusted plugin or a way to encrypt some texts in Grails Config file and the DB passwords in DataSource . as they are sensitive data , such as email username and password.
Is there a powerful and trustful way to do this
Not through a plugin, but it's possible to hide these sensitive config settings away in external files and then set appropriate file permissions on the external files so that they are only accessible to certain users.
Within Config.groovy, there is a setting for external configuration files:
grails.config.locations = [
"classpath:${appName}/externalDb.properties",
...
]
Within DataSource.groovy, a typical arrangement may be:
dataSource {
username = "yourUser"
password = "yourPassword"
...
}
Within your externalDb.properties (which would protected by your filesystem), you would then have the username/password/email/etc. overwritten:
dataSource.username = "prodUser"
dataSource.password = "secret1!"
You can leave the Config.groovy settings in-place and they will only be overwritten if the external config file is found. You could use this to your advantage by using the external files on prod and relying on the Config.groovy settings for your dev environments; you can also apply this logic to having different external config files per environment (we use JNDI at work but I think this built-in grails feature is even easier).
Here is how we had done it
we were defining the password in the Config.Groovy as follows
password = DESCodec.decode("String Returned by the output of encode")
class DESCodec {
def static encode = { String target ->
def cipher = getCipher(Cipher.ENCRYPT_MODE)
return cipher.doFinal(target.bytes).encodeBase64() as String
}
def static decode = { String target ->
def cipher = getCipher(Cipher.DECRYPT_MODE)
return new String(cipher.doFinal(target.decodeBase64())) as String
}
private static getCipher(mode) {
def keySpec = new DESKeySpec(getPassword())
def cipher = Cipher.getInstance("DES")
def keyFactory = SecretKeyFactory.getInstance("DES")
cipher.init(mode, keyFactory.generateSecret(keySpec))
return cipher
}
private static getPassword() {
"testsaltString".getBytes("UTF-8")
}
static void main(args) {
println args
if(args.length == 1) {
println encode(args[0])
} else {
println decode(args[1])
}
}
}
run from the command line
groovy DESCodec.groovy 'password'
to get the ciphertext for the a string, and use the cipher text in
the config files...

Grails : Configuring data source at runtime

I am working on a small grails application. I would like to create a install wizard for the application giving the user the ability to configure data connection settings via a web interface. Is there a way to stall the data connection and configure the datasource while the application is running? I would like to do this while maintaining the ability to leverage GORM/Hibernate for all domain objects. Restarting/reloading the application after configuring the datasource would be ok.
In Config.groovy file add 1 more entry for value of grails.config.locations
in result you will have something like this
grails.config.locations = ["file:${userHome}/.grails/global-config.groovy",
"classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-MyDbconfig.groovy"]
In you application after user enters DB connection parameters write it to file
"file:${userHome}/.grails/${appName}-MyDbconfig.groovy"
in corresponding format. Like follwoing
dataSource{
url = '...'
username = '...'
password = '...'
properties {
...
}
}
save file and restart application.
Since you say the user should be able to configure the datasource via web interface then you should ask for configuration params since maxActive, maxIdle, etc... Once you have all the params you store anywhere you want.
Inside your Grails application:
// grails-app/conf/BootStrap.groovy
import utils.DataSourceConfigurator
class BootStrap {
def init = { servletContext ->
DataSourceConfigurator.configure(servletContext)
}
}
Like this you say to your application that once its ready to run it needs to configure the DataSource first.
package utils
import org.codehaus.groovy.grails.commons.ApplicationAttributes
import org.codehaus.groovy.grails.web.json.JSONObject
class DataSourceConfigurator {
private static JSONObject getDSConfig() {
JSONObject conf = new JSONObject()
// Go find the configuration wherever you stored it from the web interface, parse it and return it.
return conf
}
public static final configure = { servletContext ->
if(!servletContext) {
// Invalid servlet context
return
}
def context = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
def ds = context?.dataSourceUnproxied
if(!ds) {
// There is no datasource available to configure.
return
}
JSONObject config = getDSConfig()
if(!config) {
// No previous configuration saved from web interface.
return
}
ds.setInitialSize(config.initialSize)
ds.setMaxWait(config.maxWait)
ds.setMaxActive(config.maxActive)
ds.setMinIdle(config.minIdle)
ds.setMaxIdle(config.maxIdle)
....
// There are many other variables to configure. Check them by yourself.
}
}
For more information you could check the documentation regarding DataSource configuration: http://docs.grails.org/latest/guide/conf.html#transactionAwareDataSourceProxy

Grails: Initialize variable using Configuration file

I just wanted to know that is it possible to set the value of a variable in Grails controller from the configuration file like config.groovy or some other configuration file?
For instance , my controller is as follows:
class WebsiteController {
def show(){
String user_name = "value to be fetched from configuration file"
}
}
Here, I want to set the value of user_name from the configuration file. I have no idea how to do this.
I have been given this requirement by my senior. I searched online but couldn't find anything relevant. If it is possible, please tell me the approach.
Thanks
Here is an example of properties added to the Config.groovy:
environments {
development {
tipline.email.address="joe#foo.us"
grails.logging.jul.usebridge = true
}
staging {
tipline.email.address="mailinglist#foo.us"
grails.logging.jul.usebridge = true
}
production {
tipline.email.address="mailinglist#foo.us"
grails.logging.jul.usebridge = false
// TODO: grails.serverURL = "http://www.changeme.com"
}
}
To access them in your code:
println("Email :"+grailsApplication.config.tipline.email.address)
Properties are properties =)
Properties properties = new Properties()
File propertiesFile = new File('test.properties')
propertiesFile.withInputStream {
properties.load(it)
}
def runtimeString = 'a'
assert properties."$runtimeString" == '1'
assert properties.b == '2'
Taken from Get values from properties file using Groovy
Another possibility is to inject parameters into the controller by using a property override configuration:
// Config.groovy:
website.user = "me"
beans {
'<replace by package>.WebsiteController' {
userName = website.user
}
}
// Controller:
class WebsiteController {
String userName
def show(){
//.. use userName ..
}
}
In this case you don't need grailsApplication and you don't hard code the configuration path in the Controller. Less dependencies make testing easier. :)

Grails domain class properties from properties file

In my grails application I want to read some values from properties file and set it to Grails Domain class static property at startup.
Example
Class A{
static myValues="1,2";
}
class B{
static myValues="2,3";
}
In the above example I have directly given the inputs..Instead of that I want to read it from one config.properties file which will have the following
A=1,2
B=2,3
Is it possible to do that in grails.Help me please.
If you put config.properties in grails-app/conf then it'll be in the classpath and this code in grails-app/conf/BootStrap.groovy will load the properties and set the values:
class BootStrap {
def init = { servletContext ->
def props = new Properties()
def cl = Thread.currentThread().contextClassLoader
props.load cl.getResourceAsStream('config.properties')
props.each { key, value ->
def clazz = Class.forName(key, true, cl)
clazz.myValues = value
}
}
}
Obviously you'll need to check that the properties file is available, that the classes, exist, etc.

Resources