Code Monkey home page Code Monkey logo

nebula-dependency-recommender-plugin's Introduction

Maintenance Mode Support

We don't plan add new functionality to this plugin. We focus mainly on compatibility with new version of Gradle.

Much of the functionality of this project can be replicated by a new feature coming in Gradle 4.6 and the default in Gradle 5.0. We would recommend new users seeking this functionality to adopt the feature directly from the Gradle. You can find details Sharing dependency versions between projects

We are actively working on switching from this plugin to Gradle Platform support too with eventual long term goal to deprecate this plugin.

Nebula Dependency Recommender

Support Status Gradle Plugin Portal Maven Central Build Apache 2.0

A Gradle plugin that allows you to leave off version numbers in your dependencies section and have versions recommended by several possible sources. The most familiar recommendation provider that is supported is the Maven BOM (i.e. Maven dependency management metadata). The plugin will control the versions of any dependencies that do not have a version specified.

Table of Contents

1. Dependency recommender configuration

Dependency recommenders are the source of versions. If more than one recommender defines a recommended version for a module, the last recommender specified will win.

dependencyRecommendations {
  propertiesFile uri: 'http://somewhere/extlib.properties', name: 'myprops'
}

dependencies {
  nebulaRecommenderBom 'netflix:platform:latest.release@pom'
  implementation 'com.google.guava:guava' // no version, version is recommended
  implementation 'commons-lang:commons-lang:2.6' // I know what I want, don't recommend
  implementation project.recommend('commmons-logging:commons-logging', 'myprops') // source the recommendation from the provider named myprops'
}

You can also specify bom lookup via a configuration

dependencies {
  nebulaRecommenderBom 'test.nebula:bom:1.0.0@pom'
}

2. Built-in recommendation providers

Several recommendation providers pack with the plugin. The file-based providers all a shared basic configuration that is described separately.

3. Producing a Maven BOM for use as a dependency recommendation source

Suppose you want to produce a BOM that contains a recommended version for commons-configuration.

buildscript {
    repositories { mavenCentral() }
    dependencies { classpath 'com.netflix.nebula:nebula-dependency-recommender:4.+' }
}

apply plugin: 'maven-publish'
apply plugin: 'com.netflix.nebula.dependency-recommender'

group = 'netflix'

configurations { implementation }
repositories { mavenCentral() }

dependencies {
   implementation 'commons-configuration:commons-configuration:1.6'
}

publishing {
    publications {
        parent(MavenPublication) {
            // the transitive closure of this configuration will be flattened and added to the dependency management section
            nebulaDependencyManagement.fromConfigurations { configurations.implementation }

            // alternative syntax when you want to explicitly add a dependency with no transitives
            nebulaDependencyManagement.withDependencies { 'manual:dep:1' }

            // the bom will be generated with dependency coordinates of netflix:module-parent:1
            artifactId = 'module-parent'
            version = 1

            // further customization of the POM is allowed if desired
            pom.withXml { asNode().appendNode('description', 'A demonstration of maven POM customization') }
        }
    }
    repositories {
        maven {
           url "$buildDir/repo" // point this to your destination repository
        }
    }
}

The resultant BOM would look like this:

<?xml version="1.0" encoding="UTF-8"?>
<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>
  <groupId>netflix</groupId>
  <artifactId>module-parent</artifactId>
  <version>1</version>
  <packaging>pom</packaging>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>commons-digester</groupId>
        <artifactId>commons-digester</artifactId>
        <version>1.8</version>
      </dependency>
      <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
      </dependency>
      <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
      </dependency>
      <dependency>
        <groupId>commons-configuration</groupId>
        <artifactId>commons-configuration</artifactId>
        <version>1.6</version>
      </dependency>
      <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.7.0</version>
      </dependency>
      <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
      </dependency>
      <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils-core</artifactId>
        <version>1.8.0</version>
      </dependency>
      <dependency>
        <groupId>manual</groupId>
        <artifactId>dep</artifactId>
        <version>1</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <description>A demonstration of maven POM customization</description>
</project>

4. Version selection rules

The hierarchy of preference for versions is:

4.1. Forced dependencies

configurations.all {
    resolutionStrategy {
        force 'commons-logging:commons-logging:1.2'
    }
}

dependencyRecommendations {
   map recommendations: ['commons-logging:commons-logging': '1.1']
}

dependencies {
   implementation 'commons-logging:commons-logging' // version 1.2 is selected
}

4.2. Direct dependencies with a version qualifier

Direct dependencies with a version qualifier trump recommendations, even if the version qualifier refers to an older version.

dependencyRecommendations {
   map recommendations: ['commons-logging:commons-logging': '1.2']
}

dependencies {
   implementation 'commons-logging:commons-logging:1.0' // version 1.0 is selected
}

4.3. Dependency recommendations

This is the basic case described elsewhere in the documentation;

dependencyRecommendations {
   map recommendations: ['commons-logging:commons-logging': '1.0']
}

dependencies {
   implementation 'commons-logging:commons-logging' // version 1.0 is selected
}

4.4. Transitive dependencies

Transitive dependencies interact with the plugin in different ways depending on which of two available strategies is selected.

4.4.1. ConflictResolved Strategy (default)

Consider the following example with dependencies on commons-configuration and commons-logging. commons-configuration:1.6 depends on commons-logging:1.1.1. In this case, the transitive dependency on commons-logging via commons-configuration is conflict resolved against the recommended version of 1.0 if we have a direct on commons-logging. Normal Gradle conflict resolution selects 1.1.1.

dependencyRecommendations {
   strategy ConflictResolved // this is the default, so this line is NOT necessary
   map recommendations: ['commons-logging:commons-logging': '1.0']
}

dependencies {
   implementation 'commons-logging:commons-logging'
   implementation 'commons-configuration:commons-configuration:1.6'
}

4.4.2. OverrideTransitives Strategy

In the following example version commons-logging:commons-logging:1.0 is selected even though commons-logging is not explicitly mentioned in dependencies. This would not work with the ConflictResolved strategy:

dependencyRecommendations {
   strategy OverrideTransitives
   map recommendations: ['commons-logging:commons-logging': '1.0']
}

dependencies {
   implementation 'commons-configuration:commons-configuration:1.6'
}

4.4.3. Bubbling up recommendations from transitives

If no recommendation can be found in the recommendation sources for a dependency that has no version, but a version is provided by a transitive, the version provided by the transitive is applied. In this scenario, if several transitives provide versions for the module, normal Gradle conflict resolution applies.

dependencyRecommendations {
   map recommendations: ['some:other-module': '1.1']
}

dependencies {
   implementation 'commons-configuration:commons-configuration:1.6'
   implementation 'commons-logging:commons-logging' // version 1.1.1 is selected
}

5. Conflict resolution and transitive dependencies

6. Accessing recommended versions directly

The dependencyRecommendations container can be queried directly for a recommended version:

dependencyRecommendations.getRecommendedVersion('commons-logging', 'commons-logging')

The getRecommendedVersion method returns null if no recommendation is found.

7. Strict Mode

dependencyRecommendations {
    strictMode = true
}

Strict mode will cause the plugin to fail if a dependency version is omitted and not found in a recommendation source.

8. Notes on POMs Generated by Gradle maven-publish

Gradle requires that version numbers are present in the dependencies block to create a valid POM file that includes version numbers. To fix the issue this causes when using the dependency-recommender plug-in, apply the nebula.maven-resolved-dependencies plug-in from the nebula-publishing-plugin set.

nebula-dependency-recommender-plugin's People

Contributors

