Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE: Must provide a scope supplier #147

Closed
aesteve opened this issue Oct 14, 2020 · 19 comments
Closed

NPE: Must provide a scope supplier #147

aesteve opened this issue Oct 14, 2020 · 19 comments
Labels

Comments

@aesteve
Copy link

aesteve commented Oct 14, 2020

Hello and thanks for reckon. Been using it for a while and it really really helps managing versions.

On some project, I'm trying to upgrade kotlin JVM plugin from 1.3.72 to 1.4.10 and get the following error:

* What went wrong:
Failed to apply plugin [id 'org.jetbrains.kotlin.jvm']
> Must provide a scope supplier.

I probably did something wrong, but everything was working completely fine with 1.3.72, any idea?

Thanks a lot.

@aesteve
Copy link
Author

aesteve commented Oct 26, 2020

I seem to have the same error by upgrading Gradle from 6.6 to 6.7.

An exception occurred applying plugin request [id: 'org.gradle.java-test-fixtures']
> Failed to apply plugin 'org.gradle.java-test-fixtures'.
   > Must provide a scope supplier.

@aesteve
Copy link
Author

aesteve commented Oct 26, 2020

Relevant (maybe) info:

  • that's a multi-module Kotlin project
  • reckon is configured in the root project as follows:
// Root Project
apply(plugin = "org.ajoberstar.reckon")

reckon {
    scopeFromProp()
    stageFromProp("milestone", "rc", "final")
}

@grolljak
Copy link

grolljak commented Oct 26, 2020

I am experiencing the same issue! I am using (among others) these plugins:

kotlin("jvm") version "1.3.72"
kotlin("plugin.jpa") version "1.3.72"
kotlin("plugin.spring") version "1.3.72"
kotlin("kapt") version "1.3.72"

When I switch to version 1.4.0 upon reimport of gradle projects I get this weird exception

org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project '<name-of-the-project>'. 
Caused by: java.util.NoSuchElementException: Collection is empty.
	at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:534)
	at org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget.sourcesJarArtifact(kotlinTargets.kt:200)
	at org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget.sourcesJarArtifact$default(kotlinTargets.kt:188)
	at org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget$kotlinComponents$2.invoke(kotlinTargets.kt:78)
	at org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget$kotlinComponents$2.invoke(kotlinTargets.kt:36)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget.getKotlinComponents$kotlin_gradle_plugin(kotlinTargets.kt)
	at org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPluginKt$applyUserDefinedAttributes$1.invoke(KotlinMultiplatformPlugin.kt:320)
	at org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPluginKt$applyUserDefinedAttributes$1.invoke(KotlinMultiplatformPlugin.kt)
	at org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginKt$whenEvaluated$1.execute(KotlinMultiplatformPlugin.kt:213)
	at org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginKt$whenEvaluated$1.execute(KotlinMultiplatformPlugin.kt)

When I try to gradle clean or build I get the already mentioned exception:

An exception occurred applying plugin request [id: 'org.jetbrains.kotlin.jvm', version: '1.4.0']
> Failed to apply plugin 'org.jetbrains.kotlin.jvm'.
   > Must provide a scope supplier.

Could you guys have a look? We would like to use some features of 1.4.0.

@grolljak
Copy link

grolljak commented Oct 30, 2020

Hey @aesteve I solved the problem by reordering the plugins:

    kotlin("jvm") version "1.4.10"
    kotlin("plugin.jpa") version "1.4.10"
    kotlin("plugin.spring") version "1.4.10"
    kotlin("kapt") version "1.4.10"
    id("org.ajoberstar.reckon") version "0.13.0"

More specifically I put the reckon plugin after kotlin plugins.

@aesteve
Copy link
Author

aesteve commented Oct 30, 2020

Glad you figured this out for your use-case.
It doesn't work for me though :( that's the order I had already. It may be related to the fact that I'm having a multi-module build.

@renato-zannon
Copy link

@aesteve I had the same issue in a multi-project build. For me, the issue was that the subprojects block was located (on gradle.build), before the reckon {} block, and apparently the kotlin plugin now needs access to project.version, before reckon is ready to provide it. This seem to match the situation on this test

I was able to fix it just by moving the reckon configuration block right below the plugins {} block, before subprojects

@aesteve
Copy link
Author

aesteve commented Nov 9, 2020

Thanks a lot for your help.
I'm still not managing to find the right order for the plugins block.
In my case, that's the java-test-fixtures which causes these issues.

I tried many many different orders but no one seems to fix the issue with java-test-fixtures, unfortunately.

Edit: note, no matter the order in plugins block, or where I put the reckon block, it's always gonna be this java-test-fixtures plugin that's gonna be causing issues.
Edit²: it always fails in the plugins block of the root project where I declare the java-test-fixtures, not where I use it. Which definitely sounds like a bug in this plugin.

@moaxcp
Copy link

moaxcp commented Jan 4, 2021

I have the same issue here but with a normal java project. This is with a project using the java-test-fixtures plugin.

@moaxcp
Copy link

moaxcp commented Mar 29, 2021

