gradle: importing local bom - maven

We have a multi-module project with all dependency versions listed in the top-level pom.xml. Is there any way to make Gradle use it, without having to install this bom into local maven repo?
More specifically: there's a pom.xml listing all dependencies in the <dependencyManagement> section. Gradle build uses "io.spring.dependency-management" plugin's importBom to read it from the mavenLocal(). This works, but requires an extra step:
mvn install:install-file -Dfile=pom.xml -DpomFile=pom.xml
which publishes the bom to the local maven repository where gradle can find it. Is there any way to avoid it? Ideally I'd like to have something like this:
dependencyManagement {
imports {
mavenBom "./pom.xml"
}
}
..which of course is not a valid "string module notation". Any ideas?

To answer my own question: nebula-recommender-plugin allows import pom files directly:
dependencyRecommendations {
mavenBom file: file('pom.xml')
}

Related

Gradle: Use a sibling subproject as plugin

I have a project with two subprobjects: gradle-plugin and plugin-consumer. I want to apply the plugin from gradle-plugin to plugin-consumer. I tried to do this:
// plugin-consumer/build.gradle
buildscript {
dependencies {
classpath project(':gradle-plugin')
}
}
apply plugin: 'my.plugin.id'
But I was greeted with the following error:
A problem occurred configuring project ':plugin-consumer'.
> Cannot use project dependencies in a script classpath definition.
I assume this is not supported because it'd require fully building gradle-plugin before plugin-consumer can be configured.
Fortunately I can use a fileTree dependency to accomplish my goal:
// plugin-consumer/build.gradle
buildscript {
dependencies {
classpath fileTree(includes: ['*.jar'], dir: '../gradle-plugin/build/libs')
}
}
apply plugin: 'my.plugin.id'
This works, but it feels like a massive hack and leads to "bootstrapping problems".
For example, I can't clean gradle-plugin because the (deleted) jar file is necessary for configuring plugin-consumer, which must be done to (re)build gradle-plugin.
Fortunately this can be avoided by always running build immediately after clean (in the same 'run' so to speak). This can be done manually (gradle clean build) or automatically (with clean.finalizedBy(build)). Again, this works, but feels like a hack.
At last, my actual question: is there a better way to do this?
Please note that gradle-plugin is an independent plugin that's not only used by plugin-consumer, therefore buildSrc is unfortunately not an appropriate solution here.
You can publish the plugin to your local Maven repository with the Maven Publish plugin. Then simply consume it like any other artifact.
Assuming you have something similar in your plugin project:
plugins {
`maven-publish`
`java-gradle-plugin`
}
Simply publish it locally:
./gradlew :my-plugin-project:publishToMavenLocal
Then in your consuming project, something like:
buildscript {
repositories {
mavenLocal()
}
dependencies {
"classpath"("com.example:my-plugin-gav:1.0.0-SNAPSHOT")
}
}
// apply plugin

Replicating Maven "dependencyManagement" tag from inside Gradle build

I am trying to follow this Spring Boot/Vaadin guide however I'm using Gradle, not Maven.
At the very top of that guide they say to use the following Maven XML:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>10.0.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
However I don't see a dependencyManagement task available via Gradle. So I ask: how do I replicate the same behavior as the <dependencyManagement/> XML element above over in "Gradle land"?
Update: current attempt
dependencyManagement {
imports {
mavenBom 'com.vaadin:vaadin-bom:10.0.11'
}
}
Only problem with this is that when I add it to my build.gradle and then run ./gradlew clean I get the following Gradle error:
"Could not find method dependencyManagement() for arguments..."
This should give you a working build:
plugins {
// the Gradle plugin which provides the “dependencyManagement” block
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
// add Java build functionality to be able to follow the Vaadin guide
id 'java'
}
dependencyManagement {
imports {
// the Maven BOM which contains a coherent set of module versions
// for Vaadin dependencies
mavenBom 'com.vaadin:vaadin-bom:10.0.11'
}
}
repositories {
// find dependency modules on Maven Central
mavenCentral()
}
dependencies {
// the dependency module you need according to the Vaadin with
// Spring Boot guide; the version of the module is taken from the
// imported BOM; transitive dependencies are automatically taken
// care of by Gradle (just as with Maven)
compile 'com.vaadin:vaadin-spring-boot-starter'
}
Run ./gradlew dependencies --configuration compileClasspath to see that all dependencies are available on your Java compile classpath now.
Edited to reply to the question in the comments: indeed, the import of the BOM leads to a slightly different set of dependencies than would be used without it. You can see the dependencies difference like so:
./gradlew dependencies --configuration compileClasspath > with-BOM.txt
Remove the dependencyManagement block and add a version to the single dependency: compile 'com.vaadin:vaadin-spring-boot-starter:10.0.11'
./gradlew dependencies --configuration compileClasspath > without-BOM.txt
diff -u with-BOM.txt without-BOM.txt
You can see slight differences like org.webjars.bowergithub.webcomponents:webcomponentsjs:1.2.6 being used with the BOM and version 1.2.2 without it. The reason for that can be found in the BOM where version 1.2.6 is defined and where the authors also mention the reason for that: “Transitive webjar dependencies, defined here for repeatable builds”
Generally maven dependencyManagement tag is used to import bom or control transitive versions.
Gradle does that with platform component, like below example.
dependencies {
implementation platform('com.vaadin:vaadin-bom:10.0.11')
implementation ('com.vaadin:vaadin-core')
}
This does not force you to depend on spring plugin for importing bom.

