1. Overview
This quick tutorial provides different ways of defining an entry point into a Spring Boot application via Maven and Gradle.
A Spring Boot applicationβs main class is a class that contains a public static void main() method that starts up the Spring ApplicationContext. By default, if we donβt specify the main class explicitly, Spring will search for one in the classpath at compile time and fail to start if none or multiple of them are found.
Unlike in conventional Java applications, the main class discussed in this tutorial does not appear as the Main-Class metadata property in META-INF/MANIFEST.MF of the resulting JAR or WAR file.
Spring Boot expects the artifactβs Main-Class metadata property to be set to org.springframework.boot.loader.JarLauncher (or WarLauncher) which means that passing our main class directly to the java command line wonβt start our Spring Boot application correctly.
An example manifest looks like this:
Manifest-Version: 1.0
Start-Class: com.baeldung.DemoApplication
Main-Class: org.springframework.boot.loader.JarLauncher
Instead, we need to define the Start-Class property in the manifest, which JarLauncher evaluates to start the application.
Letβs see how we can control this property using Maven and Gradle.
2. Maven
The main class can be defined as a start-class element in the pom.xmlβs properties section:
<properties>
<!-- The main class to start by executing "java -jar" -->
<start-class>com.baeldung.DemoApplication</start-class>
</properties>
Note that this property will only be evaluated if we also add the spring-boot-starter-parent as <parent> in our pom.xml.
Alternatively, the main class can be defined as the mainClass element of the spring-boot-maven-plugin in the plugin section of our pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.baeldung.DemoApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
3. Gradle
If weβre using the Spring Boot Gradle plugin, we could specify our main class in a few configurations inherited from org.springframework.boot.
We can specify the mainClass property of the Spring Boot DSL within the springBoot configuration block in the projectβs Gradle file. When we so define, the bootRun and bootJar tasks pick it up and apply it project-wide:
springBoot {
mainClass = 'com.baeldung.DemoApplication'
}
Alternatively, we can define the main class as the mainClass property of bootJar Gradle task:
tasks.named("bootJar") {
mainClass = 'com.baeldung.DemoApplication'
}
Furthermore, we can define it as a manifest attribute of the bootJar task:
tasks.named("bootJar") {
manifest {
attributes 'Start-Class': 'com.baeldung.DemoApplication'
}
}
Notably, the main class we specify in the bootJar configuration block only affects the JAR that the task itself produces. Accordingly, this definition doesnβt affect the behavior of other Spring Boot Gradle tasks such as bootRun.
Additionally, we can apply the Gradle application plugin and configure its mainClass, and thus use it to determine the executable archiveβs main class:
mainClass = 'com.baeldung.DemoApplication'
4. Using CLI
We can also specify a main class via the command line interface.
Spring Bootβs org.springframework.boot.loader.PropertiesLauncher comes with a JVM argument to let you override the logical main-class called loader.main:
java -cp bootApp.jar -Dloader.main=com.baeldung.DemoApplication org.springframework.boot.loader.PropertiesLauncher
5. Main Class for Different Spring Profiles
Itβs quite common to use multiple Spring profiles in a Spring Boot project for specific behavior for the application. In this section, weβll learn how to configure the entry point for such projects.
5.1. Understanding the Scenario
In a Spring Boot application, we mark the main class with the @SpringBootApplication annotation. So, by using a combination of @SpringBootApplication and @Profile annotations, we can have multiple main classes within the project. However, we must ensure that weβre activating exactly one of the profiles while running the app.
Moving forward, letβs see what happens when we try to run our application without explicitly specifying which main class to use for an active profile:
$ mvn spring-boot:run \
-Dspring.profiles.active=errorhandling \
-Perrorhandling
# output trimmed to show failure
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:3.1.5:run (default-cli) on project spring-boot-basic-customization: Execution default-cli of goal org.springframework.boot:spring-boot-maven-plugin:2.7.11:run failed: Unable to find a single main class from the following candidates [com.baeldung.favicon.FaviconApplication, com.baeldung.failureanalyzer.FailureAnalyzerApplication, com.baeldung.errorhandling.ErrorHandlingApplication, com.baeldung.changeport.CustomApplication, com.baeldung.bootcustomfilters.SpringBootFiltersApplication] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
Unfortunately, the Spring framework fails to run the application, and it reports that itβs unable to find the main class.
No worries, thereβs a well-known solution to this problem. So, letβs go ahead and learn about the fix.
5.2. Configure Main Class for Spring Profile
Firstly, we must specify the applicationβs entry point using the spring.boot.mainclass property for each profile in the pom.xml file:
<profiles>
...
<profile>
<id>errorhandling</id>
<properties>
<spring.boot.mainclass>com.baeldung.errorhandling.ErrorHandlingApplication</spring.boot.mainclass>
</properties>
</profile>
...
</profiles>
Further, we need to configure the entry point using the spring-boot-maven-plugin in the pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.5</version>
<configuration>
<mainClass>${spring.boot.mainclass}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
Lastly, we must note that weβve specified the mainClass in the pluginβs configuration section as the spring.boot.mainclass property value.
5.3. Running the Application
Now our project is correctly set up. So, letβs go ahead and run a specific profile of our Spring Boot project:
$ mvn spring-boot:run \
-Dspring.profiles.active=errorhandling \
-Perrorhandling
# trimmed build output
...
22:46:16.908 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 9000 (http) with context path ''
...
Fantastic! It looks like weβve got this one right.
6. Conclusion
There are more than a few ways to specify the entry point to a Spring Boot application. Itβs important to know that all these configurations are just different ways to modify the manifest of a JAR or WAR file.
