Статьи

Лучше иметь дело с «Не удалось найти свойство X на плагине Y» в Gradle 2.13

Отсутствует имя пользователя, пароль или токен для службы, о которой вы, возможно, никогда не слышали? Обычно это происходит, когда вы пытаетесь что-то сделать (например, просто построить проект), а не только когда используется данный плагин (например, онлайн-инструмент для покрытия кода). Мне не нравилось изменять свою среду, чтобы просто внести небольшое исправление в другой проект с открытым исходным кодом. Это раздражало меня, и я хотел изменить это. Начиная с Gradle 2.13 это стало возможным. Однако давайте начнем с причин (если вас интересует только решение, перейдите к последним 2 абзацам).

Почему я получаю «Не могу найти недвижимость…»?

Большинство плагинов Gradle должны быть настроены. Некоторые свойства могут быть установлены непосредственно в build.gradle , но некоторые другие (особенно учетные данные) лучше хранить локально в ~/.gradle/gradle.properties . В результате разделы конфигурации плагина часто выглядят так:

1
2
3
4
5
bintray {
    user = project.getProperty('bintrayUser')
    key = project.getProperty('bintrayKey')
    ...
}

или это:

1
2
3
4
5
bintray {
    user = getProperty('bintrayUser')
    key = getProperty('bintrayKey')
    ...
}

или даже короче

1
2
3
4
5
bintray {
    user = bintrayUser
    key = bintrayKey
    ...
}

Он отлично работает для разработчика проекта, для которого bintrayUser и bintrayKey определены в его локальной конфигурации, но для каждого, кто не загружает их в Bintray ежедневно, он терпит неудачу с:

1
2
3
* What went wrong:
A problem occurred evaluating root project 'another-nice-open-source-project'.
> Could not find property 'bintrayKey' on com.jfrog.bintray.gradle.BintrayExtension_Decorated@2ecc563.

В результате этого project.getProperty() , не упомянутое явное присваивание, просто выдает исключение, когда конкретное свойство не найдено. Плохо, что код выполняется во фразе конфигурации. По этой причине выполнение каждой задачи, даже не связанной с этим конкретным плагином (например, gw tasks или gw wrapper ), с треском проваливается.

В качестве обходного пути необходимо выполнить охранную проверку:

1
2
3
4
5
bintray {    //Gradle <2.13
    user = hasProperty('bintrayUser') ? getProperty('bintrayUser') : ''
    key = hasProperty('bintrayKey') ? getProperty('bintrayKey') : ''
    ...
}

Это не выглядит хорошо, очень компактно. В качестве другого варианта фиктивный заполнитель может быть сохранен в конфигурации проекта, но начиная с Gradle 2.13, есть лучший способ справиться с этим.

project.findProperty ()

Gradle 2.13 — это первая версия с моим вкладом в новый метод project.findProperty() . Он ведет себя так же, как getProperty() , но вместо выдачи исключения возвращается null значение. Это значительно упрощает назначение:

1
2
3
4
5
bintray {    //Gradle 2.13+
    user = findProperty('bintrayUser') ?: ''
    key = findProperty('bintrayKey') ?: ''
    ...
}

Некоторые люди могут сказать, что Optional может быть лучше возвращаемого значения, но это API, и Gradle поддерживает Java старше 8 лет.

Резюме

Для меня findProperty — это метод, который я очень часто искал в Gradle. Я сожалею, что мне потребовалось больше года, чтобы сделать этот запрос. Gradle 2.13 был только что выпущен, и обновления версий по проектам будут выполняться постепенно. Это может занять некоторое время, но каждый проект, переходящий на 2.13, сможет упростить свою конфигурацию, сделав сообщение об ошибке «Не удалось найти свойство X в плагине Y» воспоминанием о прошлом (конечно, если вам действительно не нужно настраивать конкретный плагин для используй это).

Протестировано с Gradle 2.13.