How to avoid "Entry WEB-INF/web.xml is a duplicate" on war task

I have an old Eclipse Tomcat JSP project. It got stripped of all Eclipse files and now I want to create the WAR artefact via Gradle. I whipped up a build.gradle reflecting the particularly file structure. However, on gradle clean war I get the following error:

> Task :war FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':war'.
> Entry WEB-INF/web.xml is a duplicate but no duplicate handling strategy has been set. 

I had a look at the referenced docs page, but I cannot see why WEB-INF/web.xml is copied into the same location twice. Maybe it has something to do with the definition of the sourceSets? (For my build.gradle see below.)

The directory structure of the project looks like this (I took out some source files for brevity):

.
β”œβ”€β”€ build.gradle
β”œβ”€β”€ gradle.properties
β”œβ”€β”€ settings.gradle
β”œβ”€β”€ src
β”‚   └── org
β”‚       └── grawar
β”‚           └── utils
β”‚               β”œβ”€β”€ ContextListener.java
β”‚               └── DBQuery.java
└── WebContent
    β”œβ”€β”€ Data
    β”‚   └── GetMyData.jsp
    β”œβ”€β”€ index.jsp
    β”œβ”€β”€ META-INF
    β”‚   └── MANIFEST.MF
    └── WEB-INF
        β”œβ”€β”€ lib
        └── web.xml

And here the code of my build.gradle:

plugins {
    id 'java'
    id 'war'
}

group = 'org.grawar'
version = '1.0.0'
description = 'Grawar Web Application'

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:4.0.1'
    providedCompile 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3'
    implementation 'javax.faces:javax.faces-api:2.3'
    implementation 'org.glassfish:javax.faces:2.3.9'
    implementation 'com.googlecode.json-simple:json-simple:1.1.1'
    implementation 'org.json:json:20200518'
    implementation 'org.apache.commons:commons-lang3:3.11'
    implementation 'com.oracle.database.jdbc:ojdbc8:19.8.0.0'
    implementation 'org.jasypt:jasypt:1.9.2'
    implementation 'javax.mail:javax.mail-api:1.6.2'
    implementation 'com.sun.mail:javax.mail:1.6.2'
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.mockito:mockito-core:5.4.0'
}

sourceSets {
    main {
        java {
            srcDirs = ['src']
        }
        resources {
            srcDirs = ['src']
            exclude '**/*.java'
        }
    }
    test {
        java {
            srcDirs = ['test']
        }
        resources {
            srcDirs = ['test']
            exclude '**/*.java'
        }
    }
}

war {
    enabled = true
    archiveBaseName = 'grawar'
    archiveVersion = project.version
    webAppDirectory = file('WebContent')
    from('WebContent') {
        into '/'
        exclude 'WEB-INF/classes/**'
        exclude 'WEB-INF/lib/**'  
    }
    classpath = sourceSets.main.runtimeClasspath
    webXml = file('WebContent/WEB-INF/web.xml')
}

wrapper {
    gradleVersion = '8.3'
    distributionType = Wrapper.DistributionType.BIN
}

clean {
    doLast {
        println "Build directory cleaned"
    }
}

defaultTasks 'build'

Any idea how to change the build files to avoid this error?

I would guess:

Thanks for chiming in @Vampire .

I added

       exclude 'WEB-INF/**'  

inside the from('WebContent') {…} to avoid double copying of the web.xml, but I still get the same error. Does the exclude not work as I expect it? How can i copy in all the WebContent then?

Oh, you probably had it three times actually, now two times.
I guess the webAppDirectory line above 1 does also include it once more.

I guess what you need is something like

    webAppDirectory = file('WebContent')
    exclude 'WEB-INF'
    webXml = file('WebContent/WEB-INF/web.xml')

Thanks for this.

Mmmh, when I do this the JSP files under the WebContent root (here index.jsp) are strangely not copied.

Works fine here, I just tried.
Can you knit an MCVE?

Sorry, I had some crap in my build file. When creating the MCVE I noticed that.

    webAppDirectory = file('WebContent')
    exclude 'WEB-INF'
    webXml = file('WebContent/WEB-INF/web.xml')

works. Thanks! :slight_smile:

1 Like