ash211 avatar billbindi avatar brharrington avatar chali avatar danhyun avatar danielthomas avatar emccallum avatar jkschneider avatar jmcampanini avatar markelliot avatar nadavc avatar noel-yap avatar odysseuslives avatar quidryan avatar rbrindl avatar romeara avatar rpalcolea avatar rspieldenner avatar sghill avatar the-alchemist avatar zyxist avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nebula-dependency-recommender-plugin's Issues

Honour Maven excludes in dependency-recommender

Producing and consuming BOMs is a great mechanism for providing library consumers with a set of known compatible dependency versions. A missing piece is for it to also honor and "recommend" dependency exclusions; Maven of course has such a mechanism (https://maven.apache.org/pom.html#Exclusions), but the Gradle Maven resolution does not currently implement it.

Would you be interested in taking a PR that implements the following feature? "When supplying version recommendations from a BOM, remove dependencies (including transitives) that were labeled as being excluded in the BOM."

Resolve errors with copied configuration [4.2.1, Gradle 4.0]

Setup

Showing only relevant files:

├── build.gradle
├── foo
│   └── build.gradle
├── settings.gradle
└── versions.props

settings.gradle

include 'foo'

build.gradle

plugins {
  id "nebula.dependency-recommender" version "4.2.1"
}

allprojects {
  apply plugin: 'nebula.dependency-recommender'
  repositories {
    mavenCentral()
  }
  dependencyRecommendations {
    strategy OverrideTransitives
    def projectVersionsFile = file("${projectDir}/versions.props")
    if (projectVersionsFile.exists()) {
        propertiesFile file: projectVersionsFile
    }
  }
}

versions.props

ch.qos.logback:logback-core = 1.1.7

foo/build.gradle

apply plugin: 'java'

dependencies {
  compile "ch.qos.logback:logback-core"
}

def resolvedArtifacts = configurations.runtime.copyRecursive()
            .exclude(group: 'org.immutables')
            .resolvedConfiguration

Result

(stripped a few irrelevant configurations)

./gradlew foo:dependencies

> Task :foo:dependencies

------------------------------------------------------------
Project :foo
------------------------------------------------------------

...

compile - Dependencies for source set 'main' (deprecated, use 'implementation ' instead).
\--- ch.qos.logback:logback-core: -> 1.1.7

default - Configuration for default artifacts.
\--- ch.qos.logback:logback-core: -> 1.1.7

runtime - Runtime dependencies for source set 'main' (deprecated, use 'runtimeOnly ' instead).
\--- ch.qos.logback:logback-core: FAILED

runtimeClasspath - Runtime classpath of source set 'main'.
\--- ch.qos.logback:logback-core: -> 1.1.7

...

Expected

If I remove the .resolvedConfiguration call from foo/build.gradle, runtime is evaluated just fine.

./gradlew foo:dependencies --configuration runtime

> Task :foo:dependencies

------------------------------------------------------------
Project :foo
------------------------------------------------------------

runtime - Runtime dependencies for source set 'main' (deprecated, use 'runtimeOnly ' instead).
\--- ch.qos.logback:logback-core: -> 1.1.7


BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

Support trailing line comments in properties files

I expected to be able to put end-of-line comments in a properties file like this:

com.squareup.retrofit2:* = 2.1.0
javax.ws.rs:javax.ws.rs-api = 2.0.1
org.apache.arrow:arrow-vector = 0.2.0  # because the X Y Z
org.antlr:antlr4 = 4.7

But then that thinks the version of org.apache.arrow:arrow-vector is 0.2.0 # because the X Y Z which obviously fails to resolve from Maven...

Instead I have to move the comment above the dependency, like this:

com.squareup.retrofit2:* = 2.1.0
javax.ws.rs:javax.ws.rs-api = 2.0.1
# because the X Y Z
org.apache.arrow:arrow-vector = 0.2.0
org.antlr:antlr4 = 4.7

which breaks sorting in the file.

Would you support a PR to enable the syntax in the first example, with the trailing end-of-line comments? I think it can be done in a similar way to ColonFilteringReader in https://github.com/nebula-plugins/nebula-dependency-recommender-plugin/blob/master/src/main/groovy/netflix/nebula/dependency/recommender/provider/PropertyFileRecommendationProvider.java

java plugin required when using recommender plugin

$ cat build.gradle
apply plugin: 'nebula'
apply plugin: 'nebula.dependency-recommender'
apply plugin: 'netflix.bom-publish'

dependencyRecommendations {
map recommendations: [ 'com.google.inject.extensions:guice-servlet': '4.0' ]
}

dependencies {
recommendation 'com.sun.jersey.contribs:jersey-guice:1.19'
}
$ ./gradlew dependencyInsight --dependency guice-servlet --configuration recommendation
...
:dependencyInsight
com.google.inject.extensions:guice-servlet:3.0 :broken_heart:
--- com.sun.jersey.contribs:jersey-guice:1.19
--- recommendation

$ cat build.gradle
apply plugin: 'nebula'
apply plugin: 'nebula.dependency-recommender'
apply plugin: 'netflix.bom-publish'

apply plugin: 'java' 💙

dependencyRecommendations {
map recommendations: [ 'com.google.inject.extensions:guice-servlet': '4.0' ]
}

dependencies {
recommendation 'com.sun.jersey.contribs:jersey-guice:1.19'
}

$ ./gradlew dependencyInsight --dependency guice-servlet --configuration recommendation
...
:dependencyInsight
com.google.inject.extensions:guice-servlet:4.0 (selected by rule) :green_heart:

com.google.inject.extensions:guice-servlet:3.0 -> 4.0
--- com.sun.jersey.contribs:jersey-guice:1.19
--- recommendation

ConcurrentModificationException in FuzzyVersionResolver

When using 5.0.0 of the nebula-dependency-recommender, I get the following stacktrace:

java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
        at java.util.ArrayList$Itr.next(ArrayList.java:851)
        at netflix.nebula.dependency.recommender.provider.FuzzyVersionResolver.versionOf(FuzzyVersionResolver.java:36)
        at netflix.nebula.dependency.recommender.provider.PropertyFileRecommendationProvider.getVersion(PropertyFileRecommendationProvider.java:39)
        at netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer.getRecommendedVersion(RecommendationProviderContainer.java:158)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:169)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:173)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$1.execute(DependencyRecommendationsPlugin.java:91)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$1.execute(DependencyRecommendationsPlugin.java:78)
        at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencySubstitutions$DependencyResolveDetailsWrapperAction.execute(DefaultDependencySubstitutions.java:249)
        at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencySubstitutions$DependencyResolveDetailsWrapperAction.execute(DefaultDependencySubstitutions.java:236)
        at org.gradle.internal.Actions$CompositeAction.execute(Actions.java:79)
        at org.gradle.internal.Actions$CompositeAction.execute(Actions.java:79)
        at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencySubstitutionApplicator.apply(DefaultDependencySubstitutionApplicator.java:34)
        at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.CachingDependencySubstitutionApplicator.apply(CachingDependencySubstitutionApplicator.java:44)
        at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionResolver.resolve(DependencySubstitutionResolver.java:34)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.SelectorState.resolveModuleRevisionId(SelectorState.java:99)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.resolveModuleRevisionId(EdgeState.java:91)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.performSelectionSerially(DependencyGraphBuilder.java:261)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolveEdges(DependencyGraphBuilder.java:226)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.traverseGraph(DependencyGraphBuilder.java:143)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:109)
        at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver.resolve(DefaultArtifactDependencyResolver.java:90)
        at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolveGraph(DefaultConfigurationResolver.java:146)
        at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolveGraph(ShortCircuitEmptyConfigurationResolver.java:73)
        at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolveGraph(ErrorHandlingConfigurationResolver.java:66)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$4.run(DefaultConfiguration.java:483)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveGraphIfRequired(DefaultConfiguration.java:474)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveToStateOrLater(DefaultConfiguration.java:459)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1700(DefaultConfiguration.java:116)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getSelectedArtifacts(DefaultConfiguration.java:901)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:889)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:404)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolve(DefaultConfiguration.java:400)
        at org.gradle.api.artifacts.Configuration$resolve$1.call(Unknown Source)
        at com.palantir.configurationresolver.ResolveConfigurationsTask$_resolveAllConfigurations_closure1.doCall(ResolveConfigurationsTask.groovy:31)
        at sun.reflect.GeneratedMethodAccessor650.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
        at groovy.lang.Closure.call(Closure.java:414)
        at groovy.lang.Closure.call(Closure.java:430)
        at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:71)
        at org.gradle.util.ConfigureUtil.configureTarget(ConfigureUtil.java:160)
        at org.gradle.util.ConfigureUtil.configure(ConfigureUtil.java:106)
        at org.gradle.util.ConfigureUtil$1.execute(ConfigureUtil.java:123)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:136)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:154)
        at org.gradle.api.DomainObjectCollection$all.call(Unknown Source)
        at com.palantir.configurationresolver.ResolveConfigurationsTask.resolveAllConfigurations(ResolveConfigurationsTask.groovy:24)
        at sun.reflect.GeneratedMethodAccessor789.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:780)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:747)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
        at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipCachedTaskExecuter.execute(SkipCachedTaskExecuter.java:108)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ResolveBuildCacheKeyExecuter.execute(ResolveBuildCacheKeyExecuter.java:61)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:60)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:626)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:581)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.lang.Thread.run(Thread.java:748)

