Override dependency jar

I would like to output a jar which internally contains my dependency jar but overrides a particular file in the dependency jar with my own. I am using gradle build. Can someone help me with this? The task which build jar for me:

jar {
  archiveName "JarName-${version}.jar"
  dependsOn configurations.runtime
  from {
    (configurations.runtime - configurations.provided).collect {
      it.isDirectory() ? it : zipTree(it)
    }
  }
}

You can remove files from dependency jar via configuration for from.

For example, copy payara-micro.jar removing jackson, and use gson as alternative of jackson, and copy the adapter jar built by you (subproject name is adapter).

dependencies {
    payaraMicro payaraMicroArtifact
    gson gsonArtifact
}
jar {
    // coping payaraMicro
    def deps = configurations.payaraMicro.findAll{!it.isDirectory()}.collect {zipTree(it)}
    from(deps) {
        // removing jackson
        exclude '**/com/fasterxml/jackson/**'
    }
    // coping gson
    from configurations.gson.findAll{!it.isDirectory()}.collect{zipTree(it)}
    // coping your jar
    from zipTree(project(':adapter').tasks.getAt('jar').archivePath)
}

I basically included the following strategy to prevent file overriding
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

It seems that the final jar initially has the root project files and then they are overridden by the dependency project files. By making overriding files not possible, the final jar had the root project files.

if you want to include root project files, please change last line of sample code
from zipTree(project(':adapter').tasks...) -> from zipTree(project.tasks.getAt('jar').archivePath)

Basically the files you want to override is not necessary, so it should be excluded from artifacts. AbstractCopy has method exclude with ant-pattern to prevent files to be packed into Jar file.

In this way, file duplication will never occur. And in the root project you should write an alternative of it.


This question is recently I tried and resolved, when removing jackson from payara-micro, and override service locators by my original service locator file.

The spec of jar I wanted is …

  • payara-micro.jar
    • jackson is not necesary
    • service locator indicates jackson, so I want to override it by my original one.
  • my original jar
    • contains alternative service locator

Then I wrote build script like this.

jar {
    // coping payaraMicro
    def payara = configurations.payaraMicro.findAll{!it.isDirectory()}.collect {zipTree(it)}
    from(payara) {
        // service locators and jackson is not needed
        exclude '**/com/fasterxml/jackson/**',
                '**/META-INF/services/javax.ws.rs.ext.Message*',
                '**/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable'
    }
    // coping genson
    def genson = configurations.genson.findAll{!it.isDirectory()}.collect{zipTree(it)}
    from(genson) {
        // service locators is not needed
        exclude '**/com/fasterxml/jackson/**',
                '**/META-INF/services/javax.ws.rs.ext.Message*',
                '**/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable'
    }
    // this jar contains alternative service locator(javax.ws.rs.ext.MessageBodyWriter... etc)
    from zipTree(tasks.getAt('jar').archivePath)
}

The point of this trick is

  • exclude file you want to override.
  • alternative of it should be provided by yourself.
  • duplicationStrategy is not needed.

I’m sorry for that I’m not good at English, so my answer became too long :wink: