Я люблю использовать Gradle в настоящее время. Я люблю IntelliJ еще больше. Тем не менее, интеграция этих двух оказывается настоящей болью в заднице!
Для простых проектов Java все отлично работает. Хотя я должен признать, что держусь подальше от плагина JetGradle, который в лучшем случае можно использовать. Но большую часть времени я все еще использую плагин Gradle IDEA. Это просто работает лучше, и я привык всегда открывать консоль: мне нужно столько же печатать, gradle idea сколько синхронизировать проект Gradle в IDEA.
Но…
Интеграция WAR просто ужасна, нет, даже ужасна. И плагин Gradle IDEA, и JetGradle не имеют функциональности для добавления веб-фасета в мой модуль. Парни из Gradle на самом деле не склонны добавлять функциональность в свой плагин, и парни из Jetbrains, кажется, блаженно не знают, что проблема была подана более года назад (я сам создал другую, чтобы разбудить их).
Отсутствие автоматического способа синхронизации моего файла сборки Gradle с моей IDE для веб-проектов вынуждает меня использовать Maven для этих проектов или использовать Eclipse в качестве моей IDEA (работает плагин eclipse-wtp). Я не доволен ни одним из этих вариантов.
Предлагаемые решения тоже не очень хороши. Вы можете вручную добавить веб-фасет в свой проект IDEA. Это подвержено ошибкам и не то, что я с нетерпением жду, чтобы делать каждый раз, когда я меняю зависимость. Другое решение еще хуже и включает манипулирование файлами проекта IntelliJ XML из скрипта сборки Gradle. Сколько времени может занять первое решение, это просто чокнутый.
Я сильно опечален. Gradle стал моим главным выбором для создания программного обеспечения. Но если они не могут обеспечить достойную интеграцию с веб-проектами, я вынужден использовать Maven для любых проектов, требующих войны. Gradle, не заставляй меня сожалеть о переходе к вам.
Обновление : Слава Богу, Gradle использует Groovy и имеет отличные возможности редактирования XML. Поэтому я выбрал решение, которое казалось безумным: манипулирование файлами iml и ipr. Потребовалось немного поработать, но следующий фрагмент добавит веб-аспект в ваш проект и создаст в IntelliJ развертываемый артефакт (взорванный WAR). Это не красиво, но работает (по крайней мере, для меня есть несколько вариантов использования, которые не будут работать). Я просто хотел, чтобы ребята из Gradle сделали это в первую очередь, но, возможно, мой код попадет в Gradle. Можно только надеяться.
Во-первых, в вашей buildSrc\src\main\groovy папке есть класс, который обладает всеми функциями для процесса обогащения (как я его называю).
import org.gradle.api.Project;
public class IdeaEnricher {
def static updateWebArtifacts(Project gradleProject, Node project) {
def artifactManager = project.component.find { it.@name == 'ArtifactManager' } as Node
if (artifactManager) {
Node artifact = artifactManager.artifact.find { it.@type == 'exploded-war' }
if (artifact) {
artifactManager.remove(artifact)
}
} else {
artifactManager = project.appendNode('component', [name: 'ArtifactManager']);
}
def builder = new NodeBuilder();
def artifact = builder.artifact(type: 'exploded-war', name: "${gradleProject.name}/Exploded war") {
'output-path'("\$PROJECT_DIR\$/build/libs/${gradleProject.name}_exploded.war")
root(id: 'root') {
element(id: 'javaee-facet-resources', facet: "${gradleProject.name}/web/Web");
element(id: 'directory', name: 'WEB-INF') {
element(id: 'directory', name: 'classes') {
element(id: 'module-output', name: "${gradleProject.name}")
}
element(id: 'directory', name: 'lib') {
gradleProject.configurations.runtime.each {
element(id: 'file-copy', path: it)
}
}
}
}
}
artifactManager.append artifact
}
def static updateWebFacet(Project gradleProject, Node module) {
def facetManager = module.component.find { it.@name == 'FacetManager' } as Node
if (facetManager) {
Node webFacet = facetManager.facet.find { it.@type == 'web' }
if (webFacet) {
facetManager.remove(webFacet)
}
} else {
facetManager = module.appendNode('component', [name: 'FacetManager']);
}
def builder = new NodeBuilder();
def webFacet = builder.facet(type: "web", name: 'Web') {
configuration {
descriptors {
deploymentDescriptor(name: 'web.xml', url: 'file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml')
}
webroots {
root(url: 'file://$MODULE_DIR$/src/main/webapp', relative: '/')
}
sourceRoots {
root(url: 'file://$MODULE_DIR$/src/main/java')
root(url: 'file://$MODULE_DIR$/src/main/resources')
}
}
}
facetManager.append webFacet
}
def static updateBuildOutputFolderForGradle(Project gradleProject, Node project) {
def projectRootManager = project.component.find { it.@name == 'ProjectRootManager' } as Node
Node output = projectRootManager.output.find{it.@url == 'file://$PROJECT_DIR$/out'}
if(output) {
output.@url = 'file://$PROJECT_DIR$/build/ide'
}
}
}
Включение его в ваш скрипт сборки gradle довольно тривиально:
idea {
module {
iml {
withXml {
IdeaEnricher.updateWebFacet(this.project, it.asNode())
}
}
}
project {
ipr {
withXml {
IdeaEnricher.updateWebArtifacts(this.project, it.asNode())
IdeaEnricher.updateBuildOutputFolderForGradle(this.project, it.asNode())
}
}
}
}
Я склонен немного поработать над файлом ipr, чтобы выходная папка соответствовала папке сборки gradle. Теперь IntelliJ создает свою собственную out папку. Это небольшое раздражение, но так как я все равно меняю конфигурацию, я мог бы пройти весь путь.
Это еще раз убедило меня, что Gradle — правильный выбор. Конечно, он немного грубоват, и еще не все функции, которые есть у вас в Maven, есть. Однажды я сказал, что Грэдл предоставляет вам инструменты, чтобы оторвать всю вашу ногу, но на этот раз я был рад, что в моем распоряжении все оружие Groovy. Тот факт, что вы можете добавить дополнительную логику в свою сборку, является чем-то чрезвычайно мощным, и я вижу, что буду делать в будущем гораздо больше.