this is not my exception... am I using the API wro...
# community-support
c
this is not my exception... am I using the API wrong?
Copy code
java.lang.NullPointerException: Cannot invoke "java.lang.Class.getName()" because "this.type" is null

        at org.gradle.api.internal.provider.DefaultProperty.describeContents(DefaultProperty.java:178)

        at org.gradle.api.internal.provider.AbstractProperty.toStringNoReentrance(AbstractProperty.java:207)

        at org.gradle.api.internal.provider.EvaluationContext.evaluate(EvaluationContext.java:142)

        at org.gradle.api.internal.provider.EvaluationContext.tryEvaluate(EvaluationContext.java:166)

        at org.gradle.api.internal.provider.AbstractMinimalProvider.toString(AbstractMinimalProvider.java:174)

        at org.gradle.process.internal.ProcessArgumentsSpec.getArgs(ProcessArgumentsSpec.java:107)

        at org.gradle.process.internal.ProcessArgumentsSpec.getAllArguments(ProcessArgumentsSpec.java:67)

        at org.gradle.process.internal.DefaultExecHandleBuilder.getAllArguments(DefaultExecHandleBuilder.java:113)

        at org.gradle.process.internal.AbstractExecHandleBuilder.getEffectiveArguments(AbstractExecHandleBuilder.java:59)

        at org.gradle.process.internal.AbstractExecHandleBuilder.build(AbstractExecHandleBuilder.java:140)

        at org.gradle.process.internal.DefaultExecAction.execute(DefaultExecAction.java:35)

        at org.gradle.process.internal.DefaultExecActionFactory.exec(DefaultExecActionFactory.java:202)

        at org.gradle.process.internal.DefaultExecOperations.exec(DefaultExecOperations.java:37)

        at com.xenoterracide.gradle.git.HeadBranchValueSource.gitRemoteShow(HeadBranchValueSource.java:68)
68
Copy code
this.execOperations.exec(execSpec -> {
        execSpec.setExecutable("git");
        execSpec.args("remote", "show", this.getParameters().getSourceRemote());
        execSpec.setStandardOutput(baos);
      }).getExitValue();
m
Does getSourceRemote return a Property? args doesn't understand them, you need to unwrap it with get()
c
I tried unwrapping it with get too and I get the same error
Might be null...
I changed the code, so at least now I know it's happening on the Property, but it's now just happening earlier
Copy code
if (!remotes.isEmpty()) {
        remotes
          .stream()
          .findFirst()
          .ifPresent(remote -> this.getParameters().getSourceRemote().convention(remote.getName()));
I know that
remote.getName()
is not null (debugger)
Copy code
java.lang.NullPointerException: Cannot invoke "java.lang.Class.isInstance(Object)" because "targetType" is null
	at org.gradle.api.internal.provider.Providers.fixedValue(Providers.java:39)
	at org.gradle.api.internal.provider.DefaultProperty.convention(DefaultProperty.java:125)
	at com.xenoterracide.gradle.git.HeadBranchValueSource.lambda$obtain$4(HeadBranchValueSource.java:55)
m
this is really strange, because
DefaultProperty.type
shouldn't be null. How is your
Parameters
interface defined?
c
moving stuff around currently to see if moving stuff out of that obtain fixes... but more or less like this. My moving around is just extending this interface for the additional properties
Copy code
public interface GitValueSourceParameters extends ValueSourceParameters {
  Property<File> getProjectDir();
}
Copy code
public interface HeadBranchValueSourceParameters extends GitValueSourceParameters {
  Property<String> getHeadBranch();
  Property<String> getSourceRemote();
before (when I commented) this was a single interface
and the vs impl would have had
Copy code
public abstract class HeadBranchValueSource implements ValueSource<String, HeadBranchValueSourceParameters> {
potentially worth noting, there is no set value of
getSourceRemote
so I'm expecting it to use the convention
m
potentially worth noting, there is no set value of getSourceRemote so I'm expecting it to use the convention
Thanks, just got to that with my research and this is what triggers the issue. Could you please file a bug?
c
ugh... so this is a blocker for this change for me... whelp 100% changing to not using value sources
well.. I guess it's not a blocker... but they are more trouble than they're worth
I'll probably move to plan B, use the value source to provide the string from the command output and then parse that elsewhere
or I cry lots
m
https://github.com/gradle/gradle/blob/9239189ef8d307b43b765f5b9637f509d8f5a436/platforms/core-configuration/model-core/src/main/java/org/gradle/api/internal/provider/ManagedFactories.java#L68 😭 we even have a TODO to fix the root cause. Though I'm not sure how we want users to set up a
convention
for a ValueSource. I suspect you cannot set the convention from outside, by e.g. wrapping
provider.of
into a helper function, because it comes from another call to
git
?
c
I mean, the default value is unset. The property exists in case they want to "explicitly" set it rather than rely on git to provide the answer. Which is why I'm conventionally setting the git result.
interesting, the original error was the same. This also tells me that ExecOperation might call the provider if one is passed.
I'm certain there are all kinds of workarounds, and I'm not certain a convention is required here?
I wasn't using one here at all... so strange
Copy code
this.execOperations.exec(execSpec -> {
        execSpec.setExecutable("git");
        execSpec.args("remote", "show", this.getParameters().getSourceRemote());
        execSpec.setStandardOutput(baos);
      }).getExitValue();
the convention was supposed to be the fix for a null value, there
m
get()
also triggers the issue you can use
orElse(<your convention value>).get()
at the consumer side (it works), but it has a slight semantic difference compared to the original
convention()
call.
c
did you create a minimal repro doing this? btw?
m
c
cool, I'll copy it into the ticket if you're ok with that 😉
thank you 1
what I'll probably do is extract any and all logic from the value source, and have it return the result of the baos.toString() instead of the real value I want. Build the logic elsewhere
the value source can be removed if jgit implements this result into a public api
as they have to have it 😕
then I've gotta go implement my own caching system 😕
if you have more to say 😉 . Thanks for the help https://github.com/gradle/gradle/issues/31123#issue-2633328896
basically though. I can do this, and forget about using
ValueSource
for anything else
Copy code
try (var git = Git.open(finalizeOnRead(this.getParameters().getProjectDir()).get())) {
      try (var baos = new ByteArrayOutputStream()) {
        this.execOperations.exec(execSpec -> {
            execSpec.setExecutable("git");
            execSpec.args("remote", "show", this.getParameters().getSourceRemote().get());
            execSpec.setStandardOutput(baos);
          }).getExitValue();

        return baos.toString(Charsets.UTF_8);
      }
    } catch (IOException e) {
      this.log.warn("Git had an exception", e);
    }
    return null;
  }
the default for
getSourceRemote
can come in from somewhere else
the convention can be set for the user input