It appears that putting a lock around the FuzzyVersionResolver glob cache would fix this.

Error when applying the plugin

Hi, I'm using Gradle 4.10.3 and when I'm applying the latest version 7.2.1, I get the below error. I tried to use other Gradle versions, cleaning up my .gradle folders but nothing change. Any idea why?

* What went wrong:
An exception occurred applying plugin request [id: 'nebula.dependency-recommender', version: '7.2.1']
> Failed to apply plugin [id 'nebula.dependency-recommender']
   > Could not create an instance of type netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer_Decorated.
      > com/google/common/base/Supplier

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.plugins.InvalidPluginException: An exception occurred applying plugin request [id: 'nebula.dependency-recommender', version: '7.2.1']
        at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.exceptionOccurred(DefaultPluginRequestApplicator.java:247)
        at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:229)
        at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:148)
        at org.gradle.kotlin.dsl.provider.PluginRequestsHandler.handle(PluginRequestsHandler.kt:49)
        at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator$InterpreterHost.applyPluginsTo(KotlinScriptEvaluator.kt:183)
        at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.applyPluginsTo(Interpreter.kt:356)
        at Program.execute(Unknown Source)
        at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:498)
        at org.gradle.kotlin.dsl.execution.Interpreter.eval(Interpreter.kt:164)
        at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator.evaluate(KotlinScriptEvaluator.kt:112)
        at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:51)
        at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:36)
        at org.gradle.kotlin.dsl.provider.KotlinScriptPlugin.apply(KotlinScriptPlugin.kt:34)
        at org.gradle.configuration.BuildOperationScriptPlugin$1$1.run(BuildOperationScriptPlugin.java:69)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:66)
        at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:63)
        at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:48)
        at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:63)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:41)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
        at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:105)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:687)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:140)
        at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:60)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:41)
        at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuild.run(DefaultGradleLauncher.java:274)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.initialization.DefaultGradleLauncher.configureBuild(DefaultGradleLauncher.java:182)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:141)
        at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:124)
        at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:77)
        at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:74)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:154)
        at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:38)
        at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:96)
        at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:74)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.run(RunAsBuildOperationBuildActionRunner.java:50)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:44)
        at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:79)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:44)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:80)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:53)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:62)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:34)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:59)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:31)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:59)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:44)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:46)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:81)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin [id 'nebula.dependency-recommender']
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:160)
        at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:130)
        at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator$3.run(DefaultPluginRequestApplicator.java:151)
        at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:225)
        ... 110 more
Caused by: org.gradle.api.reflect.ObjectInstantiationException: Could not create an instance of type netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer_Decorated.
        at org.gradle.internal.reflect.DirectInstantiator.newInstance(DirectInstantiator.java:53)
        at org.gradle.api.internal.ClassGeneratorBackedInstantiator.newInstance(ClassGeneratorBackedInstantiator.java:36)
        at org.gradle.api.internal.plugins.DefaultConvention.instantiate(DefaultConvention.java:264)
        at org.gradle.api.internal.plugins.DefaultConvention.create(DefaultConvention.java:144)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.apply(DependencyRecommendationsPlugin.java:56)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.apply(DependencyRecommendationsPlugin.java:47)
        at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:42)
        at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:50)
        at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:174)
        at org.gradle.api.internal.plugins.DefaultPluginManager.access$300(DefaultPluginManager.java:50)
        at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:264)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:152)
        at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:149)
        at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:48)
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:149)
        ... 113 more
Caused by: java.lang.NoClassDefFoundError: com/google/common/base/Supplier
        at netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer.getMavenBomRecommendationProvider(RecommendationProviderContainer.java:71)
        at netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer.<init>(RecommendationProviderContainer.java:62)
        at netflix.nebula.dependency.recommender.provider.RecommendationProviderContainer_Decorated.<init>(Unknown Source)
        at org.gradle.internal.reflect.DirectInstantiator.newInstance(DirectInstantiator.java:51)
        ... 132 more
Caused by: java.lang.ClassNotFoundException: com.google.common.base.Supplier
        ... 136 more

FuzzyVersionResolver: clearly defining and improving syntax

Currently, FuzzyVersionResolver seems to support * wildcards in selectors. While this makes sense, the mechanism for doing so uses a regex conversion, which fails to quote the rest of the string. As such, com.mycompany.extensions would match com-mycompany-extensions since the rest of the string is interpreted as (modified) regex.

