J'ai une application Spring-Boot qui doit:
J'aimerais également pouvoir exécuter cette application dans ma communauté IDE (Eclipse ou IntelliJ IDEA] en cliquant avec le bouton droit de la souris sur la variable main
et en l'exécutant.
Voici les parties intéressantes de mon fichier pom.xml (notez que je n'hérite pas du pom spring-boot-starter-parent):
...
<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>
Voici ma 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);
}
}
Lorsque j'exécute le principal dans un IDE, l'erreur suivante apparaît:
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
On dirait que mvn spring-boot:run
fait encore plus de magie qui ne se produit pas lorsque vous exécutez directement la main
.
La suppression de l'étendue provided
de la dépendance spring-boot-starter-Tomcat
résout ce problème, mais provoque des problèmes lorsque la guerre est exécutée à l'intérieur d'un conteneur de servlet.
À l'heure actuelle, le seul «correctif» que j'ai trouvé consiste à exécuter mvn spring-boot:run
dans IntelliJ IDEA au lieu d'exécuter directement le principal. Bien que cette solution de contournement soit acceptable, j'aimerais tout de même savoir pourquoi cela ne fonctionne pas et si cela peut être corrigé.
Je pense que cela pourrait être lié à https://youtrack.jetbrains.com/issue/IDEA-107048
IntelliJ IDEA n'injecte pas les dépendances provided
dans le CLASSPATH et, comme Andy l'a déclaré, c'est pourquoi spring ne peut pas créer le conteneur de servlets intégré.
Ils ont une demande de fonctionnalité depuis 2005 à ce sujet: https://youtrack.jetbrains.com/issue/IDEABKL-99
Les solutions mentionnées dans les commentaires incluent l'utilisation d'un faux module avec les bibliothèques nécessaires et son utilisation comme chemin de classe, l'utilisation de l'argument JVM -Xbootclasspath ou l'utilisation de profils Maven personnalisés pour exécuter (compiled
) vs building (provided
).
Une solution de contournement fortement inspirée de https://youtrack.jetbrains.com/issue/IDEA-140041 consiste à démarrer votre classe principale avec le classpath de test (qui inclut le servlet intégré.)
Run
-> Edit Configurations
-> Add new configuration
-> Choisissez le type Application
.Main class
sur <your.main.class>
Use classpath of module
sur <*>_test
(le module de test!)Ok
et Run
it!J'ai réussi à faire fonctionner cela en modifiant la portée de la dépendance Spring-boot-starter-Tomcat en "compiler" sous l'onglet Structure du projet-> Dépendances. Cela n'affecte pas pom.xml mais permet à ces dépendances d'être disponibles pour la configuration de démarrage à ressort
mvn spring-boot:run
inclut les dépendances provided
lorsqu’il crée le chemin de classe. Il semble qu'IntelliJ IDEA ne le soit pas. Sans Tomcat sur le chemin de classe, Spring Boot ne peut pas créer de conteneur de servlet intégré, ce qui provoque l'exception que vous voyez. On peut soutenir que c'est un bogue dans IntelliJ car, s'il n'y a pas de conteneur pour fournir la dépendance, alors il faut vraiment qu'il soit sur le chemin de classe.
Vous pourrez peut-être résoudre le problème en remplaçant le chemin d'accès aux classes par défaut utilisé par IntelliJ lors de l'exécution de la méthode main pour inclure la dépendance spring-boot-starter-Tomcat
.
J'ai pu contourner ce problème dans Intellij IDEA 2017.2 en ajoutant le libaray fourni (spring-boot-starter-Tomcat) à la configuration du projet.
Sélectionnez Fichier -> Structure du projet. Sélectionnez Bibliothèques et ajoutez une nouvelle bibliothèque de projet (type = De Maven ...). Recherchez Spring-Boot-Starter-Tomcat dans la boîte de dialogue, sélectionnez la version appropriée et ajoutez-la en cliquant sur OK. La bibliothèque est ajoutée à la liste des bibliothèques externes.
L'inconvénient est que si la version de Spring Spring est modifiée, vous devez vous rappeler de supprimer cette bibliothèque et d'ajouter la nouvelle version.
En utilisant le profil et les instructions ci-dessous, vous pouvez ajouter un profil à maven qui permet le développement dans IntelliJ sans changer les choses pour d’autres environnements.
<!-- Leave original dependency as-is -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<profiles>
<!-- Enable this profile to run in IntelliJ. IntelliJ excludes provided dependencies from compile by default. -->
<profile>
<id>intellij</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
Cliquez sur le bouton Projets Maven situé à droite d’IntelliJ, puis sous Profils , sélectionnez intellij
.
Je trouve cette page et utilise le profil maven pour gérer les profils.
<profiles>
<profile>
<id>PROD</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>DEV</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>TEST</scope>
</dependency>
</dependencies>
</profile>
</profiles>
et configurez la classe principale beforeLanuce
, définissez la commande
mvn clean compile -Pdev
Suivez ces étapes:
En haut à droite de la fenêtre intellij, cliquez sur le menu déroulant, sélectionnez Modifier la configuration pour ouvrir une nouvelle fenêtre.
Dans cette fenêtre, en haut à gauche, cliquez sur le bouton "+" et sélectionnez le démarrage du sprint.
J'ai eu le même problème avec IntelliJ 2018. Ma solution est la suivante:
Allez à Run
-> Edit Configurations
.
Sélectionnez Application
&& choisissez votre projet actuel.
Vérifiez Include dependencies with "Provided" scope
.
OK
-> RUN