I have played a bit with the Spring tutorial, mainly because I find the Application class definition/main method quite cumbersome and wanted to see if there was a better way to do that. I do understand all of it, so it is clear to me what each element does. It's just that it looks much more busy than I thought it should be.
Compare:
ComponentScan
EnableAutoConfiguration
public class Application {
class object {
platformStatic public fun main(args: Array<String>) {
SpringApplication.run(javaClass<Application>(), *args)
}
}
}
vs. Java's
@ComponentScan
@EnableAutoConfiguration
public class Application {
static public void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I mean, this is terrible. Java's version is shorter and, I may dare to say, even prettier to look at. This is unacceptable to me :-) Kotlin is supposed to look much nicer than Java (it usually does!)
So, here are my attemps (which all failed horribly):
- There is no need for the main() method to be inside the Application class. That is just a Spring convention. So, let’s move it outside:
but then gradle fails with:
Execution failed for task ':findMainClass'.
> Unable to find a single main class from the following candidates [_DefaultPackage, _DefaultPackage$Application$e0b08dc9]
So, apparently there's something wrong with using the default package.
- Fine let’s move it to com.example; it’s better, anyway.
> Unable to find a single main class from the following candidates [com.example.ExamplePackage, com.example.ExamplePackage$Application$05fdfa5c]
Nope, it's not working. So, let's inspect the first class with javap It is in fact defining a main() static method which, in turn, invokes another static method inside ExamplePackage$Application$05fdfa5c
public static final void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:tf8 Lorg/jetbrains/annotations/NotNull;
stack=1, locals=1, args_size=1le/ExamplePackage$Application$05fdfa5c
0: aload_0 #24 // com/example/ExamplePackage$Application$05fdfa5c
1: invokestatic #27 // Method com/example/ExamplePackage$Application$05fdfa5c.main:([Ljava/lang/String;)V
so that is why :findMainClass gets confused.
Now, I’m wondering: why are these two methods generated at all? Why do we have more than one main() method?
thanks!
PS: the problem can be easily fixed by adding the following lines inside build.gradle
springBoot {
mainClass = '_DefaultPackage'
}
or, in the case of the com.example package:
springBoot {
mainClass = 'com.example.ExamplePackage'
}