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

Java Application MainClass is not readable depending on how it is set #14662

Closed
Arthurm1 opened this issue Sep 27, 2020 · 4 comments
Closed

Java Application MainClass is not readable depending on how it is set #14662

Arthurm1 opened this issue Sep 27, 2020 · 4 comments

Comments

@Arthurm1
Copy link

Expected Behavior

I think I should be able to read out the Application Plugin's mainClass value regardless of how it is specified

Current Behavior

The Application plugin main class can be specified in 2 ways...

apply plugin: "application"
mainClassName = "com.foo.bar.Main"

or...

apply plugin: "application"
application {
    mainClass.set("com.foo.bar.Main")
}

I'm using the following code to access the main class via the ApplicationPluginConvention...

task('print main class') {
  println(project.convention.findPlugin(ApplicationPluginConvention.class).getMainClassName())
}

I can print out com.foo.bar.Main in the first example but I get null for the second example

As far as I know this method isn't being deprecated, only the JavaApplication#getMainClassName is being deprecated - is that correct?

I see the new mainClass property and the convention are linked in DefaultJavaApplication as follows...

this.mainClass = objectFactory.property(String.class).convention(providerFactory.provider(convention::getMainClassName));

Does that mean it's only set in one direction? So it doesn't update the convention's value when mainClass is set in the Application?

Or is it not valid to use the convention to access the main class?

Context

It's for a plugin that exports the Java/Scala build setup - Bloop

Gradle 6.5
Windows 10

@ljacomet
Copy link
Member

Doing the following is the recommended way:

application {
    mainClass.set("com.foo.bar.Main")
}

When you do mainClassName = "com.foo.bar.Main" at the root of the build script, you leverage an historical system in Gradle, the convention mappings.
This system is being slowly deprecated and replaced with Property types that have a better API and less surprises for developers new to Gradle.

When you read the value by doing println(project.convention.findPlugin(ApplicationPluginConvention.class).getMainClassName()) you only read the value of the convention. You do not read the value of the underlying model, be it application.mainClassName (deprecated) or application.mainClass, you only see what was set in the convention.

The convention was a commodity for plugin authors to set default values to fields. It should not be used in a build script by build authors.

@Arthurm1
Copy link
Author

@ljacomet thank you for the info. The move to Property types makes sense to me.

Do you have a link to documentation for plugin authors on how to read out these kind of settings from the underlying model if conventions are not the way? Or could you give me a line of code on how you would do it?

I was following the examples here although I realise here they set data, not read it

@ljacomet
Copy link
Member

ljacomet commented Sep 28, 2020

Thanks for the pointer to that documentation. It needs an update.

You should simply read the value from the model. So in the case we discussed: application.mainClass.get() or any other method on Provider that makes sense, like orElse, ...

In short, values set by convention - either through the ApplicationPluginConvention (to be considered legacy) or by calling application.mainClass.convention (the modern way for a plugin author to set a convention), will be reflected when reading the property.
And it is also the only way to get the value if the build author does application.mainClass.set("Foo")!

@Arthurm1
Copy link
Author

Ah I see. So go through the extension rather than the convention

So

project.extensions.getByType(JavaApplication.class).mainClass.get()

instead of

project.convention.findPlugin(ApplicationPluginConvention.class).getMainClassName()

Thanks for the help.

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

No branches or pull requests

3 participants