SpringBoot: Defining the main class in pom.xml file

Nunyet de Can Calçada picture Nunyet de Can Calçada · Mar 16, 2017 · Viewed 7.1k times · Source

I've generated a Spring Boot web application using Spring Initializer, embedded Tomcat, Thymeleaf template engine.Technologies used: Spring Boot 1.4.2.RELEASE, Spring 4.3.4.RELEASE, Thymeleaf 2.1.5.RELEASE, Tomcat Embed 8.5.6, Maven 3, Java 8. I have this pom.xml file,

and I generate the war using this command

mvn clean package -DskipTests -Dspring.profiles.active=pebloc,war -DAPPKEY=pebloc

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bookcloud</groupId>
    <artifactId>bookcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>bookcloud</name>
    <description>Book Cloud </description>

    <profiles>
        <profile>
            <id>jar</id>
            <properties>
                <spring.boot.mainclass>com.bookcloud.iot.BookCloudApplication</spring.boot.mainclass>
            </properties>
        </profile>
        <profile>
            <id>war</id>
            <properties>
            <spring.boot.mainclass>com.bookcloud.iot.BookCloudApplicationWar</spring.boot.mainclass>
            </properties>
        </profile>
    </profiles>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency> 

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
         <dependency>
            <groupId>it.ozimov</groupId>
            <artifactId>spring-boot-email-core</artifactId>
            <version>0.5.1</version>
        </dependency>
        <dependency>
            <groupId>it.ozimov</groupId>
            <artifactId>spring-boot-thymeleaf-email</artifactId>
            <version>0.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            </dependency>

        <!-- https://mvnrepository.com/artifact/com.icegreen/greenmail -->
        <dependency>
            <groupId>com.icegreen</groupId>
            <artifactId>greenmail</artifactId>
            <version>1.5.3</version>
            <optional>true</optional>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>     

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>


        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>               
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                        <configuration>
                            <mainClass>${spring.boot.mainclass}</mainClass>
                         </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


</project>

but I still got this error:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.2.RELEASE:repackage (default) on project bookcloud: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.2.RELEASE:repackage failed: Unable to find a single main class from the following candidates [com.bookcloud.iot.BookCloudApplication, com.bookcloud.iot.BookCloudApplicationWar] -> [Help 1]

BookCloudApplication.java

@Profile("!war")
@SpringBootApplication
@Import({SecurityConfig.class ,PersistenceConfig.class, ServiceConfig.class})
public class BookCloudApplication {

    public static void main(String[] args) {
        SpringApplication.run(BookCloudApplication.class, args);
    }
}

BookCloudApplicationWar.java

@Profile("war")
@Import({SecurityConfig.class ,PersistenceConfig.class})
@SpringBootApplication
public class BookCloudApplicationWar extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(BookCloudApplicationWar.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(BookCloudApplicationWar.class, args);
    }

}

Answer

ootero picture ootero · Mar 17, 2017

Maven profiles has no relation to Spring profiles.

You have two Maven profiles: jar, war

You either use:

mvn clean package -Pjar

or

mvn clean package -Pwar

The error you are getting is while building the artifact because pom needs:

<start-class>your.app.entry.point.Main</start-class>

inside the properties element.

I would suggest to have only one start class regardless of the Maven profile.

something like:

pom.xml:

...
<modelVersion>4.0.0</modelVersion>
<groupId>com.asimio.cloud</groupId>
<artifactId>zuul-server</artifactId>
<version>0-SNAPSHOT</version>
<packaging>${packaging.type}</packaging>
...
<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
  <start-class>your.app.entry.point.Main</start-class>
  <packaging.type>jar</packaging.type>
...
<profiles>
  <profile>
    <id>war</id>
    <properties>
      <packaging.type>war</packaging.type>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
      </dependency>
    </dependencies>
...
  </profile>
</profiles>
...

Main.java:

package your.app.entry.point;
...
@SpringBootApplication
@Import({SecurityConfig.class ,PersistenceConfig.class, ServiceConfig.class})
public class App extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(App.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

No need for Spring profiles. This artifact can now be built using either Maven profile and will run either using:

java -jar .....

when building this artifact as a jar

or

as a war file deployed to a servlet container when built using the -Pwar Maven profile.