kec2
(Klaus Christiansen)
March 12, 2020, 11:30am
1
I have a chicken/egg problem.
I have a task createDatabase that need properties from a config file.
And another task createClient that creates the config file.
If I run task createClient gradle will evaluate task createDatabase and find that a property is missing and failing before the file is created.
I need ideas on how to solve this little problem.
File configFile = file("$rootDir/$client/conf/config.properties")
Properties props = new Properties()
if (configFile.exists()) {
props.load(new FileInputStream(configFile))
props.each { prop ->
project.ext.set(prop.key, prop.value)
}
}
task createDatabase(type: Exec) {
args = [database]
def command = ['CMD', '/C', 'scripts\\db\\CreateNewDB.cmd']
commandLine = command + args
}
task createClient() {
doLast {
def customer = project.property('client')
mkdir "$customer/conf"
file("$customer/conf/config.properties").write("database=foo")
}
}
jjustinic
(James Justinic)
March 13, 2020, 6:04am
2
You don’t need to configure the args of your createDatabase task at configuration time. You can create a task such as configureDatabase that reads the properties file created by createClient and sets the args value of createDatabase during the execution phase.
Alternatively, you could create a class that implements CommandLineArgumentProvider to load the property file and provide the appropriate argument. The execution of this logic should be deferred until the createDatabase task actually requires it.
kec2
(Klaus Christiansen)
March 13, 2020, 8:12am
3
jjustinic:
execution phase
I like the idea of postpone reading of args to execution phase.
But I’m not sure how.
I guess I could change the createDatabase to something like:
task createDatabase() {
doLast {
exec {
...
}
}
}
Is that you had in mind?
jjustinic
(James Justinic)
March 13, 2020, 4:37pm
4
Using exec in your own task action should work as well. However, I was specifically mentioning that you can continue to use an Exec task, but defer adding the final argument until execution with a task that does nothing other than read the properties and add the arg to the createDatabase task. Something like this would work:
task createClient {
doLast {
def customer = project.property('client')
mkdir "$customer/conf"
file("$customer/conf/config.properties").write("database=foo")
}
}
task createDatabase(type: Exec) {
commandLine = ['CMD', '/C', 'scripts\\db\\CreateNewDB.cmd']
}
task configureCreateDatabase {
createDatabase.dependsOn it
dependsOn createClient
doLast {
File configFile = file("$rootDir/$client/conf/config.properties")
Properties props = new Properties()
if (configFile.exists()) {
configFile.withInputStream { props.load(it) }
createDatabase.args props.getProperty('database')
}
}
}
You also have the CommandLineArgumentProvider option, which will work as long as you don’t eagerly access the commandLine property:
class DatabaseArgumentProvider implements CommandLineArgumentProvider {
Iterable<String> asArguments() {
File configFile = file("$rootDir/$client/conf/config.properties")
Properties props = new Properties()
configFile.withInputStream { props.load(it) }
return Arrays.asList(props.getProperty('database'))
}
}
task createDatabase(type: Exec) {
commandLine = ['CMD', '/C', 'scripts\\db\\CreateNewDB.cmd']
argumentProviders.add(new DatabaseArgumentProvider())
}