Adding an extra config property to a grail target - grails

In my config.groovy my dev environment is...
development {
...
grails.resources.mappers.yuicssminify.disable = true
grails.resources.mappers.yuijsminify.disable = true
grails.resources.mappers.hashandcache.disable = true
grails.resources.mappers.zip.disable = true
}
When I run grails dev war from jenkins I want an extra property in some cases. This property is:
grails.plugin.jbossas.removeLog4jJars = false
I cannot alter the development environment in the Config.groovy. Is there any way I can pass in this extra property?

I think the cleanest solution would be a new environment for your jenkins:
jenkins {
grails.plugin.jbossas.removeLog4jJars = false
}
If this is not an option (like mentioned in the comments) it is also possible to move this configuration value into a system specific property file:
grails.config.locations = ["file:/home/user/my-config.properties"]
Within my-config.properties on the jenkins system you can do:
grails.plugin.jbossas.removeLog4jJars = false
The my-config.properties files of other systems stay empty (I think they don't even need to exist).
If this is also not an option you can do something (not so nice) like this:
development {
if (MyUtils.isJenkins()) {
grails.plugin.jbossas.removeLog4jJars = false
}
...
}
Within MyUtils.isJenkins() you have to determine on which system your application is running. For example:
class MyUtils {
public static boolean isJenkins() {
def env = System.getenv()
return env[IS_JENKINS]
}
}
This example checks if the system variable IS_JENKINS is set (you can add other ways to determine on which system you are running like)

Related

How to implement Spock Parameterized test best practice?

I have a test spec, which can be run with a unique data set. The best practice for this is a bit unclear. How should the code below be modified to run with:
#Stepwise
class marktest extends ShopBootStrap {
private boolean useProductionUrl = false
def "Can Access Shop DevLogin page"() {
// DevStartLogin: 'New OE Start' button click
setup:
println System.getProperty("webdriver.chrome.driver")
when:
to ShopDevStartPage
then:
at ShopDevStartPage
}
def "on start enrollment, select 'United States' and click 'continue' button"() {
when: "enter Sponsor ID and click New OE Start"
to ShopDevStartPage
sponsorId.value(ShopDevStartPage.SPONSORID)
NewOEButton.click()
then:
waitFor { NewEnrollmentPage }
}
}
1) data set 1
private boolean useProductionUrl = false
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "beta.com"
testPassword = System.getProperty("test.password") ?: "dontyouwish"
2) data set 2
private boolean useProductionUrl = true
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "production.com"
testPassword = System.getProperty("test.password") ?: "dywyk"
Generally, to make a test depend on data, use a where block, possibly together with the #Unroll annotation.
However, your case is simply not the best example for a data driven test.
The baseDomain and protocol should rather be set in the GebConfig.groovy, similar to the snippets you provided.
Refer to this section in the Book of Geb, as that is what you are using.
Simple example (in GebConfig.groovy):
environments {
production {
baseUrl = "https://production.com"
}
beta {
baseUrl = "https://beta.com"
}
}
If done this way, your individual tests does not need to care about the environment, as this is already built into Geb.
For example when navigating to pages, their base URL is automatically set.
You did not provide that part of the code in your example (how the pages are defined), so I cannot help you with that directly.
Now, in your case, as far as the "password" is concerned, you could read that from an environment variable or system property, that you set close to where you configure Geb with geb.env or geb.build.baseUrl system properties.
Note I am just considering this for practial reasons without any regards towards secrecy of the password.
You would pick up the variable in the page class that uses it.
Example code in page class:
static content = {
//...
passwordInput = { $('input[type="password"]') }
//...
}
void enterPassword() {
passwordInput.value(System.getProperty('test.password'))
}
To make this work, you need to start your test with the system properties set to correct values.
E.g. if starting directly from the command line, you would add parameters -Dgeb.env=beta -Dtest.password=dontyouwish.
If running from a Gradle task, you would need to add appropriate systemProperty keys and values to that task.
If running from IDE, refer to your IDEs documentation on how to set Java system properties when running a program.

Reusing Grails variables inside Config.groovy

In my Config.groovy I have:
// Lots of other stuff up here...
environments {
development {
myapp.port = 7500
}
production {
myapp.port = 7600
}
}
fizz {
buzz {
foo = "Port #${myapp.port}"
}
}
When I run my app via grails -Dgrails.env=development run-app, my web app spins up without errors, but then at runtime I see that the value of fizz.buzz.foo is "Port #[:]". I would expect it to be "Port #7500".
Why isn't Grails seeing my var?
You could probably get away with this if myapp.port were not in an environments block but that's a side effect of the way Config.groovy is processed rather than being intentional. And if you were to override myapp.port in an external config file then fizz.buzz.foo would still end up with the value from Config.groovy, not the override from the external.
You could make it a late-binding GString using a closure to pull the value from grails.util.Holders.config when fizz.buzz.foo is referenced rather than when it is defined:
foo = "Port #${-> Holders.config.myapp.port}"
This is different from "Port #${Holders.config.myapp.port}" which would attempt to access the config at the point where Config.groovy is being parsed.
If the value you're defining here is one that will ultimately end up defining a property of a Spring bean (for example many of the spring-security-core plugin configuration options become bean properties) then you may be able to do
foo = 'Port #${myapp.port}'
with single rather than double quotes. This causes the resulting config entry to contain the literal string ${myapp.port}, which will be resolved against the config by the Spring property placeholder mechanism when it is used as a bean property value.
Another way is to simply use variables within your config file like this:
def appPort = 7500
environments {
production {
appPort = 7600
myapp.port = appPort
}
}
fizz {
buzz {
foo = "Port #$appPort"
}
}
And also, you don't need to send the -Dgrails.environment=development when you execute the run-app, it's the default one.