I just tried this again with gradle 6.8.3. This is the stack trace I'm getting. It looks like reckon is being configured when the test-fixture-plugin is applied. This is before the extension has been setup and the scope supplier ends up being null.

Caused by: java.lang.NullPointerException: Must provide a scope supplier.
	at org.ajoberstar.reckon.core.Reckoner$Builder.build(Reckoner.java:250)
	at org.ajoberstar.reckon.gradle.ReckonExtension.reckonVersion(ReckonExtension.java:79)
	at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:167)
	at org.ajoberstar.reckon.gradle.ReckonPlugin$DelayedVersion.toString(ReckonPlugin.java:87)
	at org.gradle.api.internal.artifacts.ProjectBackedModule.getVersion(ProjectBackedModule.java:42)
	at org.gradle.api.internal.artifacts.dsl.PublishArtifactNotationParserFactory$FileProviderNotationConverter.parseType(PublishArtifactNotationParserFactory.java:127)
	at org.gradle.api.internal.artifacts.dsl.PublishArtifactNotationParserFactory$FileProviderNotationConverter.parseType(PublishArtifactNotationParserFactory.java:111)
	at org.gradle.internal.typeconversion.TypedNotationConverter.convert(TypedNotationConverter.java:43)
	at org.gradle.internal.typeconversion.CompositeNotationConverter.convert(CompositeNotationConverter.java:34)
	at org.gradle.internal.typeconversion.NotationConverterToNotationParserAdapter.parseNotation(NotationConverterToNotationParserAdapter.java:31)
	at org.gradle.internal.typeconversion.JustReturningParser.parseNotation(JustReturningParser.java:40)
	at org.gradle.internal.typeconversion.ErrorHandlingNotationParser.parseNotation(ErrorHandlingNotationParser.java:48)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfigurationPublications.artifact(DefaultConfigurationPublications.java:155)
	at org.gradle.api.plugins.jvm.internal.DefaultJvmPluginServices$DefaultElementsConfigurationBuilder.build(DefaultJvmPluginServices.java:335)
	at org.gradle.api.plugins.jvm.internal.DefaultJvmPluginServices.createOutgoingElements(DefaultJvmPluginServices.java:245)
	at org.gradle.api.plugins.jvm.internal.DefaultJvmVariantBuilder.build(DefaultJvmVariantBuilder.java:192)
	at org.gradle.api.plugins.jvm.internal.DefaultJvmPluginServices.createJvmVariant(DefaultJvmPluginServices.java:270)
	at org.gradle.api.plugins.JavaTestFixturesPlugin.lambda$apply$1(JavaTestFixturesPlugin.java:59)
	at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:248)
	at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:245)
	at org.gradle.configuration.internal.DefaultUserCodeApplicationContext$CurrentApplication$1.execute(DefaultUserCodeApplicationContext.java:100)
	at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1.run(DefaultCollectionCallbackActionDecorator.java:95)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
	at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction.execute(DefaultCollectionCallbackActionDecorator.java:92)
	at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:163)
	at org.gradle.api.internal.plugins.DefaultPluginManager.withPlugin(DefaultPluginManager.java:251)
	at org.gradle.api.plugins.JavaTestFixturesPlugin.apply(JavaTestFixturesPlugin.java:58)
	at org.gradle.api.plugins.JavaTestFixturesPlugin.apply(JavaTestFixturesPlugin.java:46)
	at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
	at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
	at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:177)
	at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:51)
	at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:272)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
	at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:157)
	at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
	at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:156)
	... 145 more

@moaxcp
Copy link

moaxcp commented Mar 29, 2021

This is what I did to fix the issue. I moved 'java-test-fixtures to be applied after the extension is configured.

plugins {
    id 'org.ajoberstar.reckon' version '0.13.0'
    id 'java-library'
    id 'io.freefair.lombok' version '5.3.0'
    id 'org.unbroken-dome.test-sets' version '3.0.1'
    id 'org.sonarqube' version '3.1.1'
    id 'com.github.moaxcp.x11protocol'
    //id 'java-test-fixtures'
    id 'maven-publish'
    id 'signing'
    id 'jacoco'
}

group = 'com.github.moaxcp.x11'
description = 'An x11 client implemented in java'

reckon {
    scopeFromProp()
    snapshotFromProp()
}

apply plugin: 'java-test-fixtures'

@chadlwilson
Copy link

Hmm, maybe #170 is duplicate but it only started happening for me after a Gradle 7.4 upgrade, with jacoco.

I have no idea how determinate it is in Gradle; but just changing the order in the plugins block seemed enough to go from working to broken. 😬

@ajoberstar
Copy link
Owner

The general problem here is likely other plugins that are too eagerly trying to get the version from project.getVersion().toString(). Reckon's approach is only quasi-supported by Gradle by them declaring the type of project.getVersion() as Object instead of String. Nowadays it should really be a Provider<String> which would work better with how Reckon wants to behave.

I'm not sure if it's resolvable by Reckon, since it almost looks like a plugin trying to access the version before the reckon {} extension block runs, which really seems like a bug in another plugin. I could be misinterpreting here though.

