GuiSim GuiSim - 7 months ago 99
Java Question

Run Spring-boot's main using IDE

I have a spring-boot application that needs to:


  • Be deployable as a war in a servlet container

  • Be runnable via `mvn spring-boot:run``



I'd also like to be able to run this application in my IDE (Eclipse or IntelliJ IDEA Community) by right clicking on the
main
and running it.

Here are the interesting parts of my pom.xml (Note that I do not inherit from spring-boot-starter-parent pom):

...
<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>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>

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


Here's my
SpringBootServletInitializer
:

@Configuration
@EnableAutoConfiguration
@ComponentScan("com.company.theproject")
public class Application extends SpringBootServletInitializer
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);

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

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


When running the main inside an IDE I get the following error:

org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
... 12 common frames omitted


Seems like
mvn spring-boot:run
does some more magic that does not happen when running the
main
directly.

Removing the
provided
scope from the
spring-boot-starter-tomcat
dependency fixes this issue but causes trouble when the war is run inside a servlet container.

Right now the only "fix" I've found is to run
mvn spring-boot:run
within IntelliJ IDEA instead of running the main directly. While this is an acceptable workaround, I'd still like to know why this doesn't work and if it can be fixed.

Answer

I believe this could be related to https://youtrack.jetbrains.com/issue/IDEA-107048

IntelliJ IDEA is not injecting the provided dependencies into the CLASSPATH and as Andy stated this is why spring is unable to create the embedded servlet container.

They have a feature request since 2005 about this: https://youtrack.jetbrains.com/issue/IDEABKL-99

Workarounds mentioned in the comments includes having a fake module with the necessary libs and using it as classpath, using the -Xbootclasspath JVM argument or using custom maven profiles for running (compiled) vs building (provided).

Comments