As a secondary concern, currently nested dependency overrides are not supported (e.g. I cannot specify com.mycompany.group:myapp-* as one version, but set com.mycompany.group:myapp-utils-* to some other version, e.g. due to independent versioning. Currently, if multiple glob-style overrides apply to one version, the glob used seems to be undefined (e.g. HashMap order).

Combining these concerns, I'd propose canonicalizing syntax some more, with the following rules:

  1. The only control characters are : and *; the former is the group-module separator, and the latter is a wildcard character matcher. All other characters will be matched literally.
  2. Exact module match is tested first. After that, glob matchers are tested in order of decreasing specificity (where specificity = number of non-wildcard characters).

Mostly, I'd like to enable the workflow of "obvious nested wildcard overrides", i.e.

com.mycompany.group:myapp-* = 1.0.1
com.mycompany.group:myapp-utils-* = 2.2.1

with the regex-escaping issue as incidental cleanup.

dependency recommender fails when trying to use org.jboss:jboss-eap-client

I am trying to use the nebula.dependency-recommender plugin to pull in JBoss client jars for a standalone application that must access ejbs on a remote JBoss server. I also use the shadow plugin to pull the dependent classes into the jar I'm building

I thought that I had the plugin working fine, and that the plugin was a really slick job, but I found I was missing a jar, so I thought I'd simply include it using the same mechanism:

apply plugin: 'nebula.dependency-recommender'
...
dependencyRecommendations {
	mavenBom module: 'org.jboss.bom:eap-runtime-artifacts:7.0.0.GA'
}
...

dependencies {
...	
     compile ('org.jboss:jboss-remote-naming')
}

This works just fine.

But now when I try to add a second dependency from the jboss runtime artifacts:

dependencies {
...
	compile ('org.jboss:jboss-remote-naming')
	compile ('org.jboss:jboss-eap-client')
}

I get the following weird error message:

FAILURE: Build failed with an exception.

* What went wrong:
Could not resolve all dependencies for configuration ':server:runtime'.
> Could not resolve org.jboss:jboss-eap-client:.
  Required by:
      project :server
   > Extension of type 'RecommendationProviderContainer' does not exist. Currently registered extension types: [DefaultExtraPropertiesExtension, EclipseModel_Decorated, Boolean]

Why does org.jboss:jboss-remote-naming work when org.jboss:jboss-eap-client fails?

If I go to look at the JBoss Maven repository I see that both jars exist. And what does that weird Extension of type error mean?

using dependencyLock and propertiesFile providers together

I primarily use nebula-dependency-recommender on multi-project repositories and have found the properties file provider to be really helpful for consolidating versions in a single place. I've recently been exploring using the gradle-dependency-lock-plugin so that I can upgrade dependencies regularly.

However, it appears that in order to gain both benefits, I need to define the extension in an if/else block as follows:

if (System.env.UPDATE_LOCKS == "true" /* can equivalently check a gradle property */) {
    dependencyRecommendations {
        propertiesFile file: project.rootProject.file('versions.props')
    }
} else {
    dependencyRecommendations {
        dependencyLock file: project.file('dependencies.lock')
    }
}

I'm looking for suggestions on a better way to achieve this behavior. I looked through some repositories in the Netflix org but it appears that most repositories inline dependency versions, even for multi-project repositories.

One idea is to define my own plugin, with an extension wrapping the dependencyRecommendations block:

generateLocks {
    dependencyRecommendations {
        propertiesFile file: project.rootProject.file('versions.props')
    }
}

The plugin would then set the actual dependencyRecommendations extension to a convention-based lock file location in most cases, and to the specified providers if a certain environment variable/gradle property is set.

Gradle generated pom files when nebula recommender is used are missing dependency versions

I have ported a number of maven projects to Gradle and use the nebula recommender to manage the versions of third party artefacts. This process works fine however I have noticed that the pom files that are being generated are not valid and cannot be processed by either Gradle or Maven.

If my component has the following dependency in the Gradle build file
compile 'org.mdg:mdg'
The corresponding entry in the published pom file for my component has the following entry

      <dependency>
             <groupId>org.mdg</groupId>
             <artifactId>mdg</artifactId>
             <scope>compile</scope>
       </dependency>

If I include my component as a dependency in another project then I get an error from Maven and Gradle that the pom file is not valid and that they are not able to resolve transitive dependencies.

Surely the generated pom file for my component should include the group, artifact and version ids. Where is the version id?

Dependencies aren't recommended for buildscript dependencies

This is likely either impossible because of the order things happen, or I'm doing something wrong. I've got buildscript dependencies that I'd like to have versions recommended for.

My parent build.gradle sets up the recommender (and works for normal dependencies throughout my projects):

plugins {
    id 'nebula.dependency-recommender' version '5.0.0'
}

dependencyRecommendations {
    strictMode = true

    map recommendations: [
            'com.avast.gradle:docker-compose-gradle-plugin'       : '0.4.5',
    ]
}

Some of my subproject build files use the docker-compose-gradle-plugin:

buildscript {
    dependencies {
        classpath 'com.avast.gradle:docker-compose-gradle-plugin'
    }
}

apply plugin: 'docker-compose'

Unfortunately, the version for d-c-g-p isn't provided and I have to manually specify it.

InvalidUserDataException exception when getRecommendedVersion is used with a copy action

When dependencyRecommendations.getRecommendedVersion is being invoked before some copy-based action (copy, pack, ospack, etc), the build fails with an exception InvalidUserDataException: Authentication scheme 'all'(Authentication) is not supported by protocol 'file'.

Tested with: gradle 3.1, gradle 3.4.1, gradle 4.1

build.gradle:

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.netflix.nebula:nebula-dependency-recommender:4.3.0'
    }
}

repositories {
    mavenLocal()
    maven { url 'http://repo1.maven.org/maven2' }
}

apply plugin: 'java'
apply plugin: 'nebula.dependency-recommender'

dependencyRecommendations {
    mavenBom module: 'org.glassfish.hk2:hk2-bom:2.5.0-b36'
}

// If the following line is commented then build is green
def someVersion = dependencyRecommendations.getRecommendedVersion('org.glassfish.hk2', 'hk2-locator')

dependencies {
    testCompile 'org.glassfish.hk2:hk2-locator:2.5.0-b36'
}

copy {
    from (zipTree(configurations.testCompile[0]))
    into 'tmp'
}

nebula dependency recommender not compatible with spring io dependency management

I have a bom file which already exists and spring's io.spring.dependency-management or org.springframework.boot plugin which pulls in the former, can reference the bom file no problem in their dependencyManagement {} closure however I cannot get nebulaBomRecommender, nor nebulaDependencyManagement, nor dependencyRecommendations to work when I am also using plugin org.springframework.boot. If i remove org.springframework.boot then nebula plugins work and find the bom file but my application needs to use boot. any advice is most appreciated.

Local properties are not prioritized in BOM

Hi,

I'm using plugin version 3.6.2. It seems the current behavior of maven bom provider does not prioritize local properties when they are defined in the pom alwell. I'm not sure if it is a bug or intended behavior but it is contradictory to a common use case like spring boot.

ext['hibernate.version'] = '5.2.4.Final'
dependencyRecommendations {
	mavenBom module: "org.springframework.boot:spring-boot-dependencies:1.4.2.RELEASE"
}

The maven pom sets the property hibernate.version to 5.0.11.Final in its properties block. The recommendation plugin does consider the local version 5.2.4.Final as the higher priority. The documentation Maven-BOM-Provider on the over hand states properties can be at least supplied via the ext mechanism. And most likely the later ones should take priority.

Regards
Joke

Rewrite to avoid deprecation warnings in Gradle 3.+

There are two deprecation warnings in Gradle 3.3

The ProjectDependency.getProjectConfiguration() method has been deprecated and is scheduled to be removed in Gradle 4.0.
        at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency.getProjectConfiguration(DefaultProjectDependency.java:74)
        at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency_Decorated.getProjectConfiguration(Unknown Source)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.applyRecommendationToDependency(DependencyRecommendationsPlugin.java:37)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.access$000(DependencyRecommendationsPlugin.java:18)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1.execute(DependencyRecommendationsPlugin.java:55)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1.execute(DependencyRecommendationsPlugin.java:51)
...

And

ModuleDependency.getConfiguration() has been deprecated and is scheduled to be removed in Gradle 4.0. Use ModuleDependency.getTargetConfiguration() instead.
        at org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependency.getConfiguration(AbstractModuleDependency.java:56)
        at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency_Decorated.getConfiguration(Unknown Source)
        at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency.getProjectConfiguration(DefaultProjectDependency.java:75)
        at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency_Decorated.getProjectConfiguration(Unknown Source)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.applyRecommendationToDependency(DependencyRecommendationsPlugin.java:37)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.access$000(DependencyRecommendationsPlugin.java:18)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1.execute(DependencyRecommendationsPlugin.java:55)
        at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1.execute(DependencyRecommendationsPlugin.java:51)
...

Support Merging Recommendations instead of "Last one wins"

According to the docs, when multiple recommendations files recommend a version on a single dependency, the "last one wins".

Please consider supporting the actual merging and conflict resolution of multiple recommendations such that the highest version wins. This new behavior can be governed by a property if needed.

Gradle daemon blocks properties file

Environment

------------------------------------------------------------
Gradle 3.3
------------------------------------------------------------

Build time:   2017-01-03 15:31:04 UTC
Revision:     075893a3d0798c0c1f322899b41ceca82e4e134b

Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_111 (Oracle Corporation 25.111-b14)
OS:           Windows 7 6.1 amd64