I would be curious if 0.14.0 works any better for those of you with this issue. The fundamental approach is unchanged, but it more deeply uses BuildService and Property/Provider that before.

@chadlwilson
Copy link

Thanks @ajoberstar.

For what it's worth, the call in Jacoco's case (built-in Gradle plugin maintained by Gradle team) is triggered during apply at this line here, where it calls ConfigurationPublications.artifact(notation) which internally inside Gradle eventually comes to project.getVersion().toString() at this line here.

The full stack is in #170 if you're curious.

I am wondering, if using the plugins { } block, is there some kind of determinism here that might indicate the "safest" place for Reckon to be in the list (the start? the end? or it's a hash and un-ordered)

@chadlwilson
Copy link

I would be curious if 0.14.0 works any better for those of you with this issue. The fundamental approach is unchanged, but it more deeply uses BuildService and Property/Provider that before.

Also, after upgrade to 0.14.0 it still breaks in the same place with my simple reprod on #170, just with a slightly different Reckon stacetrace.

@ajoberstar
Copy link
Owner

I'm not clear on the determinism of the plugin block, but if reckon is applied after jacoco, it would work because reckon wouldn't have taken over the version yet. Unless something else comes along to correct the version on that artifact later, it likely has a null version because Gradle's still processing plugins and hasn't reached your real buildscript logic yet.

If reckon is applied earlier than jacoco you would get this error because reckon has reassigned the version to DelayedVersion, but again Gradle hasn't processed your build logic yet so you haven't configured how reckon should behave and it bombs.

Without Gradle making changes to make evaluation of version more lazy, I'm not positive if there's any way to resolve this generally. A partial idea is that maybe having reckon applied as a settings plugin instead of a project plugin could allow it to inject it's logic in earlier. I've never written a settings plugin, but might be worth exploring.

@chadlwilson
Copy link

Interesting, thanks for the reply. At least it's clear that doing something to try and affect the order of plugin loading is a workaround.

It's weird that simplify moving from Gradle 7.3.3 to 7.4 broke it for me, but perhaps they changing something in the ordering of plugin loads there...

@ajoberstar ajoberstar changed the title [Kotlin][1.4] Must provide a scope supplier NPE: Must provide a scope supplier Feb 15, 2022
@ajoberstar
Copy link
Owner

Re: @x80486 in #170 (which is a duplicate of this discussion)

Do you think there could be a resolution for this or would it be like that because the issue with the plugins block?

I do have other plugins in use and as soon as I start using the apply plugin way (even with Reckon only), they start failing as well; for instance, this is one of them: com.github.jakemarsden.git-hooks — unable to get the version number.

I guess it's around the same subject all this.

I have a handful of thoughts around this:

  1. If reckon could configure the version even earlier, it could be done in time for other plugins that "behave badly" in toStringing version eagerly to not notice. This could maybe be done with a Plugin<Settings>, which aren't common and I've not used before, but should be early enough to stop any normal Plugin<Project> from interfering. It would also reinforce the idea that reckon is setting a build-wide version not a project-specific version.
  2. Reckon could be a little more forgiving. If you haven't configured the reckon block yet, but something needed the version, just return "unspecified" or whatever the default version is, log a warning to the console, and let someone try again later. Currently, it's trying to be safe in the sense that if you wanted reckon involved you wanted its version to be used. If something is calling version.toString() before the reckon {} has run its going to get the wrong version regardless, because it's probably running before the user had a change to write version = 'whatever' if they weren't using reckon. Maybe that caller doesn't need the version for an important purpose or maybe the plugin or you will go correct it later anyway. However, that's utlimately a problem with the other plugin, and not something reckon really needs to play traffic cop on. The logging should help trace down the offending plugin in case tweaks need to be made there.
  3. Gradle could make the implicit laziness of project.getVersion() explicit by using Property<String>. They have issues open for this in Project "coordinates" should use providers gradle/gradle#13672 and Add lazy property style APIs for project.version and project.group gradle/gradle#15088. Even if they fix this, it will take time for plugins to be updated to use the new method. Since plugins could address this currently anyway, it doesn't replace the need for 1 or 2.
  4. I've seen another case of this error happen where it was actually covering up a different problem. Another failure was happening, but somehow in the chain it needed to access the version, and the reckon exception buried the real problem. Usually in this case, disabling reckon would help you see the real exception. Not applicable to all cases.
  5. Ultimately, the other plugins need to reckon with (pun intended) how they use project.getVersion() and likely make changes to access it more lazily. Again 3 would help them with this, but its not necessary technically.

I'm currently working on updates to other plugins, so this isn't the top of my list, but I do plan to come back to this. And I think both 1 and 2 are approaches I want to pursue.

@ajoberstar
Copy link
Owner

Issues #173 and #174 are open for the two items I listed above. Once #174 is implemented, I'll close this issue.

@ajoberstar
Copy link
Owner

The settings plugin org.ajoberstar.reckon.settings solution is available in 0.17.0-beta.2. I think this will provide a more reliable way to ensure that reckon runs early enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants