When maven-war-plugin builds a war file, it includes all artifact dependencies and put them into WEB-INF/lib folder, but maven-jar-plugin does not. That is why excluding works perfectly for jar, but does not work for war.

This commit provides a new method Layout.getLibrariesLocation() that returns the location of the libraries within the archive. The Jar Entries which are located in this Libraries Location should be filtered out, as the new libraries will be added at the end of the repackaging process.

fixes gh-15808

Comment From: nosan

Thanks, I spent a lot of time to find a way to rework this to use getLibraryDestination(String, LibraryScope), and telling the truth I don't know how it can be done at the moment.

this method will return the wrong location for a provided artifact in a war – it will return WEB-INF/lib when it should return WEB-INF/lib-provided.

maven-war-plugin does not include provided dependencies.

Here is a small background why excluding is not working for WAR.

RepackageMojo:


    private void repackage() throws MojoExecutionException {
       // (1)
        Artifact source = getSourceArtifact();
        File target = getTargetFile();
        Repackager repackager = getRepackager(source.getFile());
        // (2)
        Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(), getFilters(getAdditionalFilters()));
        //(3)
        Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack, getLog()); 
        try {
            LaunchScript launchScript = getLaunchScript();
            repackager.repackage(target, libraries, launchScript);
        }
        catch (IOException ex) {
            throw new MojoExecutionException(ex.getMessage(), ex);
        }
        updateArtifact(source, target, repackager.getBackupFile());
    }

  1. a source war has already had WEB-INF/lib folder which has been added by maven-war-plugin before.
  2. RepackageMojo filters all dependencies using the filters. (such as excludeGroupIds, )
  3. RepackageMojo creates ArtifactsLibraries which includes only filtered libraries.

then, Repackager tries to repackage the sourceJar using the given libraries and other parameters:

Repackager: ```java private void repackage(JarFile sourceJar, File destination, Libraries libraries, LaunchScript launchScript) throws IOException {

// (1)
WritableLibraries writeableLibraries = new WritableLibraries(libraries);
try (JarWriter writer = new JarWriter(destination, launchScript)) {
    writer.writeManifest(buildManifest(sourceJar));
    writeLoaderClasses(writer);
    if (this.layout instanceof RepackagingLayout) {
    // (2)
        writer.writeEntries(sourceJar,
                new RenamingEntryTransformer(((RepackagingLayout) this.layout).getRepackagedClassesLocation()), writeableLibraries);
    }
    else {
    // (2)
        writer.writeEntries(sourceJar, writeableLibraries);
    }



    // (3)

    writeableLibraries.write(writer);
}

}

```

  1. Source jar has already had WEB-INF/lib folder with dependencies, as maven-war-plugin includes all compile dependencies and put them beneath WEB-INF/lib folder.
  2. JarWriter adds all jar entries from sourceJar into the destination. (including WEB-INF/lib)
  3. Write libraries

So, summarizing the above I can not understand how getLibraryDestination(String, LibraryScope) can help here. In my opinion, JarWriter should avoid any libraries, because for this purpose WritableLibraries is responsible. Currently, there is no way to exclude/filter jar entries during the JarWriter.writeEntries process.

Comment From: wilkinsona

maven-war-plugin does not include provided dependencies.

Unfortunately, I don't think that helps here. I really don't want to add a public API that only gives the right answer when used in one particular scenario.

It sounds like we need to find a different approach to solving this one. Thanks anyway for your efforts.