Steps to reproduce

build.gradle

buildscript {
  dependencies {
    classpath 'com.netflix.nebula:nebula-dependency-recommender:3.7.0'
  }
}

allprojects {
  apply plugin: 'nebula.dependency-recommender'

  dependencyRecommendations {
    propertiesFile file: file("${rootProject.projectDir}/versions.properties")
  }
}

version.properties

CXF_VERSION=3.1.4

org.apache.cxf:cxf-rt-frontend-jaxws=$CXF_VERSION
org.apache.cxf:cxf-rt-transports-http=$CXF_VERSION
org.apache.cxf:cxf-rt-features-clustering=$CXF_VERSION
org.apache.cxf:cxf-core=$CXF_VERSION
org.apache.cxf:cxf-rt-databinding-xmlbeans=$CXF_VERSION
org.apache.cxf:cxf-rt-management=$CXF_VERSION
org.apache.cxf:cxf-rt-wsdl=$CXF_VERSION

console:

$ git pull
Unlink of file 'versions.properties' failed. Should I try again? (y/n) y
Unlink of file 'versions.properties' failed. Should I try again? (y/n) y
Unlink of file 'versions.properties' failed. Should I try again? (y/n) y
...etc

Actual behavior

It's very often Gradle Daemon does not release a properties files defined in dependencyRecommendations after a Gradle build is completed. The problem appears only with the plugin's properties files.

Expected behavior

The properties file is released

extra "/" when downloading parent poms via mavenCentral()

appears to be because mavenCentral is defined something like this:

https://repo.maven.apache.org/maven2/

workaround is to define maven repo with:

repositories {
    maven {
        url 'https://repo.maven.apache.org/maven2'
    }
}

To reproduce error, attempt to use:

repositories {
    mavenCentral()
}
dependencyRecommendations {
    mavenBom module: 'io.vertx:vertx-dependencies:3.4.1'
}

build with debug and you will see a failed attempt to load the parent pom, owing to presence of doubled-up "/" character:

GET /maven2//org/sonatype/oss/oss-parent/7/oss-parent-7.pom

