Plugin enhance maven-publish plugin behaviour.
Features:
- Support gradle
java-library
plugin - Adds
optional
andprovided
configurations when used withjava
orgroovy
plugins (affect only resulted pom) - Fix dependencies scopes in generated pom
- Add
pom
configuration closure to avoid maven-publish's withXml. - Add
withPomXml
configuration closure to be able to modify xml manually (shortcut for maven-publish's withXml) - Compatible with spring's dependency management plugin
Note: Gradle 4.8 provides similar pom dsl: why pom plugin still matter
If you develop java or groovy library you may look to java-lib plugin
which already includes pom
plugin and configures maven publication for you (don't confuse with gradle's java-library plugin which only declares api and implementation configurations).
If your project is hosted on github you may look to github-info plugin which fills some pom sections for you automatically.
Also, you can use java-library generator to setup new project with all plugins configured.
- Configuration closures:
pom
,withPomXml
- Configurations:
optional
,provided
(ifjava-library
not enabled) - Enable plugins: maven-publish
IMPORTANT: version 1.3.0 and above
- Requires gradle 4.6 or above. For lower gradle use version 1.2.0.
- For gradle 4.8 and above plugin will enable STABLE_PUBLISHING preview feature -
disable lazy evaluation of publishing configuration (unification).
This is required to overcome hard to track
Cannot configure the 'publishing' extension
errors. If you need some properties to evaluate lazily wrap them inafterEvaluate
inside publishing configuration. - In gradle 5 this preview option will be enabled by default.
Releases are published to bintray jcenter, maven central and gradle plugins portal.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'ru.vyarus:gradle-pom-plugin:1.3.0'
}
}
apply plugin: 'ru.vyarus.pom'
OR
plugins {
id 'ru.vyarus.pom' version '1.3.0'
}
Plugin must be applied after java or groovy plugins. Otherwise it will do nothing.
Plugin requires java or groovy or java-library plugins to be enabled.
Plugin implicitly applies maven-publish plugin. Publication must be configured manually, for example:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
dependencies {
compile 'com.foo:dep-compile:1.0'
runtime 'com.foo:dep-runtime:1.0'
provided 'com.foo:dep-provided:1.0'
optional 'com.foo:dep-optional:1.0'
}
Plugin correct dependencies scopes according to configuration, so the resulted pom will contain:
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>dep-compile</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>dep-runtime</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>dep-provided</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>dep-optional</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
Currently (gradle 4), compile
and runtime
configurations are deprecated in favour of new java-library
plugin's
api
and implementation
. Old configurations could still be used (due to legacy reasons,
for groovy projects
or due to increased memory consumption).
Extra optional
and provided
configurations registered only if java-library
plugin not applied
(because otherwise obviously you want to use new configurations and will not use deprecated compile).
Available configurations and the resulted scope in pom:
Configuration | Pom scope |
---|---|
compile | compile |
runtime | runtime |
optional | compile (with optional marker) |
provided | provided |
compileOnly | Artifacts not present in pom |
runtimeOnly | runtime |
Plugin registers provided
and optional
configurations and makes compile
configuration extend them.
So, for gradle, provided
and optional
dependencies will work the same as compile
.
Only during pom generation plugin will detect dependencies from provided
or optional
and mark them accordingly
in generated pom.
If you want to include some other configuration dependencies as provided in pom, you can do:
configurations.provided.extendsFrom configurations.myConf
But, don't forget that compile
already extends provided
, so your configuration will be transitively included
into compile. Anyway, in resulted pom all dependencies from myConf
will have provided scope.
When java-library
plugin used, optional
and provided
configurations are not registered.
Use compileOnly
instead of provided.
Available configurations and the resulted scope in pom:
Configuration | Migrate from (legacy conf. name) | Pom scope |
---|---|---|
api | compile | compile |
implementation | compile | compile |
compileOnly | provided | Artifacts not present in pom |
runtimeOnly | runtime | runtime |
apiElements | -- | compile |
runtimeElements | -- | runtime |
Usage with dependency management plugin
Do not disable plugin's pom modifications, because without it dependencies in pom file will be without version. Plugin will generate dependencyManagement pom section, which will make pom dependencies without version valid.
By default, maven-publish plugin fills pom only with dependencies and artifact id, group and version.
Other information could be configured through pom
closure:
pom {
name 'Project Name'
description 'My awesome project'
licenses {
license {
name "The MIT License"
url "http://www.opensource.org/licenses/MIT"
distribution 'repo'
}
}
scm {
url 'https://github.com/me/my-repo.git'
connection 'scm:git@github.com:me/my-repo.git'
developerConnection 'scm:git@github.com:me/my-repo.git'
}
developers {
developer {
id "dev1"
name "Dev1 Name"
email "dev1@email.com"
}
}
}
Closure doesn't restrict structure: any tags may be used.
If name
and description
not specified, they will be applied implicitly from project.name
and project.description
.
Here is complete example of all possible maven pom sections definition (you can use any tags if needed, not just these).
If pom already have some tags (e.g. set manually with withXml or by some plugin), plugin will override values and properly merge pom. No duplicate tags will be created.
Only one pom
closure may be defined: next pom closure completely override previous one.
If multiple publications declared,
then pom closure will affect all of them. In this case, use it for general info
and use gradle native dsl for details.
As pom
closure is normal groovy closure, you may face situations when tag name clash with some method in your gradle project.
By default there is only one such case:
pom {
parent {
name 'name'
relativePath 'path'
}
}
relativePath
tag will not be present in resulted pom, because it clashes with gradle Project.relativePath method
and it will be called instead of "just holding" tag name.
Special prefix '_' may be used in such cases:
pom {
parent {
name 'name'
_relativePath 'path'
}
}
This prefix will solve clash with real method and will be dropped during xml generation. You can use this prefix with any tag.
Another (standard) solution for this problem is using delegate reference: delegate.relativePath
.
But, for me, solution with prefix is simpler and easier to read.
To test resulted pom you can use pom generation task:
$ gradlew generatePomFileForMavenJavaPublication
Note that 'MavenJava' in task name is publication name and in your case task name could be different.
Pom will be generated by default in build/publications/mavenJava/pom-default.xml
If for, some any reason, you need to modify pom manually (like in withXml closure)
you can use define withPomXml
configuration closure:
pom {
scm {
url 'https://github.com/me/my-repo.git'
connection 'scm:git@github.com:me/my-repo.git'
developerConnection 'scm:git@github.com:me/my-repo.git'
}
}
withPomXml {
it.appendNode('description', 'A demonstration of maven POM customization')
}
Generated pom xml passed to closure as parameter (no need to call asNode() as in gradle withXml block), so block above could declare parameter explicitly
withPomXml { Node node ->
node.appendNode('description', 'A demonstration of maven POM customization')
}
See Node api and groovy xml guide.
withPomXml
called just after pom
closure merging into main pom, but before applying default name and description (because you may define them manually).
So xml Node passed into closure contains all modification applied by plugin (except default name and description).
NOTE pom plugin uses withXml to apply pom modifications.
If other plugins use withXml too and these plugins registered after pom plugin, then their xml modification will be executed after pom plugin and after withPomXml
block.
Most likely, this will not be an issue, but just keep it in mind when using manual xml modifications.
Since gradle 4.8 you can use dsl like in pom plugin in raw gradle:
publishing {
publications {
maven(MavenPublication) {
from components.java
// native gradle syntax!
pom {
name = 'first'
scm {
url = "http://subversion.example.com/svn/project/trunk/"
}
}
}
}
}
So why use pom plugin now?
Because maven publication configuration could be moved to external plugin (like ru.vyarus.java-lib which configures maven-compatible publication artifacts) and, in this case, only pom should be customized:
plugins {
id 'ru.vyarus.java-lib'
}
pom {
name 'first'
scm {
url "http://subversion.example.com/svn/project/trunk/"
}
}
Also, pom plugin applies pom declaration to all registered maven publications which is useful, for example, for gradle plugin where publication is prepared by closed source plugin.
If pom plugin used together with gradle dsl then pom plugin will merge it's configuration into dsl:
plugins {
id 'ru.vyarus.pom'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
// native gradle syntax!
pom {
name = 'first'
description = 'desc'
scm {
connection = "scm:svn:http://subversion.example.com/svn/project/trunk/"
url = "http://subversion.example.com/svn/project/trunk/"
}
}
}
}
}
pom {
name 'custom name'
scm {
url "http://custom.url/"
}
}
And the resulted pom will contain:
<pom>
<name>custom name</name>
<description>desc</description>
<scm>
<connection>scm:svn:http://subversion.example.com/svn/project/trunk/</connection>
<url>http://custom.url/</url>
</scm>
</pom>
Plus, pom plugin automatically fixes dependencies scopes, which is also important.
- quality-plugin - java and groovy source quality checks
- animalsniffer-plugin - java compatibility checks
- mkdocs-plugin - project documentation generator