Chapter 12. IDE Support

When we develop applications, we usually use an Integrated Development Environment (IDE). An IDE provides support for writing code for our applications. We can write our code in Java, Groovy, or Scala. We have seen how we can use Gradle to define, for example, library dependencies to compile the code. We want to use the same information that we have defined in a Gradle build file in a project in our favorite IDE.

In this chapter, we will learn how we can use Gradle plugins to generate the project files with classpath dependencies for Eclipse and JetBrains IntelliJ IDEA. We will also learn how we can customize the file generation to add extra configuration data.

Next, we will see the Eclipse and IntelliJ IDEA support for running Gradle tasks from within the IDE.

Using the Eclipse plugin

The Eclipse plugin can generate the project files necessary to import the project in Eclipse. In this section, we will see which tasks are added by the plugin and how we can customize the generated output.

If we have a Java project and want to import the project into Eclipse, we must use the Eclipse plugin to generate the Eclipse project files. Each Eclipse project has as minimum a .project file and a .classpath file. The .project file contains metadata about the project, such as the project name. The .classpath file contains classpath entries for the project. Eclipse needs this to be able to compile the source files in the project. The Eclipse plugin will try to download the artifact with source files belonging to a dependency as well. So, if we import the project into Eclipse and the source files are available, we can directly see the source of dependent class files.

For a Java project, an additional Java Development Tools (JDT) configuration file is created in the .settings folder. The name of the file is org.eclipse.jdt.core.prefs.

Let's create a simple Gradle build file for a Java project. The code for the build file is shown in the following code snippet:

apply plugin: 'java'
apply plugin: 'eclipse'

version = 1.0

sourceCompatibility = 1.6
targetCompatibility = 1.6

description = 'Sample project'

ext {
    slf4jVersion = '1.6.6'
    slf4jGroup = 'org.slf4j'
}

configurations {
    extraLib 
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'

    extraLib "$slf4jGroup:slf4j-api:$slf4jVersion", "$slf4jGroup:slf4j-simple:$slf4jVersion"
}

We apply the Java and Eclipse plugins for our project. We set some project properties, such as version, description, source, and target compatibility. We define a dependency on JUnit for the testCompile configuration. Also, we add an extra custom configuration with a dependency on the slf4j logging library.

First, let's see which tasks are added to our project by the Eclipse plugin. We invoke the tasks task and look at all the tasks in our plugin, shown in the following code snippet:

$ gradle tasks --all
...
IDE tasks
---------
cleanEclipse - Cleans all Eclipse files.
    cleanEclipseClasspath
    cleanEclipseJdt
    cleanEclipseProject
eclipse - Generates all Eclipse files.
    eclipseClasspath - Generates the Eclipse classpath file.
    eclipseJdt - Generates the Eclipse JDT settings file.
    eclipseProject - Generates the Eclipse project file....
...

The eclipse task is dependent on the following three tasks: eclipseClasspath, eclipseJdt, and eclipseProject. Each task generates a single file. The eclipseClasspath task generates the .classpath file, eclipseProject generates the .project file, and eclipseJdt generates org.eclipse.jdt.core.prefs.

When we execute the eclipse task from the command line, we get the following output:

$ gradle eclipse
:eclipseClasspath
Download http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8.pom
Download http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8-sources.jar
Download http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8.jar
:eclipseJdt
:eclipseProject
:eclipse

BUILD SUCCESSFUL

Total time: 8.672 secs

Note that the sources of the JUnit library are downloaded. We now have the .classpath and .project files in our project folder. In the .settings folder we have the org.eclipse.jdt.core.prefs file.

The .project file has the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        <name>chapter12</name>
        <comment>Sample project</comment>
        <projects/>
        <natures>
                <nature>org.eclipse.jdt.core.javanature</nature>
        </natures>
        <buildSpec>
                <buildCommand>
                        <name>org.eclipse.jdt.core.javabuilder</name>
                        <arguments/>
                </buildCommand>
        </buildSpec>
        <linkedResources/>
