grails 3 - Update grails config during Plugin "doWithApplicationContext" - grails

I've got a plugin that, during startup, reads some properties from the applications Config file, creates some domain objects and then needs to update the configuration with some additional information. However, it seems that the config object available during doWithApplicationContext is not the actual grailsApplication.config object.
For instance, attempting to do something straightforward in the MyPluginGrailsPlugin.groovy file like:
void doWithApplicationContext() {
grailsApplication.config.put('test', 'testValue')
}
does not update the config.
If this plugin is incldued in an application, at any point after startup, grailsApplication.config.getProperty('test') will return null.
How does one go about updating the config map during plugin startup?
NOTE: In grails 2, this used to work.

With this code snippet in MyPluginGrailsPlugin.groovy's doWithApplicationContext, new properties were successfully added into the application's config object.
ConfigObject myConfigObject = new ConfigSlurper().parse(props)
PropertySource propertySource = new MapPropertySource('grails.plugins.myPlugin', [:] << myConfigObject)
def propertySources = grailsApplication.mainContext.environment.propertySources
propertySources.addFirst propertySource
As an additional note: in doWithApplicationContext in my plugin, changing the config object like this worked in Grails 2 and no longer works in Grails 3.
grailsApplication.config.merge(myConfigObject)
grailsApplication.configChanged()

Related

“Inject environment variables” Jenkins 2.0

I recently upgraded to Jenkins 2.0.
I’m trying to add a build step to a jenkins job of "Inject environment variables" along the lines of this SO post, but it’s not showing up as an option.
Is this not feature in Jenkins 2.0 (or has it always been a separate plugin)? Do I have to install another plugin, such as Envinject?
If you are using Jenkins 2.0
you can load the property file (which consists of all required Environment variables along with their corresponding values) and read all the environment variables listed there automatically and inject it into the Jenkins provided env entity.
Here is a method which performs the above stated action.
def loadProperties(path) {
properties = new Properties()
File propertiesFile = new File(path)
properties.load(propertiesFile.newDataInputStream())
Set<Object> keys = properties.keySet();
for(Object k:keys){
String key = (String)k;
String value =(String) properties.getProperty(key)
env."${key}" = "${value}"
}
}
To call this method we need to pass the path of property file as a string variable
For example, in our Jenkins file using groovy script we can call like
path = "${workspace}/pic_env_vars.properties"
loadProperties(path)
Please ask me if you have any doubt

How can I reload the message updates in the messages.properties using Grails Localization plugin?

In Grails Localization plugin documentation, it says:
If you distribute your finished application in the form of a war file, then unless the target application server unzips the war file on installation, the localizations plugin will be unable to automatically load (or subsequently 'import') the properties files from within the war file.
In order to walk around to reload all the message updates using war, I use the following code in BootStrap.groovy.
import org.grails.plugins.localization.Localization
class BootStrap {
def init = { servletContext ->
Localization.reload()
}
}
This code does help me that whenever the app deploys to a Tomcat server, the message updates will apply. But as more and more releases get deployed, the localization table's id number increases automatically.
So I tried "truncate table" in my code to resolve the issue. In BootStrap.groovy:
import org.grails.plugins.localization.Localization
class BootStrap {
def sessionFactory
def init = { servletContext ->
sessionFactory.getCurrentSession().createSQLQuery('truncate table localization').executeUpdate()
Localization.load()
}
}
Using this code leads the run-app fails, because sometime, the truncate table happens in the middle of the load process, not before!
Did you try to execute it as a thread and force waiting for the end of that process?
Localization plugin has a LocalizationsBootStrap.groovy. Writing code in BootStrap.groovy leads to a race between two of the BootStrap files.
We can just do nothing in the BootStrap.groovy,but override the LocalizationsBootStrap.groovy by createing it under conf:
import org.grails.plugins.localization.*
class LocalizationsBootStrap {
def sessionFactory
def init = { servletContext ->
sessionFactory.getCurrentSession().createSQLQuery('truncate table localization').executeUpdate()
Localization.load()
}
}

How to tell Grails application which environment it is in?

