Spring boot with maven multi module project

2019-04-10 06:08发布

问题:

I have a maven multi module project designed like the first answer in following SO post: Multi-module maven with Spring Boot

Now I want a common maven module that can contain some models to be used by multiple microservices. If I make this common project as a child of the first level parent pom (so that all dependencies injected by boot like jpa, jackson etc are available to common), then STS/Spring is detecting it as a boot application and complains about no Main class on maven build.

Can someone suggest how I can achieve this?

Current Code:

parent pom.xml: (Only relevant parts included)

<project>
<name>...</name>
<groupId>...</groupId>
<artifactId>...</artifactId>
<packaging>pom</packaging>
<version>...</version>
<parent>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-parent</artifactId>
    <version>Brixton.M3</version>
    <relativePath />
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
</project>

child (common module) pom.xml (only relevant parts), not to be boot app:

<project>
<artifactId>...</artifactId>
<version>...</version>
<name>...</name>

<parent>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
</parent>

</project>

回答1:

I don't have all the details regarding your project but my best guess is that the spring-boot-maven-plugin is defined on the parent (or you are using the spring-boot-starter-parent in your root pom). This effectively ask the build to package your module as a Spring Boot app (which is not what you want).

STS probably looks for that hint to figure out if a module contains a Spring Boot application or not. Maybe it would be nicer if it looks for a main class annotated with @EnableAutoConfiguration (or SpringBootApplication).

You can fix the problem easily (from the build side) by specifying the skip property of the repackage goal

  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
          <skip>true</skip>
    </configuration>
  </plugin>

If STS still picks up the module as a Spring Boot app, I'd create an issue in their tracker



回答2:

Normally, Spring Boot won't start a web container if it's not present in the module. I would suggest you to analyse your dendencies using the command

mvn dependency:tree 

One more brute-force way of ensuring is use this configuration in your application.properties

spring.main.web-environment=false


回答3:

Here are two ways to fix this:

  1. You can add the skip property like @Stephane Nicoll mentioned. However, this will completely ignore the test cases inside that module. https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/it-skip.html
  2. Another option is to add a classifier property to make a separate executable jar out of this module. https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/repackage-classifier.html

    <executions>
              <execution>
                <id>repackage</id>
                <goals>
                  <goal>repackage</goal>
                </goals>
                <configuration>
                  <classifier>exec</classifier>
                </configuration>
              </execution>
    

This fix will make sure the dependent module get its required jar and the source module will still be an executable one.