Spring Tutorial

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):

  1. 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.

  1. 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' }

There is another way to do it, using the main class at package level

Check this example, is based on Kotlin M8 (before platformStatic support)

https://github.com/MarioAriasC/gs-relational-data-access/tree/master/kotlin

This is probably closer to the thing that you want to achieve

https://github.com/MarioAriasC/gs-rest-service/tree/master/kotlin