</projectDescription>

The name element is filled with the project's folder name. We will learn how to change this later in the chapter. The comment element contains our project description. We have applied the Java plugin in our project, and hence the Java nature and build command are added to the project configuration.

If we look at the .classpath file, we can see a classpathentry element with the JUnit dependency, as shown in the following code snippet:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="output" path="bin"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" exported="true"/>
        <classpathentry sourcepath="/Users/mrhaki/.gradle/caches/artifacts-14/filestore/junit/junit/4.8/source/abe171e0fc1242d1fe10e8dc43bce031e3f65560/junit-4.8-sources.jar" kind="lib" path="/Users/mrhaki/.gradle/caches/artifacts-14/filestore/junit/junit/4.8/jar/4150c00c5706306ef0f8f1410e70c8ff12757922/junit-4.8.jar" exported="true"/>
</classpath>

The classpathentry element has a reference to the location in the Gradle cache of the downloaded JUnit library. Note that the sourcepath attribute references the source files.

The last generated org.eclipse.jdt.core.prefs file has the following contents:

#
#Thu Aug 21 09:36:25 CEST 2012
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

We can see that the source and target compatibility we defined in the Gradle build file are used for the properties org.eclipse.jdt.core.compiler.source, org.eclipse.jdt.core.compiler.codegen.targetPlatform, and org.eclipse.jdt.core.compiler.compliance.

We have added the Java plugin to our project and the Eclipse plugin knows this, so the Java nature and builder are added to the generated .project file. If we use the Groovy and Scala plugins, the Eclipse plugin will add the correct nature and build configurations to the .project file.

Customizing generated files

We have several options to customize the configuration in the generated files. The Eclipse plugin adds a DSL to configure model objects that represent Eclipse configuration objects. If we use the DSL to configure the objects, these newly configured objects are merged with existing configuration before the file is generated. We can also hook into the generation process and work directly on the model objects before and after the configuration is merged and the file is generated. Finally, we can even use a hook to work directly on the XML structure before the configuration file is generated.

The following steps describe the complete configuration file generation lifecycle:

  1. First, the file is read from disk or a default file is used if the file is not available.
  2. Next, the beforeMerge hook is invoked. The hook accepts the model object for the configuration file as an argument.
  3. The implicit configuration information from the Gradle build file and the configuration defined using the DSL are merged.
  4. Then, the whenMerged hook is executed. The hook accepts the model object for the configuration file as an argument.
  5. The withXml hook is invoked. XML manipulation can happen here before the file is written to disk.
  6. Finally, the configuration file is written to disk.

Customizing using DSL

When the Eclipse plugin generates the files, it will look in the Gradle build file for the necessary information. For example, if we set the description property of the Project object, the comment section in the .project file is filled with the value of that property :

The Eclipse plugin also adds a configuration script block with the name eclipse. The configuration can be described using a simple DSL. At the top level we can add path variables that will be used for replacing absolute paths in classpath entries. The org.gradle.plugins.ide.eclipse.model.EclipseModel object is used and the pathVariables() method of this class must be used to define a path variable.

Next, we can define the configuration information for the .project file in the project section. The model object org.gradle.plugins.ide.eclipse.model.EclipseProject is used to model the Eclipse project configuration. We can, for example, use the name property to change the name of the project in the generated .project file. It is good to know that Gradle can generate unique project names for a multi-project build. A unique name is necessary to import the projects into Eclipse. During the .project file generation, all projects that are part of the multi-project must be known. So, it is best to run the eclipse or eclipseProject task from the root of the project. Also, methods for adding project natures and new build commands are available.

To customize the .classpath file generation, we can use the classpath section of the eclipse configuration closure. Here, the org.gradle.plugins.ide.eclipse.model.EclipseClasspath object is used to model the classpath entries of the Eclipse project. We can use the properties plusConfigurations and minusConfigurations to add or remove dependency configurations from the generated .classpath file. By default, the associated source files for a dependency are downloaded, but we can also set the downloadJavadoc property to true to download the Javadoc associated with the dependency.

The jdt section of the eclipse configuration closure can be used to change the source and target compatibility versions. By default, the Gradle Java plugin settings are used, but we can overrride it here. The org.gradle.plugins.ide.eclipse.model.EclipseJdt object is used to model the Eclipse configuration.

In the following build file, we see an example of all the possible methods and properties we can use with the DSL to customize the generated .project file:

apply plugin: 'java'
apply plugin: 'eclipse'

eclipse {
    pathVariables 'APPSERVER_HOME': file('/apps/appserver/1.0')

    project {
        name = 'sample-eclipse'

        comment = 'Eclipse project file build by Gradle'

        // Add new natures like Spring nature.
        natures 'org.springframework.ide.eclipse.core.springnature'

        // Add build command for Spring.
        buildCommand 'org.springframework.ide.eclipse.core.springbuilder'

        // If using location attribute then type 1 is file, 2 is folder
        linkedResource name: 'config', type: '2', location: file('/opt/local/config')

        // If using locationUri attribute then type 1 for file/folder, 2 is virtual folder
        linkedResource name: 'config2', type: '1', locationUri: 'file:../config'

        // Define reference to other project. This is not 
        // a build path reference.
        referencedProjects 'other-project'
    }
}

In the following example build file, we see the options to change the.classpath file:

apply plugin: 'java'
apply plugin: 'eclipse'

eclipse {
    classpath {
        // Add extra dependency configurations.
        plusConfigurations += configurations.extraLib

        // Remove dependency configurations.
        minusConfigurations += configurations.testCompile

        // Included configurations are not exported.
        noExportConfigurations += configurations.testCompile

        // Download associated source files.
        downloadSources = true

        // Download Javadoc for dependencies.
        downloadJavadoc = true

        // Add extra containers.
        containers 'ApacheCommons'

        // Change default output dir (${projectDir}/bin)
        defaultOutputDir file("$buildDir/eclipse-classes")        
    }
}

The following example build file shows the configuration options to generate the org.eclipse.jdt.core.prefs file:

apply plugin: 'java'
apply plugin: 'eclipse'

eclipse {
    jdt {
        sourceCompatibility = 1.6
        targetCompatibility = 1.6
    }
}

Customizing with merge hooks

Using the DSL to customize file generation is very elegant. Remember from the configuration file generation steps that this information is used right after the beforeMerged and before the whenMerged hooks. These hooks take a model object as an argument that we can use to customize. We can use the merge hooks if we want to do something that is not possible using the project configuration or DSL.

The merge hooks can be defined in the eclipse configuration closure. For each file, we can define a configuration closure for the beforeMerged and whenMerged hooks. These methods are part of the org.gradle.plugins.ide.api.XmlFileContentMerger class. Gradle will delegate the configuration closures to the methods of this class. The beforeMerged hook is useful to overwrite or change existing sections in the configuraton file. The cleanEclipse task cleans all the sections in a configuration file, and by using the beforeMerged hook we can ourselves define which parts need to be cleaned or overwritten.

The whenMerged hook is the preferred way of changing the model object. When this hook is invoked, the model object is already configured with all settings from the project configuration and DSL.

Each file is represented by the file property of the eclipse configuration closures. For example, to add a merge hook to the .project file generation, we define it 353using the eclipse.project.file property.

The following table shows the class that is passed as an argument for the merge hooks closures:

Model

Merge hook argument

Description

Project

org.gradle.plugins.ide.eclipse.model.Project

Model object with properties for .project file generation.

Classpath

org.gradle.plugins.ide.eclipse.model.Classpath

Model object with properties for .classpath file generation.

Jdt

org.gradle.plugins.ide.eclipse.model.Jdt

Model object with properties for org.eclipse.jdt.core.prefs file generation.

For the Jdt model, we have an additional method named withProperties(), to change the contents of the file. This method has a closure with an argument of type java.util.Properties.