02:46:29.910 [INFO] [org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor] Cached resource https://repo1.maven.org/maven2/io/vertx/vertx-dependencies/3.4.1/vertx-dependencies-3.4.1.pom is up-to-date (lastModified: Wed Mar 15 13:45:14 GMT 2017).
02:46:29.910 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.CachingModuleComponentRepository] Downloaded artifact 'vertx-dependencies.pom (io.vertx:vertx-dependencies:3.4.1)' from resolver: MavenRepo
02:46:29.912 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 17: dispatching class org.gradle.launcher.daemon.protocol.BuildEvent
02:46:31.395 [DEBUG] [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@31b8a5145 pairs: {GET /maven2//org/sonatype/oss/oss-parent/7/oss-parent-7.pom HTTP/1.1: null}{User-Agent: Java/1.8.0_121}{Host: repo1.maven.org}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}
02:46:31.410 [DEBUG] [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@630a33519 pairs: {null: HTTP/1.1 404 Not Found}{Last-Modified: Wed, 10 Aug 2016 15:08:35 GMT}{ETag: "1fb066da6a67c7c02962f59b4b8cd1ee"}{x-amz-error-code: NoSuchKey}{x-amz-error-message: The specified key does not exist.}{x-amz-error-detail-Key: maven2//org/sonatype/oss/oss-parent/7/oss-parent-7.pom}{Content-Type: text/html}{Via: 1.1 varnish}{Fastly-Debug-Digest: 2fa0d61717159a3e4ec0b11eb5109d7653dd17f522da9e74825f9b455f27eb0c}{Content-Length: 554}{Accept-Ranges: bytes}{Date: Tue, 18 Apr 2017 01:46:31 GMT}{Via: 1.1 varnish}{Age: 2369}{Connection: keep-alive}{X-Served-By: cache-iad2133-IAD, cache-lcy1121-LCY}{X-Cache: HIT, HIT}{X-Cache-Hits: 1, 1}{X-Timer: S1492479991.386050,VS0,VE1}
02:46:31.412 [ERROR] [org.gradle.api.Project] Exception while polling provider recommender-5 for version

Spring Cloud BOMs are not applied correctly

Hi! I have multi module project and there is need to import several maven BOM's, but for some reason I can't.

Here is my build.gradle. In such configuration only BOM defined first will work and the version for spring-boot-starter-websocket won't be resolved.

buildscript {
    repositories { jcenter() }

    dependencies {
        classpath 'com.netflix.nebula:nebula-dependency-recommender:4.1.0'
    }
}

allprojects {

    apply plugin: 'java'
    apply plugin: 'groovy'
    apply plugin: 'nebula.dependency-recommender'
    group = 'org.gradle.sample'
    version = '1.0'

    repositories {
        mavenCentral()
    }

    dependencyRecommendations {
        mavenBom module: 'org.springframework.cloud:spring-cloud-netflix:1.2.6.RELEASE'
        mavenBom module: 'org.springframework.boot:spring-boot-starter-parent:1.5.2.RELEASE'
    }

    configurations.all {
        it.resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
}

subprojects {
    dependencies {
        compile(group: 'org.springframework.boot', name: 'spring-boot-starter-websocket')
        compile(group: 'org.springframework.cloud', name: 'spring-cloud-starter-feign')
    }
}

Recommendation does not work with composite builds

I am not really sure if you can do something about this, but at least it can be noted for future reference or other people dealing with the same issue. Version recommendation does not work when used with composite build feature. I believe it is for the same reason as described in this Gradle issue.

Allow easy pass-through of other recommendations.

We would like to be able easily to pass through other recommendations BOM, something like:

dependencies {
  recommendation 'netflix.grpc:netflix-grpc-recommendations:latest.release@pom'
}

where netflix.grpc:netflix-grpc-recommendations:latest.release@pom is the other recommendations BOM to be passed through. This can be done with some logic in the build.gradle file. It would be more readable and less complex to the maintainer of that file if that logic were abstracted away and hidden within the recommendations plugin itself.

Slight error in documentation

Hi,

On this page Properties-File-Provider there is a typo I think:

This code doesn't work:

dependencyRecommendations {
   propertiesFile file: 'recommendations.props'
}

It fails with Cannot cast object 'recommendations.props' with class 'java.lang.String' to class 'java.io.File'

It looks like a documentation error to me. Should probably be:

dependencyRecommendations {
   propertiesFile file: file('recommendations.props')
}

when using nebula, both `artifactoryPublish` and `publishRecommenderPublicationToBomRepository` publish the same pom file

The first one that runs wins and the second one fails.

$ ./gradlew publish
...
:publishNebulaPublicationToBomRepository (Thread[main,5,main]) completed. Took 1.423 secs.
:publishNebulaPublicationToDistMavenRepository (Thread[main,5,main]) started.
:publishNebulaPublicationToDistMavenRepository
Executing task ':publishNebulaPublicationToDistMavenRepository' (up-to-date check took 0.0 secs) due to:
Task has not declared any outputs.
Publishing to repository org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository_Decorated@2c5708e7
Deploying to file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven
Uploading: netflix/runtime-internal-platform-parent/4/runtime-internal-platform-parent-4.jar to repository remote at file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven/
Uploading: netflix/runtime-internal-platform-parent/4/runtime-internal-platform-parent-4.pom to repository remote at file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven/
Uploading: netflix/runtime-internal-platform-parent/4/runtime-internal-platform-parent-4-sources.jar to repository remote at file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven/
Downloading: netflix/runtime-internal-platform-parent/maven-metadata.xml from repository remote at file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven/
Uploading: netflix/runtime-internal-platform-parent/maven-metadata.xml to repository remote at file:/home/nyap/proj/allow-recommender-to-depend-on-bom/family/bom/build/distMaven/
:publishNebulaPublicationToDistMavenRepository (Thread[main,5,main]) completed. Took 0.05 secs.
...
:publishRecommenderPublicationToBomRepository (Thread[main,5,main]) started.
:publishRecommenderPublicationToBomRepository
Executing task ':publishRecommenderPublicationToBomRepository' (up-to-date check took 0.0 secs) due to:
Task has not declared any outputs.
Publishing to repository org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository_Decorated@51dd6ef7
Deploying to http://artifacts.netflix.com/boms-snapshots-local
Uploading: netflix/runtime-internal-platform-parent/4/runtime-internal-platform-parent-4.pom to repository remote at http://artifacts.netflix.com/boms-snapshots-local/
Upload http://artifacts.netflix.com/boms-snapshots-local/netflix/runtime-internal-platform-parent/4/runtime-internal-platform-parent-4.pom
:publishRecommenderPublicationToBomRepository FAILED

Maven BOM provider fails, if Maven repository requires authentication

We have a BOM file foo.pom that itself has another parent POM bar.pom with more settings, and a Maven repository that requires authentication. Our build script was not able to find bar.pom, if it was not already cached in the local Maven repository.

After some investigation we noticed that Maven BOM provider ignores the credentials section while scanning the Maven repositories in the implementation of ModelResolver.resolveModel() and does not add Authentication HTTP header. As a result, it gets HTTP 401 Unauthorized from the server and finally, fails to resolve the dependency.

I managed to fix the issue in my fork, and the fix solved the problem for us.

Dependency recommender incompatible with configure-on-demand

This commit added support for traversing project dependencies. However, the ProjectDependency.getProjectConfiguration() call assumes that the downstream project has already been notified of pre-resolution, and evaluated itself if necessary. This is not true until ProjectDependencyInternal.beforeResolved() is called. As such, errors like the following currently occur:

Configuration on demand is an incubating feature.

FAILURE: Build failed with an exception.

* Where:
Script '<omitted>' line: 13

* What went wrong:
A problem occurred configuring project ':<omitted>'.
> Exception thrown while executing model rule: PublishingPlugin.Rules#publishing(ExtensionContainer)
   > Configuration with name 'default' not found.

Project dependencies may introduce inconsistent version recommendations

Hi all,
Assume a two-project (A,B) build such that B has a project-dependency on A. A common setup is to have a top-level versions.props (as a recommendation source) and project level A/versions.props and B/versions.props for per-project overrides. Now, when building B, the transitive dependencies induced by the project dependency on A are erroneously resolved with the combination of the top-level versions.props and B/versions.props rather than the expected A/versions.props. Any suggestions for handling this scenario?
Thanks! Robert.

Passing Properties to Recommendations

How does recommender-plugin passes properties to maven BOM, lets same i have a maven bom like com.example:my-bom:1.0, that BOM has some properties e.g. jdk.version, typically when adding BOM like that the dependency resolution fails with the trace Failed to determine Java version for profile jdk1.7 ... where jdk1.7 is a profile name in referred parent pom

Versions not found for custom configurations

I have the plugin working for compile dependencies.

However, when I introduce a custom configuration in my project...

configurations {
abc
}

...and then reference a dependency with no version

dependencies {
abc group: 'com.mygroup', name: 'myartifact', ext: 'xml'
}

the version isn't picked up when using mavenBom.

If I explicitly state the version then the dependency is resolved.

Is there something I need to do to enable dependency recommendations for custom configs ?

Lazy initialization of recommendation providers is not thread-safe for multiproject builds with --parallel

Hi!

The recommendation plugin traverses up the project hierarchy to find a suitable recommendation in one of the parent projects, which is a good feature.

But as soon as the "--parallel" switch comes into play, a common parant project recommendation container gets requested by multiple threads in parallel.

My builds fail because a not completely preinitialized recommendation-HashMap is returned by the MavenBomRecommendationProvider in those situations.

Currenly we only use the MavenBomRecommendationProvider but by reviewing the code I found the same issue in:

  • MavenBomRecommendationProvider
  • DependencyLockProvider.groovy
  • IvyRecommendationProvider.groovy
  • PropertyFileRecommendationProvider.java

I will prepare two pull requests with fixes. One for the MavenBomRecommendationProvider which I tested successfully in my project and another one for the other three fixes.

Could you please review my code changes and merge the changes if suitable?

Thanks!

Regards
Christian

"mavenBom file: 'pom.xml'" causes error "Module may not be null"

Steps to reproduce:

create build.gradle:

buildscript {
  repositories {
    maven {
      url 'https://plugins.gradle.org/m2/'
    }
  }
  dependencies {
    classpath 'com.netflix.nebula:nebula-dependency-recommender:4.0.2'
  }
}

repositories {
  mavenCentral()
}

apply plugin: 'java'
apply plugin: 'nebula.dependency-recommender'
dependencyRecommendations {
  mavenBom file: 'pom.xml'
}

create pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <groupId>org.example</groupId>
  <artifactId>example</artifactId>
  <packaging>pom</packaging>
  <version>1.0</version>

  <dependencyManagement>
  </dependencyManagement>

</project>

execute gradle build:

FAILURE: Build failed with an exception.

* Where:
Build file '/tmp/example/build.gradle' line: 19

* What went wrong:
A problem occurred evaluating root project 'example'.
> Module may not be null

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 0.719 secs

using gradle --version:

------------------------------------------------------------
Gradle 3.4
------------------------------------------------------------

Build time:   2017-02-20 14:49:26 UTC
Revision:     73f32d68824582945f5ac1810600e8d87794c3d4

Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_121 (Oracle Corporation 25.121-b13)
OS:           Linux 4.1.15-gentoo-r1 amd64

This plugin probably does not take into account --offline switch?

It seems that when your projects has applied this plugin then you can't build in offline mode. Maybe we should add this feature? Its not often needed feature maybe, but it's unfortunate when plugin does not support something that core provides. There is gradle.startParameter.isOffline() command to check when the build has been started in offline mode. BOM files should be caches in MavenLocal() as well I think.

Provide errors for misconfigured version.props file

I spent about half an hour trying to dig into why a certain buildscript of mine wasn't properly resolving a dependency with nebula. After getting another pair of eyes on it, it turned out I had written a:b:* = 1.0.0 instead of a:* = 1.0.0 or a:b = 1.0.0. It seems like this would be something that nebula would be able to complain about and point you to the right error instead of silently not providing the right version number, leaving me to wonder where the bug was coming from.

Documentation conflict about resolution order

The README says:

"Dependency recommenders are the source of versions. If more than one recommender defines a recommended version for a module, the first recommender specified will win."

However, later in the README is a link to https://github.com/nebula-plugins/nebula-dependency-recommender-plugin/wiki/Resolving-Differences-Between-Recommendation-Providers which states:

"By default, recommendation providers are queried for recommendations in LIFO order."

I'm wondering which of these is correct?

Ignore buildscript/classpath configuration

dependencyRecommendations appears to be overriding my buildscript dependencies, I'd like to have different forced versions for Gradle than for my project, what's the right way to narrow the scope of its application?

Cannot generate BOM file

I'm trying to generate a BOM file, but I'm getting:

Could not get unknown property 'dependencyManagement' for object of type 
org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication.

Indeed if I take the sample code from here and paste it into a new project and try to run any task, I get this error.

Any hints on what I'm doing wrong?

(I tried with a few Gradle versions, but I'm currently on 3.3.)

Maven BOM provider uses Maven API incorrectly, producing meaningless exceptions if dependency resolution fails

The implementation of ModelResolver.resolveModel() shall throw UnresolvableModelException, if the artifact cannot be found in any of the repositories.

The current implementation returns NULL, and the Gradle output does not contain any indication which artifact causes the problem. There is just a meaningless IllegalArgumentException thrown from Maven code internals.

I fixed the issue in my fork. The exception contains the full information about the artifact, and the concatenated error messages from IOExceptions for each of the scanned repositories, and it is printed out in the logs.

Incompatible with Spring Boot plugin

This plugin is incompatible with the spring boot plugin because you both try to add a dependencyManagement extension. I'd like to be able to use both. Any chance of a rename on your end?

Recommender-plugin breaks project dependencies

I have a very basic project with two sub-modules. One of the sub-module has a dependency to the other using a compile project dependency:

apply plugin: 'java' dependencies { compile project(':projecta') }

the recommender plugin does not seem to be able to handle the project dependency, without the following line the project works perfectly fine

apply plugin: 'nebula.dependency-recommender'

the complete example is attached as zip.

the following exception is thrown:

`
FAILURE: Build failed with an exception.

  • What went wrong:
    Could not resolve all dependencies for configuration ':projectb:compileClasspath'.

    Could not resolve project :projecta.
    Required by:
    jcan:projectb:1.0.0-SNAPSHOT
    Extension of type 'RecommendationProviderContainer' does not exist. Currently registered extension types: [DefaultExtraPropertiesExtension]

  • Try:
    Run with --info or --debug option to get more log output.

  • Exception is:
    org.gradle.api.artifacts.ResolveException: Could not resolve all dependencies for configuration ':projectb:compileClasspath'.
    at org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration.rethrowFailure(DefaultLenientConfiguration.java:62)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultResolvedConfiguration.rethrowFailure(DefaultResolvedConfiguration.java:36)
    at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyConfigurationResolver$FilesAggregatingResolvedConfiguration.rethrowFailure(SelfResolvingDependencyConfigurationResolver.java:112)
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver$ErrorHandlingResolvedConfiguration.rethrowFailure(ErrorHandlingConfigurationResolver.java:189)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:666)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:292)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileTreeConverter.convertInto(DefaultFileCollectionResolveContext.java:202)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:103)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileTrees(DefaultFileCollectionResolveContext.java:74)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileTreeConverter.convertInto(DefaultFileCollectionResolveContext.java:188)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:98)
    at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileTrees(DefaultFileCollectionResolveContext.java:74)
    at org.gradle.api.internal.changedetection.state.DefaultFileCollectionSnapshotter.visitFiles(DefaultFileCollectionSnapshotter.java:41)
    at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter.snapshot(AbstractFileCollectionSnapshotter.java:57)
    at org.gradle.api.internal.changedetection.state.DefaultFileCollectionSnapshotter.snapshot(DefaultFileCollectionSnapshotter.java:29)
    at org.gradle.api.internal.changedetection.rules.AbstractFileSnapshotTaskStateChanges.createSnapshot(AbstractFileSnapshotTaskStateChanges.java:47)
    at org.gradle.api.internal.changedetection.rules.InputFilesTaskStateChanges.(InputFilesTaskStateChanges.java:33)
    at org.gradle.api.internal.changedetection.rules.TaskUpToDateState.(TaskUpToDateState.java:52)
    at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.getStates(DefaultTaskArtifactStateRepository.java:142)
    at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.isUpToDate(DefaultTaskArtifactStateRepository.java:73)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:55)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
    at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
    at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve project :projecta.
    Required by:
    jcan:projectb:1.0.0-SNAPSHOT
    at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionResolver.resolve(DependencySubstitutionResolver.java:42)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$ModuleVersionSelectorResolveState.resolveModuleRevisionId(DependencyGraphBuilder.java:868)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$DependencyEdge.resolveModuleRevisionId(DependencyGraphBuilder.java:216)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.traverseGraph(DependencyGraphBuilder.java:100)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:75)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver$1.execute(DefaultArtifactDependencyResolver.java:88)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver$1.execute(DefaultArtifactDependencyResolver.java:78)
    at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:61)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:39)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver.resolve(DefaultArtifactDependencyResolver.java:78)
    at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.run(CacheLockingArtifactDependencyResolver.java:41)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:192)
    at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:175)
    at org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:106)
    at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.useCache(DefaultCacheFactory.java:187)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager.useCache(DefaultCacheLockingManager.java:64)
    at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver.resolve(CacheLockingArtifactDependencyResolver.java:39)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolve(DefaultConfigurationResolver.java:91)
    at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyConfigurationResolver.resolve(SelfResolvingDependencyConfigurationResolver.java:40)
    at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolve(ShortCircuitEmptyConfigurationResolver.java:52)
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolve(ErrorHandlingConfigurationResolver.java:43)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveGraphIfRequired(DefaultConfiguration.java:371)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:346)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getResolvedConfiguration(DefaultConfiguration.java:339)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getResolvedConfiguration(Unknown Source)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:664)
    ... 84 more
    Caused by: org.gradle.api.UnknownDomainObjectException: Extension of type 'RecommendationProviderContainer' does not exist. Currently registered extension types: [DefaultExtraPropertiesExtension]
    at org.gradle.api.internal.plugins.ExtensionsStorage.getHolderByType(ExtensionsStorage.java:99)
    at org.gradle.api.internal.plugins.ExtensionsStorage.getByType(ExtensionsStorage.java:77)
    at org.gradle.api.internal.plugins.DefaultConvention.getByType(DefaultConvention.java:116)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:76)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:81)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$2.execute(DependencyRecommendationsPlugin.java:51)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$2.execute(DependencyRecommendationsPlugin.java:40)
    at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencySubstitutions$DependencyResolveDetailsWrapperAction.execute(DefaultDependencySubstitutions.java:193)
    at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencySubstitutions$DependencyResolveDetailsWrapperAction.execute(DefaultDependencySubstitutions.java:183)
    at org.gradle.internal.Actions$CompositeAction.execute(Actions.java:79)
    at org.gradle.internal.Actions$CompositeAction.execute(Actions.java:79)
    at org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionResolver.resolve(DependencySubstitutionResolver.java:40)
    ... 111 more

`

The recommender plugin should not even attempt to touch any of the project dependencies. Their version never needs to be resolved/recommended.
example.zip

Strategy for transitive conflicts (or minimal version)?

Assume we have an external library with transitive dependecy:

external:lib:2.0
\ -- external:lib-trans:1.2

In the past lib-trans v1.0 had a major bug and was updated to v1.1, and then to v1.2 because of a minor bug

My build.gradle:

compile('external:lib')

My version.properties:

external:lib=2.0
external:lib-trans=1.1

In this case version.properties means "I know that I need external:lib-trans v1.1 or higher to get application worked (major bugfix)".

But I also want to use higher version if it's available (minor bugfix).

When I use OverrideTransitives strategy, I get 1.1 version resolved, but I expect 1.2.

How can I tell plugin to perform conflict resolution when a dependency is transitive?

SNAPSHOT dependencies listed in a Maven BOM are not updated

If you have a project that references a BOM that contains SNAPSHOT versions listed in it, Gradle never seems to check for newer versions of the library.

In our setup, we have a BOM which itself is a SNAPSHOT version and when running gradle with --refresh-dependencies and --info, I can see that gradle checks to see if a new version of the BOM is available but it never does the same with any libraries listed in the BOM.

Plugin doesn't work with Gradle 2.2.1

Apparently Gradle no longer uses/bundles Apache Commons.

:core:compileJava

FAILURE: Build failed with an exception.

* What went wrong:
Failed to notify dependency resolution listener.
> org/apache/commons/lang/StringUtils

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.listener.ListenerNotificationException: Failed to notify dependency resolution listener.
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:94)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy19.beforeResolve(Unknown Source)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:249)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getResolvedConfiguration(DefaultConfiguration.java:240)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getResolvedConfiguration(Unknown Source)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:442)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:205)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
[…]
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$1.execute(DependencyRecommendationsPlugin.java:33)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$1.execute(DependencyRecommendationsPlugin.java:29)
    at org.gradle.listener.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:109)
    at org.gradle.listener.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:98)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:83)
    ... 75 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang.StringUtils
    ... 80 more

