-P & hasProperty

I am having trouble getting simple -P values to work. I have a multi-module build, so maybe the root/sub project comes into play, but what I have is this:

  1. in the root build.gradle I have the following abbreviated code:

    subprojects { subProject ->

    subProject.tasks.withType( Test.class ).all { task ->

     printf 'checking `db` setting wrt applying databases.gradle overrides\n'
    
     if ( hasProperty( 'db' ) ) {
         final String db = property( 'db' )
         printf 'Encountered db setting : %s', db
         dbBundle[db].each { entry->
             println '    [' + entry.key + '] -> [' + entry.value + ']'
         }
         task.systemProperties.putAll( dbBundle[db] );
     }
    

    }
    }

I then run the following command:

…/gradlew -Pdb=oracle test --tests “org.hibernate.test.hql.ASTParserLoadingTest”

but I only get the following output and for sure the test sys props do not contain these values:

checking db setting wrt applying databases.gradle overrides
checking db setting wrt applying databases.gradle overrides
checking db setting wrt applying databases.gradle overrides
checking db setting wrt applying databases.gradle overrides
checking db setting wrt applying databases.gradle overrides

(I’ve tried both -P and -D but no difference)

Why is hasProperty not picking up these -P/-D options?

Hello,

The Groovy specifications tells us that:

  • delegate corresponds to a third party object where methods calls or properties are resolved whenever the receiver of the message is not defined
  • By default, the delegate is set to owner
tasks.withType(Test).all { task ->
    println "Configuration closure delegate is: ${delegate}"
    println "Configuration closure owner is:    ${owner}"
    println "Configuration closure this is:     ${this}"
    if (hasProperty('db')) {
        println "Property db is set, working with $task"
    }
}

If you run this, it will print:

Configuration closure delegate is: task ':test'
Configuration closure owner is:    DynamicObject for task ':test'
Configuration closure this is:     root project 'foo'

When using -P flag, you set project properties. But the hasProperty is sent to a task object, not your project object. To solve your issue, you can use:

if (this.hasProperty('db')) // ...

or better in my opinion (less misleading):

if (project.hasProperty('db')) // ...

@Pierre1 is correct here. It’s safest simply to use project.hasProperty() (same with property() and findProperty()) everywhere to avoid the ambiguity.

A related question… so how can I define a project property in the build script (to give it a default value) and override it via -P?

Do I have to do something “hoky” like:

ext {
    db = project.hasProperty('db') ? project.property('db') : 'h2';
}

You can simplify this somewhat with the elvis operator.

ext {
    db = project.findProperty('db') ?: 'h2'
}

The findProperty() method returns null instead of throwing an exception for unknown properties.

Thanks Pierre. Thanks Mark.