In the following example build file, we use the merged hooks to change the configuration in the .project file:

apply {
    plugin 'java'
    plugin 'eclipse'
}

eclipse {
    project {
        file { 
            beforeMerged { project ->
                // We can access the internal object structure
                // using merge hooks.
                project.natures.clear()
            }

            afterMerged { project ->
                project.name = 'sample-eclipse'

                project.comment = 'Eclipse project file build by Gradle'       
       
                project.natures.add 'org.springframework.ide.eclipse.core.springnature'

                buildCommand.add 'org.springframework.ide.eclipse.core.springbuilder'

                linkedResources.add name: 'config', type: '2', location: 'file:/opt/local'

                referencedProjects.add 'other-project'
            }
        }
    }
}

In the following example build, we use the merged hooks to change the .classpath and org.eclipse.jdt.core.prefs files:

apply {
    plugin 'java'
    plugin 'eclipse'
}

eclipse {
    classpath {
        file {
            beforeMerged { classpath ->
                // Remove lib classpath entries.
                classpath.entries.removeAll {
                    it.kind == 'lib'
                }
            }

            whenMerged { classpath ->
                classpath.entries.add kind: 'output', path: "$buildDir/eclipse-classes"
            }
        }
    }

    jdt {
        file {
            beforeMerged { jdt ->
            }

            whenMerged { jdt ->
                jdt.sourceCompatibility = 1.6
                jdt.targetCompatibility = 1.6
            }

            whenProperties { properties ->
                properties.extraProperty = 'value'
            }
        }
    }
}

Customizing with XML manipulation

We have seen how to customize the configuration file generation with project configuration, DSL, and the merge hooks. At the lowest level, there is a hook to change the XML structure before it is written to disk. Therefore, we must implement the withXml hook. We define a closure, and the first argument of the closure is of type org.gradle.api.XmlProvider. The class has the asNode() method, which returns the root of the XML as a Groovy node. This is the easiest object with which to alter the XML contents. The asString() method returns a StringBuilder instance with the XML contents. Finally, the asElement() method returns an org.w3c.dom.Element object.

The asNode() method returns the Groovy groovy.util.Node class. With this node class, we can easily add, replace, or remove nodes and attributes.

In the following example build file, we can see different ways to manipulate the XML structure:

apply {
    plugin 'java'
    plugin 'eclipse'
}

eclipse {
    project {
        file { 
            withXml { xml ->
                def projectXml = xml.asNode()
                projectXml.name = 'sample-eclipse'

                def natures = projectXml.natures
                natures.plus {
                    nature {
                        'org.springframework.ide.eclipse.core.springnature'
                    }   
                }   
            }
        }
    }

    classpath {
        file {
            withXml { xml ->
                def classpathXml = xml.asNode()
                classpathXml.classpathentry.findAll { it.@kind == 'con' }*.@exported = 'true'
            }
        }
    }
}

We have seen all the different options to change the configuration files. Configuration changes, which we would normally make in Eclipse, can now be done programmatically in a Gradle build file.

Merging configuration

If a file already exists, Gradle will try to merge extra information with the existing information. Depending on the section, the information will be amended to existing configuration data or will replace existing configuration data. This means that if we make changes to our project settings in Eclipse, they will not be overwritten even if we invoke one of the eclipse tasks.

To completely rebuild the project files, we must use the cleanEclipse tasks. For each project file, there is a corresponding cleanEclipse task. For example, to rebuild the .project file, we invoke the cleanEclipseProject task before eclipseProject. Any changes we have made manually are removed, and a new .project file is generated by Gradle, with the settings from our Gradle build file.

Configuring WTP

We can add Web Tools Platform (WTP) to Eclipse, to add support for Java enterprise applications. We get support for web applications (WAR) and enterprise applications (EAR). To generate the correct configuration files, we must add another plugin to our Gradle build file. We add the Eclipse WTP plugin to the project and also the War or Ear plugin.

