WEB-INF not getting added to SpringBoot jar

Viewed 1204

I'm putting together a webapp using SpringBoot.

The REST part works fine, but the "JSP part" is borked. The endpoints are called, everything is fine until I return the basename of the JSP page, such as return "info"; The method returns a String.

When I invoke an endpoint, I get this message:

[...] [dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Could not resolve view with name 'info' in servlet with name 'dispatcherServlet'] with root cause javax.servlet.ServletException: Could not resolve view with name 'info' in servlet with name 'dispatcherServlet'

I followed "the pattern" for adding JSP support to SpringBoot (I say "the pattern" because the dozen or so sources I found all seem to quote the same example).

I'm building a JAR with Maven, looking into that jar, I don't find the JSP files, or even any of the WEB-INF directory structure, so I believe the problem is somewhere between Maven and SpringBoot's plugin.

Here are the pieces of the POM, most of the dependencies removed:

<packaging>jar</packaging>
...

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

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
...
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

The POM was built mostly from an archetype.

I'm rather ignorant about debugging Maven builds, assuming that this is a Maven problem, however, I suppose it could have something to do with the springboot plugin. I appreciate all assistance, include better resources to read than the ones that I found.

UPDATE Per Qiu Zhou's comment about the , I added the following to the POM:

    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>

and moved the JSP directory to src/main/resources/WEB-INF/jsp. The JAR file now contains this:

BOOT-INF/classes/WEB-INF/jsp/info.jsp

which seems to be correct. I no longer get the dispatcherServlet message (see above), however, when I curl the site, this is what I get:

% curl localhost:8099/info
{"timestamp":"2020-09-01T17:22:28.413+00:00","status":404,"error":"Not Found","message":"","path":"/info"}

The controller code is this:

@Controller
public class SimpleController {
   @GetMapping("/info")
   public String info() {
      return "info";
  }
}

I remain perplexed -- Is the JAR built correctly?? Thanks

3 Answers

You are not specifying the version of the plugin you wish to use. Depending on the version you might need to configure the plugin to add the resources directory to the application classpath by adding the following to the plugin configuration

<configuration>
    <addResources>true</addResources>
</configuration>

This enables hot reloading of resources, but what is actually recommended now for this and other development features is adding spring dev tools dependency.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>2.3.3.RELEASE</version>
        <optional>true</optional>
    </dependency>
</dependencies>

You can learn more about it by reading the plugin docs. https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/html/#run

khmarbaise provided a solution in his comment - which was to package the JAR as a WAR. I waited for him to post an answer v. a comment, but its been quite a while, so I will answer on his behalf.

try following steps:

1、include jstl dependency:

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

2、put your jsp files in src/main/webapp/WEB-INF/jsp directory. (manually create it if does not exist)

3、set view prefix in application.properties or application.yml:

   spring.mvc.view.prefix=/WEB-INF/jsp/
   spring.mvc.view.suffix=.jsp

4、specify where jsp files should be in output, put following config in pom.xml(based on the your config):

<packaging>jar</packaging>
...

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

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>
...
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>


    <resources>
      <resource>
          <directory>src/main/webapp</directory>
          <targetPath>META-INF/resources</targetPath>
          <includes>
               <include>**/**</include>
          </includes>
          <filtering>false</filtering>
      </resource>
      <resource>
            <directory>src/main/resources</directory>
      </resource>
   </resources>

 </build>
Related