After I add:

    classpath 'commons-lang:commons-lang:2.6'
    classpath 'commons-io:commons-io:2.4'

to the buildscript's dependencies, I get errors resolving parent POMs for mavenBom:

Exception while polling provider recommender-13 for version
java.lang.IllegalArgumentException: no model resolver provided, cannot resolve parent POM org.jboss.resteasy:resteasy-jaxrs-all:3.0.10.Final for POM org.jboss.resteasy:resteasy-bom:3.0.10.Final
    at org.gradle.mvn3.org.apache.maven.model.building.DefaultModelBuilder.readParentExternally(DefaultModelBuilder.java:805)
    at org.gradle.mvn3.org.apache.maven.model.building.DefaultModelBuilder.readParent(DefaultModelBuilder.java:664)
    at org.gradle.mvn3.org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:310)
    at org.gradle.mvn3.org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:232)
    at netflix.nebula.dependency.recommender.provider.MavenBomRecommendationProvider.getVersion(MavenBomRecommendationProvider.java:38)
    at netflix.nebula.dependency.recommender.RecommendationProviderContainer.getRecommendedVersion(RecommendationProviderContainer.java:98)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:71)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin.getRecommendedVersionRecursive(DependencyRecommendationsPlugin.java:77)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$2.execute(DependencyRecommendationsPlugin.java:51)
    at netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin$1$1$2.execute(DependencyRecommendationsPlugin.java:39)
    at org.gradle.internal.Actions$CompositeAction.execute(Actions.java:78)
    at org.gradle.api.internal.artifacts.ivyservice.VersionForcingDependencyToModuleResolver.resolve(VersionForcingDependencyToModuleResolver.java:39)
