Search code examples
mavenpom.xmlgradle-2

How to maven-publish a Gradle project JAR with provided scope


Given a Gradle web project that is to be published as a JAR (so that it can be a dependency of another Gradle web project, which has a different release cycle).

The maven-publish plugin is used:

apply plugin: 'war'
apply plugin: 'maven'
apply plugin: 'maven-publish'

The web project has a providedCompile dependency:

providedCompile 'javax.servlet:javax.servlet-api:3.0.1'

A jar is published using mavenJava:

publishing {
    publications {
        // mavenJava publishes a jar file
        mavenJava(MavenPublication) {
            from components.java
        }
    }
    repositories {
        mavenLocal()
    }
}

The problem is that javax.servlet-api has a runtime scope in the resulting Maven POM:

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.0.1</version>
  <scope>runtime</scope>
</dependency>

Runtime scope makes no sense for the servlet-api, it is even harmful. How can the scope be set to provided in the pom.xml?


Solution

  • With the help of pom.withXml (see this Gradle sample) it's possible to transform Gradle's providedCompile into provided scope for Maven's POM:

    publishing {
        publications {
            mavenJava(MavenPublication) {
                from components.java
    
                // providedCompile -> provided scope
                pom.withXml {
                    asNode().dependencies.'*'.findAll() {
                        it.scope.text() == 'runtime'  && project.configurations.providedCompile.allDependencies.find { dep ->
                            dep.name == it.artifactId.text()
                        }
                    }.each() {
                        it.scope*.value = 'provided'
                    }
                }
            }
        }
        repositories {
            mavenLocal()
        }
    }
    

    What the pom.withXml section does is going through all dependencies of type providedCompile within the Gradle project configuration and changing the scope to be written into the Maven pom.xml from runtime to provided.

    The generated pom.xml now has the provided scope set for the javax.servlet-api:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        [...]
        <dependencies>
            [...]
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.0.1</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </project>