In the Grails configuration how do I access variables in other environments?

If I have a list environment variable in grails in one environment, how do I modify it on the cascade to other environments?
For instance, in my quartz configuration I added the following,
quartz {
// other variables remove for clarity
whiteListedJobs = [ Job1.class, Job2.class, Job3.class ]
}
The quartz is not specific to any single environment. But in my environment specific configurations I'd like to override this list to include more jobs for certain environments.
Something like,
environments {
development {
quartz {
whiteListedJobs = whiteListedJobs + Job4.class
}
}
}
But unfortunately this doesn't work. My code that tries to read the quartz config variable as a list throws Cannot cast object '{}' with class 'groovy.util.ConfigObject' to class 'java.util.List', which suggests to me that it isn't working.
What is the correct way to do this?
The problem is that the groovy ConfigSlurper doesn't provide a way to read a config entry at a different level during the parsing process. However, it is parsed as a Groovy script, so you can use local variables to avoid completely rewriting entries:
def defaultJobs = [ Job1.class, Job2.class, Job3. class ]
quartz {
whiteListedJobs = defaultJobs
}
environments {
development {
quartz {
whiteListedJobs = defaultJobs + Job4.class
}
}
}

Load an external properties file in grails

I am trying to load the properties file externally, by setting up the system environment.
In my config.groovy file,
println "Config file location --->" + System.getenv("SAM_ENV")
grails.config.locations = ["file:"+ System.getenv("SAM_ENV")]
I have set the system env SAM_ENV value as C:\test\config.properties.
When I try to run the application,I am getting the print value as
Config file location ---> C:\test\config.properties prints properly.
The problem is when I try to access the properties file in my controller as
print "PAGINATION1"+grailsApplication.config.PAGINATION1
the value of PAGINATION1 is not getting printed properly.
Can any one help me what configuration has to be done to access the external properties file in grails application.
Add the below line in config.groovy
grails.config.locations = [ "classpath:grails-app-config.properties"]
environments {
development {
grails.logging.jul.usebridge = true
grails.config.locations = ["file:C:\\conf\\externalfile.groovy"]
}
production {
grails.logging.jul.usebridge = false
grails.config.locations = ["file:/opt/config/externalfile.groovy"]
// TODO: grails.serverURL = "http://www.changeme.com"
}
}
If you want to access any property from external configuration(config.groovy) then just declare the property like
property = property value eg:(ImagePath = "C:\\Users\\Saved Pictures")
access it like grailsApplication.config."property"
eg:(grailsApplication.config.ImagePath)
NOTE: dont use def just a property and its value.
What you're looking for is extending the classpath, which you can achieve by adding a post compilation event in _Events.groovy. Try this:
eventCompileEnd = {
ant.copy(todir:classesDirPath) {
fileset(file:"C:\test\config.properties")
}}
You can find more help here

Configuration of Grails plugin

I'm developing my first Grails plugin. It has to access a webservice. The Plugin will obviously need the webservice url. What is the best way to configure this without hardcoding it into the Groovy classes? It would be nice with different config for different environments.
You might want to Keep It Simple(tm). You may define the URL directly in Config.groovy -including per-environment settings- and access it from your plugin as needed using grailsApplication.config (in most cases) or a ConfigurationHolder.config object (See further details in the manual).
As an added bonus that setting may also be defined in standard Java property files or on other configuration files specified in grails.config.locations.
e.g. in Config.groovy
// This will be the default value...
myPlugin.url=http://somewhe.re/test/endpoint
environments {
production {
// ...except when running in production mode
myPlugin.url=http://somewhe.re/for-real/endpoint
}
}
later, in a service provided by your plugin
import org.codehaus.groovy.grails.commons.ConfigurationHolder
class MyPluginService {
def url = ConfigurationHolder.config.myPlugin.url
// ...
}
If its only a small (read: one item) config option, it might just be easier to slurp in a properties file. If there are some number of configuration options, and some of them should be dynamic, i would suggest doing what the Acegi Security plugin does - add a file to /grails-app/conf/plugin_name_config.groovy perhaps.
added bonus is that the user can execute groovy code to compute their configuration options (much better over using properties files), as well as being able to do different environments with ease.
check out http://groovy.codehaus.org/ConfigSlurper , which is what grails internally use to slurp configs like config.groovy.
//e.g. in /grails-app/conf/MyWebServicePluginConfig.groovy
somePluginName {
production {
property1 = "some string"
}
test {
property1 = "another"
}
}
//in your myWebServicePlugin.groovy file, perhaps in the doWithSpring closure
GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())
ConfigObject config
try {
config = new ConfigSlurper().parse(classLoader.loadClass('MyWebServicePluginConfig'))
} catch (Exception e) {/*??handle or what? use default here?*/}
assert config.test.property1.equals("another") == true

Resources