Deploying embedded tomcat spring-boot application using IntelliJ

I have a spring-boot application using embedded tomcat. I have no problem deploying with a mvn spring-boot:run

target , but . I am having problems trying to deploy with intelliJ spring-boot plugins. It is important to note that we changed the default setting, turning our application into war, which can be deployed to full tomcat Traditional deployment , but this in development mode would be better to just deploy the application using embedded tomcat. The problem is that basically we ended up with this post when trying to start spring boot application from intelliJ

Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.support.SpringBootServletInitializer
    at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.retrieveBeanMethodMetadata(ConfigurationClassParser.java:380) ~[spring-context-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:314) ~[spring-context-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    ... 17 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
    at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_144]
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_144]
    at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_144]
    at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    ... 22 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_144]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_144]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_144]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_144]
    ... 26 common frames omitted

      

Do you have any idea why this is happening? and how can we solve it?

EDIT:

I am using IntelliJ IDEA 2017.2 (just in case the build is idea-IU-172.3317.76) and as an SSCCE allows the spring-boot example to be used and allows the changes suggested for traditional deployment to be applied (first link) we will have the following files

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>org.springframework</groupId>
    <artifactId>gs-spring-boot</artifactId>
    <version>0.1.0</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>

    <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>
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

      

Then we will have Application.java

package hello;

import java.util.Arrays;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

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

        System.out.println("Let inspect the beans provided by Spring Boot:");

        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }

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

}

      

And I haven't modified HelloController.java , but just for completeness:

package hello;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

      

This example works without issue with help mvn spring-boot:run

, but fails to start when using spring-boot intelliJ plug-in

+3


source to share


2 answers


Note - this answer is referring to Spring documentation for version 1.5.6.RELEASE (current version)




Analyzes:

Running the main class from IJ is similar to running your application from the command line. This way, the classpath will only include dependent scopes compile

and runtime

. Provided

means it will be needed at compile time, but you would expect the JDK or container to provide it for your application at runtime:

Provided

This is very similar to compile

, but indicates that you expect the JDK or container to provide a runtime dependency . For example, when building a web application for Java Enterprise Edition, you must install a dependency on the servlet API and its associated Java EE scoped APIs Provided

, since the web container exposes these classes. This scope is only available in the compilation and test path and is not transitive.

On the other hand, spring-boot-maven-plugin

uses a different classpath to accomplish the goal run

:

By default, in integers repackage

and any dependencies that are defined in the project run

will be specified . A download based project must account for dependencies as container dependencies required to run the application.Provided

Provided




Conclusion and solutions:

So this is a class configuration issue. As you mentioned, for war packaging or traditional deployment , you should exclude the embedded servlet container. However, to be able to run your application during development, you need an embedded container.

As a solution or work around, you have at least the following 2 options:

1) Remove <scope>provided</scope>

dependencies from declaration spring-boot-starter-tomcat

. You can remove this dependency completely if you want as Tomcat is the default container usedspring-boot-starter-web

, but it might be better to leave it that way and add a comment so you won't forget about it when you drop

2) A clean trick that works with IJ and will make it easy not to forget to uncomment Provided

before releasing the release to leave the dependency as it is now and add a maven dev

that you can activate from within IJ. So it will be by default Provided

and it can be safely packaged in war and only when developing and manually activating the profile will it be enabled. After adding the profile, reimport your maven project so you can select the profile:

<profiles>
    <profile>
        <id>dev</id>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
        </dependencies>
    </profile>
</profiles>

      

reimport the project and activate the profile

+2


source


If you are using a maven project you need to add the dependency javax.servlet-api

.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

      



you can also download the jar from http://central.maven.org/maven2/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar

0


source







All Articles