How do I define a simple Gradle project with only a single jar file?

I have a Gradle project that depends on an external jar file. Currently I'm defining the dependency like this:
dependencies {
compile files('/path/to/my/jar/library.jar')
}
However I want to include it as a project dependency instead, like this:
dependencies {
compile project(':whatGoesHere?')
}
I assume I need to define a new Gradle project that contains the jar file but I don't know how to do this. I'm wondering about things like:
Do I just need to create a new build.gradle or are there more steps?
What would go in the build.gradle file?
Assume the new project contains nothing but the jar file (since it does). Also assume I know almost nothing about Gradle (because I don't!).
P.S. If it matters, this is an Android Gradle project.
As a roundup for our discussion, I'll bring simple example of "build.gradle" file, using maven local and maven central repositories:
apply plugin: 'maven'
apply plugin: 'java'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'commons-io:commons-io:2.4'
testCompile 'junit:junit:4.11'
}
Explanation:
"apply plugin: 'maven'" enables maven plugin, which is needed for dependency download.
"apply plugin: 'java'" enables java compilation tasks for your project.
"repositories" declares one or more repositories (maven or ivy), from where artifacts (jar libraries) will be downloaded.
"mavenLocal" refers to so-called local maven repository, which is located in "~/.m2/repository" folder on your computer. local maven repository effectively caches external repositories, but it also allows installation of local-only artifacts.
"mavenCentral" refers to maven central.
"dependencies" lists your project dependencies, either other projects or artifacts (jars).
"compile" is a configuration supported by "java" and "groovy" plugins, it tells gradle: "add these libraries to the classpath of the application during compilation phase".
"testCompile" is another configuration supported by "java" and "groovy" plugins, it tells gradle: "add these libraries to the classpath of the application during test phase".
'commons-io:commons-io:2.4' is "coordinates" of the artifact within maven repository, in form group:name:version.
You can search for well-known java libraries at address: http://mvnrepository.com/ and then include their coordinates in "build.gradle". You don't need to download anything - gradle does it for you automatically.

Importing Maven dependency

I'm trying to include ViewPagerIndicator into my project and I'd rather use the Maven dependency rather than importing the android library project. There's some code posted for maven
<dependency>
<groupId>com.viewpagerindicator</groupId>
<artifactId>library</artifactId>
<version>2.4.1</version>
<type>apklib</type>
</dependency>
and inside the sample project, that code is in a pom.xml file, but I don't have that file. Can I translate the above code into my build.gradle file? Or can I just create a pom.xml file and put it in my project?
You should ask the author JakeWharton to make an aar available on Maven Central. (vote here: https://github.com/JakeWharton/Android-ViewPagerIndicator/pull/229). Until then there is a temporary solution to use maven repo from community.
repositories {
maven {
url 'https://github.com/Goddchen/mvn-repo/raw/master/'
}
mavenCentral()
}
dependencies {
compile 'com.actionbarsherlock:viewpagerindicator:2.4.1'
}
https://github.com/Goddchen/mvn-repo
You will find the file in Maven Central which means simple run the build and the file will be downloaded. This is also true for gradle where it looks like this:
'com.viewpagerindicator', name: 'library', version: '2.4.1', ext: 'apklib'

Gradle Dependency loading from maven

I am new to gradle.
I have seen some examples about java dependency like the following example but my project will be simply a zip file.
I just want to download the zip file.
apply plugin: 'java'
dependencies {
compile 'commons-lang:commons-lang:2.6'
}
In the above example, it will automatically download the jar file. But it doesn't download my zip file if my maven repositories contains zip that mentioned in the pom.xml about that package.
Questions:
What is the flow when depend on a maven repository? It will first read the pom.xml and then download the zip file?
How to dynamically load the dependency? e.g 'commons-lang:commons-lang:2.6' will have dependency of 'commons-lang:en:1.0" in the pom.xml. How to make it automatically load and loop the dependency list?
Thanks all
I have tried the follwoing script but it gives me error on compile but I have apply the java plugin
My gradle file
apply plugin: 'java'
repositories {
mavenLocal()
maven {
url "http://nexus.com/myrepo/"
}
}
dependencies {
compile 'com.a.b:projectA:2.0#zip'
}
I can run without problem that files downloaded are inside .m2
Question about the transitive dependency
I have the pom.xml like this. But it is unable to load the dependency one. It will directly go to the new pom.xml first or download zip directly if i mention sth like this?
<dependencies>
<dependency>
<groupId>com.a.b.c</groupId>
<artifactId>base</artifactId>
<version>1.2</version>
<type>zip</type>
</dependency>
</dependencies>
When declaring a dependency and a maven repository, this maven repository will be used to resolve the artifact. this means that usually first the metadata is read and then the artifact will be downloaded. If no repository is declared the resolution will fail early.
Having a dependency notation like yours:
dependencies {
compile 'commons-lang:commons-lang:2.6'
}
gradle resolves the default artifact of that dependency. If you want to resolve additional declared zip files from maven central, you have to use this notation
repositories{
mavenCentral()
}
dependencies {
compile 'commons-lang:commons-lang:2.6#zip'
}
As a default, the a dependency is transitive. This means, that if e.g 'commons-lang:commons-lang:2.6' has a dependency on 'commons-lang:en:1.0" in its pom.xml the commons-lang library (and again its transitive dependencies if any) is also resolved.
cheers,
René

Resources