[…]

Provide ability to exclude certain gradle configurations

Some gradle configuration especially internal ones should be allowed to be excluded from applying recommendations. One of the cases would be scala project.. let's say project defines the following

  apply plugin: 'scala'
  apply plugin: 'nebula.dependency-recommender'

  project.dependencyRecommendations {
    strategy OverrideTransitives
    map recommendations: ['org.scala-lang:scala-library': '2.11.7']
  }

  dependencies {
    compile 'org.scala-lang:scala-library'
  }

dependency recommender is used to get the version 2.11.7 of scala-library and the OverrideTransitives strategy is used

In such case plugin forces the scala-library defined in zinc internal configuration used to compile scala sources to version 2.11.7, wheras the zinc compiler works properly at the moment only with the version defined by the scala plugin itself i.e. 2.10.x Very verbose solution is to do force to make dependency recommender plugin to omit scala-library in zinc configuration i.e.

configurations.zinc.resolutionStrategy { resStr ->
  eachDependency { details ->
    def req = details.requested
    if (req.name == 'scala-library') {
      resStr.force "${req.group}:${req.name}:${req.version}"
    }
  }
}

but the better would be to allow just to exclude zinc in dependencyRecommendations i.e.

  dependencyRecommendations {
    exclude 'zinc'
    [...]
  }

Ability to omit mavenBom version if it's provided elsewhere

I want to pull in library bar's BOM, and also pull in library bar.

Today I have to do something awkward like

dependencyRecommendations {
    map recommendations: ['com.foo:bar-lib': '0.47.3']
    mavenBom module: 'com.foo:bar-bom:0.47.3' // the version is now described twice
}

Would prefer to do something like

dependencyRecommendations {
    map recommendations: ['com.foo:*': '0.47.3']
    mavenBom module: 'com.foo:bar-bom' // can omit version
}

Substituted dependencies have version replaced by recommendation

In this case, it's a substitution to 1.0.0 which is then replaced by a recommendation, causing the dependency to fail to resolve:

11:46:08.511 [INFO] [netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin] Recommending version 2.5.6 for dependency org.springframework:spring
11:46:08.511 [INFO] [netflix.nebula.dependency.recommender.DependencyRecommendationsPlugin] Recommending version 2.5.6 for dependency org.springframework:spring
11:46:08.511 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder] Selecting new module version com.netflix.spring:spring-legacy:2.5.6
11:46:08.511 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver] Attempting to resolve component for com.netflix.spring:spring-legacy:2.5.6 using repositories [local, nfrepo-everythingRepo, nfrepo-everything-pomMavenRepo]
11:46:08.512 [DEBUG] [org.gradle.api.internal.artifacts.repositories.resolver.DefaultExternalResourceArtifactResolver] Loading file:/Users/dannyt/ivy2-local/com.netflix.spring/spring-legacy/2.5.6/spring-legacy-2.5.6-ivy.xml

problems with transitive dependencies

I'm probably missing something but I can't make it work with transitive dependencies. Here's a small project to illustrate the problem:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>some</groupId>
  <artifactId>some</artifactId>
  <version>0.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>net.jcip</groupId>
        <artifactId>jcip-annotations</artifactId>
        <version>1.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

build.gradle

plugins {
  id "nebula.dependency-recommender" version "3.5.0"
}

allprojects {
  apply plugin: "nebula.dependency-recommender"
}

dependencyRecommendations {
  mavenBom file: file('pom.xml')
}

subprojects {
  repositories {
    jcenter()
    mavenCentral()
  }

  apply plugin: 'java'
}

settings.gradle

include 'alpha', 'bravo'

alpha/build.gradle

dependencies {
  compile project(":bravo")
}

bravo/build.gradle

dependencies {
  compile 'net.jcip:jcip-annotations'
}

In other words, alpha->bravo->net.jcip:jcip-annotations:1.0

Seems to work inside bravo:

 ❯ gradle dependencies --configuration compile
:bravo:dependencies

------------------------------------------------------------
Project :bravo
------------------------------------------------------------

compile - Dependencies for source set 'main'.
\--- net.jcip:jcip-annotations: -> 1.0

But not inside alpha:

 ❯ gradle dependencies --configuration compile
:alpha:dependencies

------------------------------------------------------------
Project :alpha
------------------------------------------------------------

compile - Dependencies for source set 'main'.
\--- project :bravo
     \--- net.jcip:jcip-annotations: FAILED

Here's an archive with the project:
nebula-bug.tar.gz

Any ideas what could be the cause?

Thanks

Maven BOM with profile fails to find `java.version`

I have pushed a code commit to my fork to reproduce the issue I see when trying to use my BOM. The error stops all recommending and causes failures in resolving dependencies (as there is no version specified.

Error message:

org.apache.maven.model.building.ModelBuildingException: 1 problem was encountered while building the effective model for sample:recommender:1.0
[ERROR] Failed to determine Java version for profile java7 @ 


	at org.apache.maven.model.building.DefaultModelProblemCollector.newModelBuildingException(DefaultModelProblemCollector.java:195)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:419)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:371)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:362)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:232)
	at netflix.nebula.dependency.recommender.provider.MavenBomRecommendationProvider.getVersion(MavenBomRecommendationProvider.java:107)
	at netflix.nebula.dependency.recommender.provider.MavenBomRecommendationProviderSpec.recommendations are loaded from the dependencyManagement section of a BOM(MavenBomRecommendationProviderSpec.groovy:69)

The Apache maven model builder, when a profile is found that has an <activation> tag with a <jdk>nested within will fail because it looks for the java.version in the model builder request's system properties. This is not specified so the model builder throws an exception.

I would have opened a pull request but I'm not sure where the java version should come from in the context of the call site. Any advice on how to handle this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.