I would like to load Environment specific configurations in my grails application so that depending on which JVM the grails application is running on, I can point to that environment specific urls. In my case, I have 4 different environments to work with (instead of the default 3 that grails app assumes) when my app goes from dev to prod.
My JVMs all have a System property defined that, when I do "System.getProperty()", tell me which environment that application is running on.
My question is, what is the best place to check and load the environment-specific configurations during run-time? Inside BootStrap.groovy? I do not have the option to build my war file using command line or grails {env_name} war.
Thanks.
Set the variable grailsEnv as a environment Java variable for Tomcat below is an example:
set CATALINA_OPTS=%CATALINA_OPTS% -Xms256m -Xmx1024m -Dgrails.env=development
On a grails command line you add the environment variable:
grails run-app -Dgrails.env=stage
You can use check the environment variable like this:
if (grails.util.Environment.current.name == "development") {
UsageCodeDefinition ucd = new UsageCodeDefinition()
ucd.setDescription("UFARSFileUpload Upload Development")
ucd.setFiscalYear("12-13")
ucd.setInstructions("Welcome to UFARSFileUpload Development were Open")
ucd.save(failOnError: true)
}
You can use the Enumerated values instead of the name variable but if you use custom environmental values then they are mapped to the enumeration custom and using the name works to distinguish between the custom values.
if (grails.util.Environment.current == grails.util.Environment.DEVELOPMENT) {
Without setting the JVM startup parameter:
-Dgrails.env=whatever
Your grails app will use the value set in
<yourapp>/WEB-INF/classes/application.properties
There will be a value set like this:
grails.env=development
This default environment value is determined by what options are used when building the war. You can build the war with
-Dgrails.env=development war
Then the application.properties will have grails.env=development, if you leave that off, it defaults to grails.env=production
As far as your question, you are not specific about what is being configured to use "environment specific urls". And it is not clear how you are storing these environment specific urls. If, for example, the URL variable is a member variable of a Grails service and you are storing the environment specific URLs in the Config.groovy, then you could
import grails.util.Environment
...
//inject the GrailsApplication Configuration in Config.groovy
def grailsApplication
//Hold the URL value from Config.groovy
String environmentUrl
...
Environment current = Environment.getCurrent()
if(Environment.PRODUCTION == current) {
environmentUrl = grailsApplication.config.PRODUCTION_URL
} else {
environmentUrl = grailsApplication.config.DEVELOPMENT_URL
}
Where Config.groovy has
PRODUCTION_URL = "http://blah.com/blah/"
DEVELOPMENT_URL = "http://blah.dev/blah"
Hope that helps.
If you have a System property available that tells you what environment you're in you can simply add if statements or a switch statement in your Config.groovy file, like this:
if (System.getProperty("foo") == "myTestEnvironment") {
myConfigSetting = "test"
} else if (System.getProperty("foo") == "myProductionEnvironment") {
myConfigSetting = "production"
}
This solution also works in other config files under grails-app/conf
Grails config files are parsed using groovy ConfigSlurper so you can put executable code in there without a problem.
Sorry this is way late, but another way is to inject a configuration property in BootStrap.groovy.
For Example:
if (currentEnv == Environment.DEVELOPMENT) {
...
grailsApplication.config.some.property = DEVELOPMENT_ENVRIONMENT
...
}
else if (currentEnv == Environment.TEST) {
...
grailsApplication.config.some.property = TEST_ENVIRONMENT
...
}
I have used this recently and it works really well. We are using Grails 2.5.2
As an addendum to the other answers:
You can use Environment.isDevelopmentMode() or in a groovier way Environment.developmentMode to check if the environment is set to development. This is useful when you take the aproach of only modifying settings for development on your code where production settings are default.

How to configure the Grails embedded Tomcat to use the file based security realm

I need to create a user/password for the embedded Tomcat, since my app uses JAAS. I found some examples, but they refer to older versions of Grails. I am using 2.3.5.
The link above advises to create users via events, in a Grails script:
eventConfigureTomcat = {tomcat ->
println "Loading users"
tomcat.addUser("user", "password")
tomcat.addRole("user", "group")
}
But when I create a Grails script in the scripts folder, it is pre-populated with this:
includeTargets << grailsScript("_GrailsInit")
target(_Events: "The description of the script goes here!") {
// TODO: Implement script here
}
setDefaultTarget(_Events)
How to add the user in the new version of Grails? Thanks!
You have to add the event in the file scripts/_Events.groovy. If it's not there, just create it. If it's there, just append your event to the existing content.
Make sure to execute stop-app and run-app so that the event is processed. When executing run-app, you should see the output of your println-statement.

Get custom grails plugin version from within the plugin

I have a Grails plugin that I've written that has its version set using set-version within our continuous integration environment. While building, I'd like to programmatically output the version from within "eventCompileEnd" event hook. So, for my Grails app I can just get the "app.version" metadata but plugin versions are set in the GrailsPlugin.groovy file in the root of the plugin. Is there any way to access that value? Here's the version info I'm referring to:
class MyUtilityGrailsPlugin {
// the plugin version
def version = "4.6.8"
// the version or versions of Grails the plugin is designed for
def grailsVersion = "2.1 > *"
...etc.
You can use below eventCompileEnd event in _Events.groovy of the app to get the name and version of all the plugins used in the app from GantBinding which is by default available to the post compile event. You can filter your plugin info based on the name:
//scripts/_Events.groovy
eventCompileEnd = {msg->
msg.supportedPluginInfos.each{println "${it.name} - ${it.version}"}
}
If you want to access the plugin info from any where else (for example: BootStrap) using applicationContext would be the simplest approach. Something like below would be useful:
//Bootstrap.groovy
def grailsApplication
def init = { servletContext ->
grailsApplication.mainContext.getBean('pluginManager')
.allPlugins.each{plugin->
println "Plugin Info ${plugin.name} - ${plugin.version}"
}
}
In your case, appCtx will not be available in post compile event, so you have to depend on GantBinding.
I found that version information can be retrieved from within an event hook for that plugin by doing this:
pluginSettings.getPluginInfo(isPluginProject.getParent()).version;
pluginSettings is a bound variable in the current scope and isPluginProject actually returns a File object that represents the GrailsPlugin.groovy file.

Resources