Let's create a build file and add the War and Eclipse WTP plugins, as follows:

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'

version = 1.0

description = 'Sample project'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'
}

The Eclipse WTP plugin adds several new tasks to our Gradle build. In the following snippet, we invoke the tasks task to see which tasks are added:

$ gradle tasks --all
...
IDE tasks
---------
cleanEclipse - Cleans all Eclipse files. [cleanEclipseWtp]
    cleanEclipseClasspath
    cleanEclipseJdt
    cleanEclipseProject
cleanEclipseWtp - Cleans Eclipse wtp configuration files.
    cleanEclipseWtpComponent
    cleanEclipseWtpFacet
eclipse - Generates all Eclipse files. [eclipseWtp]
    eclipseClasspath - Generates the Eclipse classpath file.
    eclipseJdt - Generates the Eclipse JDT settings file.
    eclipseProject - Generates the Eclipse project file.
eclipseWtp - Generates Eclipse wtp configuration files.
    eclipseWtpComponent - Generates the Eclipse WTP component settings file.
    eclipseWtpFacet - Generates the Eclipse WTP facet settings file.
...

The Eclipse WTP plugin includes the Eclipse plugin as well. We get all the tasks that we have seen earlier, but new tasks are also added for WTP configuration files. The task eclipseWtp depends on eclipseWtpComponent and eclipseWtpFacet, to generate the corresponding configuration files. Note that the eclipse task itself also now depends on eclipseWtp.

For each of these tasks, there is a corresponding clean task. These clean tasks will delete the configuration files.

If we execute the eclipse task, we get the following configuration files: .project, .classpath, and org.eclipse.jdt.core.prefs. We also get additional configuration files in the .settings folder, with the names org.eclipse.wst.common.component and org.eclipse.wst.common.project.facet.core.xml.

$ gradle eclipse
:eclipseClasspath
:eclipseJdt
:eclipseProject
:eclipseWtpComponent
:eclipseWtpFacet
:eclipseWtp
:eclipse

BUILD SUCCESSFUL

Total time: 4.264 secs

The contents of the .project file show that the Eclipse WTP plugin added additional natures and build commands, which is shown as follows:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        <name>chapter12</name>
        <comment>Sample project</comment>
        <projects/>
        <natures>
                <nature>org.eclipse.jdt.core.javanature</nature>
                <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
                <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
                <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
        </natures>
        <buildSpec>
                <buildCommand>
                        <name>org.eclipse.jdt.core.javabuilder</name>
                        <arguments/>
                </buildCommand>
                <buildCommand>
                        <name>org.eclipse.wst.common.project.facet.core.builder</name>
                        <arguments/>
                </buildCommand>
                <buildCommand>
                        <name>org.eclipse.wst.validation.validationbuilder</name>
                        <arguments/>
                </buildCommand>
        </buildSpec>
        <linkedResources/>
</projectDescription>

In the .classpath configuration file, an additional container named org.eclipse.jst.j2ee.internal.web.container is added, as shown in the following code snippet:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="output" path="bin"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" exported="true"/>
        <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container" exported="true"/>
        <classpathentry sourcepath="/Users/mrhaki/.gradle/caches/artifacts-14/filestore/junit/junit/4.8/source/abe171e0fc1242d1fe10e8dc43bce031e3f65560/junit-4.8-sources.jar" kind="lib" path="/Users/mrhaki/.gradle/caches/artifacts-14/filestore/junit/junit/4.8/jar/4150c00c5706306ef0f8f1410e70c8ff12757922/junit-4.8.jar" exported="true">
                <attributes>
                        <attribute name="org.eclipse.jst.component.nondependency" value=""/>
                </attributes>
        </classpathentry>
</classpath>

The contents of the org.eclipse.jdt.core.prefs file in the .settings folder are not different from the standard Eclipse plugin. The org.eclipse.wst.common.component file has the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="2.0">
        <wb-module deploy-name="chapter12">
                <property name="context-root" value="chapter12"/>
                <wb-resource deploy-path="/" source-path="src/main/webapp"/>
        </wb-module>
