I'll start off by saying I've looked at and tried the solutions in every question regarding this that I can find. The biggest problem is that most of these solutions are very old, and Spring Boot has changed a lot in the last several years. To be clear, I've tried this, this, this, this, and more. I've also read numerous tutorials. Nothing works.
I have a brand new Spring Boot application and I'm trying to get JSP rendering working with it. These are my dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>[2.8.0,3)</version>
</dependency>
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>[2.7,3)</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>[8.0.21,9)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>[2.3.2,)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>[2.3.4.RELEASE,3)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>[9.0.38,)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>[2.3.4.RELEASE,3)</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
My project is laid out as follows:
- source
- production
- java
- [my source code packages]
- resources
- WEB-APP
- jsp
- initialization
- begin.jsp
- [my resource packages]
- test
- java
- resources
"WEB-APP/jsp" is just the latest iteration I've tried. I've tried "WEB-INF/jsp", "META-INF/jsp", "webapp/jsp", no parent (just "jsp"), etc., all with the same results.
I know the parent directories are a bit non-standard, but it's configured correctly in Maven and I've confirmed it's not the source of my problems:
<build>
<sourceDirectory>source/production/java</sourceDirectory>
<resources>
<resource>
<directory>source/production/resources</directory>
</resource>
</resources>
...
</build>
My Application class is as follows:
@SpringBootApplication(scanBasePackages="com.my.project")
@EnableWebMvc
@EnableJpaRepositories("com.my.project.repository")
@EntityScan("com.my.project.model")
public class Application
{
private static final Logger LOGGER = LogManager.getLogger(Application.class);
public Application()
{
}
@Bean
public ViewResolver viewResolver()
{
LOGGER.info("Constructing InternalResourceViewResolver[JstlView]");
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-APP/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
resolver.setRedirectContextRelative(true);
resolver.setRedirectHttp10Compatible(false);
return resolver;
}
public static void main(final String[] args)
{
SpringApplication.run(Application.class, args);
}
}
And my Controller:
@Controller
public class InitializationController
{
private static final Logger LOGGER = LogManager.getLogger(InitializationController.class);
@GetMapping("/initialize_application")
public String beginInitialization(ModelMap model)
{
LOGGER.info("Beginning initialization");
...
LOGGER.info("Returning view");
return "initialization/begin";
}
...
}
On startup I see the "Constructing InternalResourceViewResolver" log entry (my view resolver bean is created). When I go to /initialize_application
, I get the following error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Oct 18 21:45:26 CDT 2020
There was an unexpected error (type=Not Found, status=404).
Looking in the log again, I see "Beginning initialization" and "Returning view," so I know that the 404 is for my JSP and not my controller. My controller is working.
Other things I've tried:
- Initially I did not have
@EnableWebMvc
on my application. Without it, the log was empty except my log statements. When I added@EnableWebMvc
, this is now logged with the 404:No mapping for GET /WEB-APP/jsp/initialization/begin.jsp
(or whatever other directory I've tried other than "WEB-APP"). - I've tried running this directly on the pure command line with
mvn spring-boot:run
- I've tried running this in IntelliJ IDEA with a Maven run configuration and command
spring-boot:run
(same result) - I've tried both
<packaging>jar</packaging>
and<packaging>war</packaging>
, but neither make a difference, because neither a JAR nor a WAR are ever made. Maven runs the application directly out of thetarget/classes
directory instead of creating an artifact. - When I've tried
WEB-INF
orMETA-INF
instead ofWEB-APP
orwebapp
or something else, I've seen a logged warning:Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/initialization/begin.jsp]
I have also confirmed that my JSPs are present in target/classes/WEB-APP/jsp
(or whatever other directory I've tried other than "WEB-APP"), so they do exist.
I'm at a loss how to proceed. I'm beginning to think I need to ditch Spring Boot and stick with a traditional boilerplate Spring Web MVC application with a Servlet config and a Tomcat installation, but I was really excited about the "just runs" aspect of Spring Boot. Any help would be appreciated.
UPDATE 1
After reading this Spring documentation about JSP limitations, I now know that I have to use <packaging>war</packaging>
, and I'm using that now, but it hasn't made a difference. I'm starting to suspect that the underlying problem here is that maven spring-boot:run
doesn't create a WAR and run it, it just builds everything to target/classes
and runs it from there.
Also, after finding this old, official Spring boot samples application, I've changed my project structure a little:
- source
- production
- java
- [my source code packages]
- resources
- [my resource packages]
- webapp
- META-INF
- WEB-INF
- jsp
- initialization
- begin.jsp
- test
- java
- resources
Updated my view resolver configuration:
resolver.setPrefix("/jsp/");
resolver.setSuffix(".jsp");
And added this to my POM:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<warSourceDirectory>source/production/webapp</warSourceDirectory>
</configuration>
</plugin>
If I run mvn package
, my WAR gets created correctly (classes and JSPs all where they should be), but neither mvn spring-boot:run
nor mvn package spring-boot:run
work—I still get 404 errors resolving my JSPs.
The old Spring Boot sample application linked to above puts the JSPs in WEB-INF/jsp
, but I can't do that, because that results in the warning Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/initialization/begin.jsp]
(and still 404). What's frustrating is that this sample application doesn't exist anymore, nor does any new variation of it. I can't find any updated version that works with the newest version of Spring Boot. The sample application was deleted in 2.2.x.
Can you try by changing the scope of
tomcat-embed-jasper
toprovided
as this dependency is needed to compile JSPs.Edit:
I looked for various
spring-boot + jsp
projects over internet. I noticed that they have they also havespring-boot-starter-tomcat
withprovided
scope. Can you try this.References :
https://mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/
https://dzone.com/articles/spring-boot-2-with-jsp-view
Edit-2 :
So this time i created a new springboot project. Did bare minimum setup to get jsp rendered. So basically i followed this tutorial and my project was running fine.
Then I replaced the pom.xml with yours and the i got the same error you mentioned in the question.
Then while doing trial and error i removed the
<version>[9.0.38,)</version>
from<artifactId>tomcat-embed-jasper</artifactId>
and it started working for me.Although i have different directory structure. But as you mentioned that is not the cause of issue.
I have uploaded the project to github. Feel free to pull it run it locally.
Github