Idiomatic concise way to get an optional property

So far, I have used the following idiom to get optional and default properties

project.properties.myProp ?: 'defaultValue

This is especially useful when one wants to implement a cascade of defaults - i.e. allow to specify credentials per actual service-instance, if not specified, use per service-type, if not - per environment, if not - use default.

If I use the pattern above, this can be one line:

def p = project.properties
def credentials = p["$env.$serviceId"] ?: p["$env.$serviceType"] ?: p["global.$serviceType"] ?: p["$env"] ?: defaultCreds

Unfortunately, I just found out that Project.getProperties() resolves all deferred extensions, which can result in mysterious breaks (in my case an inexplicable “Cannot configure the ‘publishing’ extension after it has been accessed.” error)

The current way I know is to use hasProperty(), though that has the unfortunate side effect to turn the above one-liner into:

def credentials = hasProperty("$env.$serviceId")     ? property("$env.$serviceId") 
                : hasProperty("$env.$serviceType")   ? property("$env.$serviceType")
                : hasProperty("global.$serviceType") ? property("global.$serviceType") 
                : hasProperty("$env") ? property("$env") 
                : defaultCreds

Is there a reason for not having a method to to lookup a project property with default? Can you recommend a better way to structure this?

Is it possible to capture an exception when a deferred config is resolved and then throw it as a cause when somebody tries to modify the resolved config?

I’m currently not aware of a good workaround for this. The real solution here is to fix the publish plugin so the error you get is not thrown at all. The new Rule based model configuration we’re currently working on aims to provider a proper solution for this kind of issues.

cheers,
René

Revisiting my old posts, this issue has been resolved in Gradle 2.13 by the new Project.findProperty('abc') API.

Thanks!