</project-modules>

Here, we find information for the web part of our project.

The last generated file in the .settings folder is org.eclipse.wst.common.project.facet.core.xml file, here we see the servlet and Java versions. The file has the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
        <fixed facet="jst.java"/>
        <fixed facet="jst.web"/>
        <installed facet="jst.web" version="2.4"/>
        <installed facet="jst.java" version="6.0"/>
</faceted-project>

Customizing file generation

The Eclipse WTP plugin uses the same configuration options as the standard Eclipse plugin. The plugin uses project information to set the value in the configuration files. We can use a DSL to configure the values we want in the generated files. We can also use the merge hooks and work with model objects to change information. The XML structure can be changed using the withXml hook with a configuration closure.

To use the DSL, we can add an additional wtp script block to the eclipse script block. In the wtp script block, we can change the component configuration in a component configuration closure and the facet settings in the facet configuration closure.

In the following example build file, we see some of the options we can set by using the DSL:

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'


eclipse {
    wtp {
        component {
            // Change context path of the Web application.
            // Default value is project.war.baseName.
            contextPath = '/sample-web'

            // Customize wb-resource elements of type WbResource.
            // Default for war plugin is 
            // [deployPath: '/', sourcePath: project.webAppDirName] and
            // for ear plugin is []
            resources += [deployPath: '/css', sourcePath: 'src/main/css']
            // We can also use the resource() method   resource deployPath: '/css', sourcePath: 'src/main/css'

            // Remove configurations from 
            // the deployed configurations.
            minusConfigurations += project.configurations.testCompile

            // Add dependency configurations to 
            // the deployLibPath location.
            libConfigurations += project.configurations.testCompile
   
            // Extra source directory.
            sourceDirs += file('src/main/css')
        }

        facet {
            // Add extra facet via property.
            facets += [name: 'extra', version: '1.0']

            // Or via facet() method.
            facet name: 'gradle', version: '1.1'
        }
    }
}

Another method to customize file generation is by using the merge hooks. The beforeMerged and whenMerged hooks accept a configuration closure to set properties on a model object. In the following table, we see the types of the model object that is passed as argument to the closure:

Model

Merge hook argument

Description

Component

org.gradle.plugins.ide.eclipse.model.WtpComponent

Model object with properties for org.eclipse.wst.common.component file generation.

Facet

org.gradle.plugins.ide.eclipse.model.WtpFacet

Model object with properties for org.eclipse.wst.common.project.facet.core.xml file generation.

In the following example build file, we use the merge hooks to customize the configuration:

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'

version = 1.0

description = 'Sample project'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'
}

eclipse {
    wtp {
        component {
            file { 
                beforeMerged { wtpComponent ->
                    wtpComponent.wbEntries.clear()
                }

                whenMerged { wtpComponent ->
                    wtpComponent.contextPath = '/sample-web'
                    wtpComponent.deployName = 'sample'
                }
            }
        }

        facet {
            file {
                beforeMerged { wtpFacet ->
                }

                whenMerged { wtpFacet ->
                    def java = wtpFacet.facets.find { it.facet == 'jst.java' }
                    java.version = '5.0'
                }
            }
        }
    }
}

Finally, we can manipulate the XML with the withXml hook. The argument is of type XmlProvider, just like the standard plugin. In the closure, we can change nodes and attributes.

The following example build file shows how we can manipulate the XML:

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'

version = 1.0

description = 'Sample project'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'
}

eclipse {
    wtp {
        component {
            file {
                withXml { componentXml ->
                    def root = componentXml.asNode()
                    root.'wb-module'.@'deploy-name' = 'sample'
                }
            }
        }

        facet {
            file {
                withXml { facetXml ->
                    def root = facetXml.asNode()
                    root.installed.find { it.@facet == 'jst.web' }.@version = '2.5'
                }
            }
        }
    }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.151.32