# The Ear Plugin

version 9.7.0-rc-2

The Ear plugin adds support for assembling web application EAR files. It adds a default EAR archive task. It doesn’t require the Java plugin, but for projects that also use the Java plugin it disables the default JAR archive generation.

## Usage

To use the Ear plugin, include the following in your build script:

build.gradle.kts

    plugins {
        ear
    }

build.gradle

    plugins {
        id 'ear'
    }

## Tasks

The Ear plugin adds the following tasks to the project.

`ear` — Ear

  Depends on: `compile` (only if the Java plugin is also applied)

  Assembles the application EAR file.

### Dependencies added to other tasks

The Ear plugin adds the following dependencies to tasks added by the Base Plugin.

`assemble`

  Depends on: `ear`.

## Project layout

    .
    └── src
        └── main
            └── application (1)

1 | Ear resources, such as a META-INF directory

## Dependency management

The Ear plugin adds two dependency configurations: `deploy` and `earlib`. All dependencies in the `deploy` configuration are placed in the root of the EAR archive, and are not transitive. All dependencies in the `earlib` configuration are placed in the 'lib' directory in the EAR archive and are transitive.

## Ear

The default behavior of the Ear task is to copy the content of `src/main/application` to the root of the archive. If your `application` directory doesn’t contain a `META-INF/application.xml` deployment descriptor then one will be generated for you.

The Ear class in the API documentation has additional useful information.

## Customizing

Here is an example with the most important customization options:

build.gradle.kts

    plugins  {
        ear
        java
    }

    repositories { mavenCentral() }

    dependencies {
        // The following dependencies will be the ear modules and
        // will be placed in the ear root
        deploy(project(path = ":war", configuration = "war"))

        // The following dependencies will become ear libs and will
        // be placed in a dir configured via the libDirName property
        earlib("log4j:log4j:1.2.15@jar")
    }

    tasks.ear {
        appDirectory = file("src/main/app")  // use application metadata found in this folder
        libDirName = "APP-INF/lib" // put dependent libraries into APP-INF/lib inside the generated EAR
        deploymentDescriptor {  // custom entries for application.xml:
    //      fileName = "application.xml"  // same as the default value
    //      version = "6"  // same as the default value
            applicationName = "customear"
            initializeInOrder = true
            displayName = "Custom Ear"  // defaults to project.name
            // defaults to project.description if not set
            description = "My customized EAR for the Gradle documentation"
    //      libraryDirectory = "APP-INF/lib"  // not needed, above libDirName setting does this
    //      module("my.jar", "java")  // won't deploy as my.jar isn't deploy dependency
    //      webModule("my.war", "/")  // won't deploy as my.war isn't deploy dependency
            securityRole("admin")
            securityRole("superadmin")
            withXml { // add a custom node to the XML
                asElement().apply {
                    appendChild(ownerDocument.createElement("data-source").apply { textContent = "my/data/source" })
                }
            }
        }
    }

build.gradle

    plugins {
        id 'ear'
        id 'java'
    }

    repositories { mavenCentral() }

    dependencies {
        // The following dependencies will be the ear modules and
        // will be placed in the ear root
        deploy project(path: ':war', configuration: 'war')

        // The following dependencies will become ear libs and will
        // be placed in a dir configured via the libDirName property
        earlib("log4j:log4j:1.2.15@jar")
    }

    tasks.named('ear') {
        appDirectory = file('src/main/app')  // use application metadata found in this folder
        libDirName = 'APP-INF/lib' // put dependent libraries into APP-INF/lib inside the generated EAR
        deploymentDescriptor {  // custom entries for application.xml:
    //      fileName = "application.xml"  // same as the default value
    //      version = "6"  // same as the default value
            applicationName = "customear"
            initializeInOrder = true
            displayName = "Custom Ear"  // defaults to project.name
            // defaults to project.description if not set
            description = "My customized EAR for the Gradle documentation"
    //      libraryDirectory = "APP-INF/lib"  // not needed, above libDirName setting does this
    //      module("my.jar", "java")  // won't deploy as my.jar isn't deploy dependency
    //      webModule("my.war", "/")  // won't deploy as my.war isn't deploy dependency
            securityRole("admin")
            securityRole("superadmin")
            withXml { provider -> // add a custom node to the XML
                provider.asNode().appendNode("data-source", "my/data/source")
            }
        }
    }

You can also use customization options that the Ear task provides, such as `from` and `metaInf`.

## Skinny WAR Pattern

The Ear plugin supports the Skinny WAR deployment pattern, where shared libraries are placed in the EAR’s `lib` directory rather than being packaged within individual WAR files.

### Basic Skinny WAR Setup

To implement the Skinny WAR pattern, configure your multi-module project with separate `war` and `ear` modules:

Project structure

    .
    ├── settings.gradle.kts
    ├── war/ (1)
    │   └── src/main/
    │       ├── java/
    │       └── webapp/
    └── ear/ (2)
        └── src/main/application/
            └── META-INF/
                └── application.xml

1 | Contains web application code and resources, produces skinny WAR with compileOnly dependencies
2 | Assembles complete enterprise application, packages WAR and shared libraries in lib directory

### WAR Module Configuration

Configure the WAR module to use `compileOnly` dependencies for libraries that will be provided by the EAR:

Example 1. WAR module build script
build.gradle.kts

    plugins {
        war
    }

    repositories {
        mavenCentral()
    }

    configurations {
        create("war") {
            isCanBeResolved = false
            outgoing {
                artifact(tasks["war"])
            }
        }
    }

    dependencies {
        // Shared libraries provided by parent EAR - use compileOnly to avoid packaging in WAR
        compileOnly("org.apache.commons:commons-lang3:3.14.0")
    }

build.gradle

    plugins {
        id 'war'
    }

    repositories {
        mavenCentral()
    }

    configurations {
        war {
            canBeResolved = false
            outgoing {
                artifact(tasks.war)
            }
        }
    }

    dependencies {
        // Shared libraries provided by parent EAR - use compileOnly to avoid packaging in WAR
        compileOnly 'org.apache.commons:commons-lang3:3.14.0'
    }

### EAR Module Configuration

Configure the EAR module to include the WAR and place shared libraries in the `lib` directory:

Example 2. EAR module build script
build.gradle.kts

    plugins {
        ear
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        // Include WAR module in EAR
        deploy(project(":war", "war"))

        // Shared libraries placed in EAR/lib directory
        earlib("org.apache.commons:commons-lang3:3.14.0")
    }

build.gradle

    plugins {
        id 'ear'
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        // Include WAR module in EAR
        deploy project(path: ':war', configuration: 'war')

        // Shared libraries placed in EAR/lib directory
        earlib 'org.apache.commons:commons-lang3:3.14.0'
    }

### Runtime Library Resolution

In the Skinny WAR pattern, shared dependencies are centralized in the EAR’s `lib` directory instead of being duplicated in each WAR file. The generated EAR file structure demonstrates this dependency organization:

    ear.ear
    ├── META-INF/
    │   ├── MANIFEST.MF
    │   └── application.xml
    ├── lib/
    │   └── commons-lang3-3.14.0.jar
    └── war.war (skinny WAR - no shared libraries)

## Using custom descriptor file

You may already have appropriate settings in a `application.xml` file and want to use that instead of configuring the `ear.deploymentDescriptor` section of the build script. To accommodate that goal, place the `META-INF/application.xml` in the right place inside your source folders (see the `appDirName` property). The file contents will be used and the explicit configuration in the `ear.deploymentDescriptor` will be ignored.