How do I generate maven-metata.xml with maven-publish and the artifactory-gradle-plugin?
Asked Answered
F

4

7

I've written a Gradle plugin in groovy and used Gradle to build it. I've got a local network Artifactory server that I publish the results to using the Gradle Artifactory plugin and the maven-publish plugin in Gradle. I have another Gradle build script that relies on this plugin as a dependency. I've been able to get this all working if I list my dependency with a specific version. I've tried to use a maven version range (ex. '[1.0,2.0)'), but this fails saying it can't find maven-metadata.xml. I checked Artifactory, and sure enough, it isn't there. What do I need to do to produce it, preferably during the build of the plugin?

Here is the build.gradle file for my custom gradle plugin:

buildscript {
    repositories {
        maven {
            url "${artifactory_contextUrl}/plugins-release"
            credentials {
                username = "${artifactory_user}"
                password = "${artifactory_password}"
            }
        }
    }
    dependencies {
        classpath group: 'org.apache.directory.studio', name: 'org.apache.commons.io', version: '2.4'
        classpath group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '2.0.9'
    }
}

plugins {
    id 'com.jfrog.artifactory' version '3.0.1'
}

apply plugin: 'groovy'
apply plugin: 'maven-publish'

artifactory {
    contextUrl = "${artifactory_contextUrl}"
    publish {
        repository {
            repoKey = 'plugins-snapshot-local'
            username = "${artifactory_user}"
            password = "${artifactory_password}"
            maven = true
        }
        defaults {
            publications ('mavenJava')
        }
    }
    resolve {
        repository {
            repoKey = 'libs-release'
            username = "${artifactory_user}"
            password = "${artifactory_password}"
            maven = true
        }
    }
}

dependencies {
    compile gradleApi()
    compile localGroovy()
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

I've searched the Gradle, Artifactory, and Maven documentation to understand maven-metadata.xml and how to generate and deploy. It makes sense what it is, and I could probably build one manually, but I can't find anything that explains specifically how to automatically generate it in Gradle with either the maven-publish plugin or the artifactory-gradle-plugin. I don't want to have to manually update the file since that would defeat the automation effort, and I don't want to switch to mvn since I've already invested so much in Gradle.

Frivolity answered 3/3, 2015 at 0:20 Comment(0)
F
5

A groupId had to be added to the publications section. Once implemented, a maven-metadata.xml file was published to the artifact repository.

publishing {
    publications {
        mavenJava(MavenPublication) {
            groupId = 'com.group'
        }
    }
}
Frivolity answered 3/3, 2015 at 21:54 Comment(0)
A
1

I had the same problem and it turned out that the Artifactory repository was not a Maven repo, it was a Generic repo. It took me forever to notice because I didn't create the repo and I assumed it was a Maven repo, and deploying/resolving otherwise was working as expected.
After switching to a Maven repo, the maven-metadata.xml's were generated upon publishing.

Assist answered 6/2, 2020 at 1:33 Comment(0)
B
0

maven-metadata.xml should be handled by Artifactory. What is your local repository layout in Artifactory?

Braxy answered 3/3, 2015 at 1:39 Comment(4)
It is the default layout for plugins-release-local and plugins-snapshot-local which is maven-2-default. I should also mention that it is the Open Source version of Artifactory, so I was actually thinking it may be a feature that requires Pro or higher.Frivolity
Well, shoot. That second project I mentioned received a maven-metadata.xml file. I'm going to try the first one with a groupId to see if that makes the difference.Frivolity
Sure enough, adding a groupId caused Artifactory to generate a maven-metadata.xml file.Frivolity
I disagree. The build tool needs to check if a maven-metadata.xml already exists in the repository. If it exists, it needs to download it and update it with the new information, but appending to it. If it doesn't exist, then it needs to generate a new one. It is not the artifact repository manager to be generating this for you. Sure, it can do this, if there is a scheduled task for it, but it's actually the build and deployment tool that must handle this.Jape
F
0

The accepted answer is correct. And I upvoted it. However, there is also this caveat.

I have a multi module project, so I will use "allprojects". If you have a monolith/single-jar ( :( ).. you can use use a different scope than "allprojects".

They key here is that you set the "group". (and version as well)

allprojects {

apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'


repositories {
    jcenter()
}

group = 'com.group'

version = '1.0-SNAPSHOT'

}

Ok, now build.gradle (which in my multi-module project is not the root-build.gradle) (but values in a root build.gradle would be similar)

below is the entire contents of my non-root build.gradle file

// the "name" variable inside the publications/myPublicationName block is getting overwritten.  so create a variable here to capture the name (as the artifactid)
def artifactIdForPublicationBlockHolder = "${name}"


dependencies {
    testImplementation group: 'junit', name: 'junit', version: junitVersion
}

println("hey.here.read.me")
println("group=${group}")
println("version=${version}")
println("artifactId=${name}")


publishing {
    publications {
        myCustomPublicationName(MavenPublication) {
            // groupId, artifactId and version have defaults, so do not arbitrarily override : https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:publications

//your value below could be slightly different, look for *.jar after you do ./gradlew. build (note, this path value (of "./") is relative to the non-root-build.gradle path, not the overall root-build.gradle
"./build/libs/${artifactIdForPublicationBlockHolder}-${version}.jar"
        }
    }
}

As the link says, you'll get defaults for

// groupId, artifactId and version have defaults, so do not arbitrarily override : https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:publications

You just have to set these values, like I show above with the

group = 'com.group' 
version = '1.0-SNAPSHOT'

code

After going thru the grinder a few times with the

myCustomPublicationName(MavenPublication)

I find the least amount of stuff I custom-set, the better. and prefer to piggy back on the defaults...which means setting the values which drive the defaults... in the build.gradle .. and not to set the myCustomPublicationName(MavenPublication)

altering the values inside

myCustomPublicationName(MavenPublication)

should be reserved (IMHO) to when the defaults don't work for you. which usually is a very small minority of time.

note:

"${name}" at the top of my non-root-gradle.build is getting populated by the directory structure of my multi-module project.

i don't know how it works in a non multi-module since i never write monoliths.

settings.gradle example in my code:

rootProject.name = 'com.me.myproject-rootProjectName'

include ':source:java:mydatalayer'
include ':source:java:mybizlogic'
include ':source:java:mydomain'

Bonus Quote below:

Moreover, modular decomposition represents a key component of software quality. If you have a tightly coupled system, when you tweak one component, the whole system breaks. If you thought in terms of APIs, the intermodular boundaries are clear, so you can maintain and improve one module without affecting the others.

Massive refactorings prove difficult. If you built something as a monolithic system and then find you had repeated code all over the place, and you want to refactor it properly, you'll have a massive job. In contrast, if you wrote it as components, but you got some of the component boundaries a little wrong, you can tweak them easily.

-- Joshua Bloch, former Chief Java Architect at Google. Modular Decomposition Link

Flem answered 27/9, 2020 at 7:14 Comment(1)
The technical answer you provide is accurate and has merit. I have a word of caution. I agree wholeheartedly with the quote from Joshua Bloch, but modular decomposition is achieved through discipline alone and is not limited in the forms it can take. If you fail to correctly decompose your system with a multi-module project, you fail to gain the benefit while adding significant and needless complexity. I'm not saying you've done that, but you do seem to be confusing the discipline with a feature in a particular build tool, and especially for the uninitiated, this impression carries great risk.Frivolity

© 2022 - 2024 — McMap. All rights reserved.