Unable to serve JSP in Spring Boot applications - spring-boot

I have tried several tutorials to serve JSP pages using Spring Boot. They all return a 404 page not found error.
To overcome the known limitations, I'm using a WAR packaging, with the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
I have defined the path where JSP pages are in application.properties:
spring.mvc.view.prefix= /WEB-INF/jsp/
spring.mvc.view.suffix= .jsp
When requesting a JSP page, the following WARN is displayed:
WARN 10251 --- [io-8080-exec-11] o.s.w.s.r.ResourceHttpRequestHandler : Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/hello.jsp]
Have JSP been deprecated in Spring Boot 2? Do you have any Spring Boot 2 working example with JSP ?

can you please try adding scope in your dependency just like this
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>

I'm using Intellij IDEA. I found out that we cannot just run the SpringBootApplication main class directly. We need to let the maven do the work.
Short solution: maven run you application by the command below from your module root directory
mvn clean package spring-boot:run
You can also add a run configuration using Maven so that you don't have to type the command every time.
Some said JSPs folder should be put under src/main/resources/META-INF/resources/WEB-INF/jsp. This indeed solves the spring boot application run problem though, it will fail when you run the application using tomcat. So we still need to keep the structure if we are going to deploy the application to Tomcat.

Unfortunately, I couldn't find any Spring Boot 2 example able to serve JSP pages as they all return a 404 error. As a workaround I have configured the application to be deployed on WildFly, as described in this tutorial and run my application with JSP on WildFly.

If you want example here it is.
This also help you.

Related

Spring Boot 3 JSP Issue

I've been having issues with JSP since moving to Java 17 and Spring Boot 3. I know that we need to use jakarta.* instead of javax.*, but is there something I'm missing? I am using Spring Tools 4 and just running a basic web app using JSP. When using the following dependencies
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
</dependency>
The project runs, but I get the following error
The superclass "javax.servlet.http.HttpServlet", determined from the Dynamic Web Module facet version (2.5), was not found on the Java Build Path
I can get rid of it by adding the javax servlet dependency
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
But that goes against using javax.* dependencies with Spring Boot 3.
I have read these articles and tried adding the jakarta.servlet.jsp dependency with no luck.
https://debugah.com/solved-tomcat10-error-jakarta-servlet-servletexception-class-com-kuang-servlet-helloservlet-is-not-a-servlet-22749/
https://howtodoinjava.com/java/exception-handling/solved-the-superclass-javax-servlet-http-httpservlet-was-not-found-on-the-java-build-path-in-eclipse/
Solved!
All I had to do was go into Project Properties and under Project Faces, change my Dynamic Web Module from 2.5 to 5.0
The JSTL warning can be suppressed under Properties->Web->JSP Files->Validation->Custom actions->Other problems with TagExtraInfo class (Just change from 'Warning' to 'Ignore')

Springboot 2.0.2 not working with thymeleaf template, throwing 404 error

I am using Springboot 1.5.7 for my rest api application, and I am using thymeleaf template to send emails from my api. But when I updated the version of spring boot to 2.0.2 its throwing 404 error i.e "Error resolving template "error", template might not exist or might not be accessible by any of the configured Template Resolvers".
Below is the config I have in application.yml
spring:
thymeleaf:
cache: false
enabled: true
mode: HTML5
prefix: /templates/
suffix: .html
thymeleaf version in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
Below is the template structure i am using,
My app release is very near and I am badly stuck with this problem, if someone can provide me workaround then it would be a great help.
Remove prefix: /templates/ from application.yml
If still does not work, add thymeleaf-layout-dialect dependency (See: Thymeleaf stopped resolving layout templates after migrating to Thymeleaf 3)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
FYI, I put my views in WEB-INF/webapp/views, so I am using prefix: /WEB-INF/webapp/views/ (spring boot war deploy to tomcat)
As stated in the 2.0 migration guide.
The Thymeleaf starter included the thymeleaf-layout-dialect dependency
previously. Since Thymeleaf 3.0 now offers a native way to implement
layouts,
we removed that mandatory dependency and leave this choice up to you.
If your application is relying on the layout-dialect project, please
add it explicitly as a dependency.
Adding the following dependencies should work
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
SOURCE : https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#template-engines

ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean

I have written a spring batch application using Spring boot. When I am trying to run that application using command line and classpath on my local system it is running fine. However, when I tried to run it on linux server it is giving me following exception
Unable to start web server; nested exception is
org.springframework.context.ApplicationContextException:
Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
Below is the way I am running it:
java -cp jarFileName.jar; lib\* -Dlogging.level.org.springframework=DEBUG -Dspring.profiles.active=dev -Dspring.batch.job.names=abcBatchJob com.aa.bb.StartSpringBatch > somelogs.log
Case 1:
#SpringBootApplication annotation missing in your spring boot starter class.
Case 2:
For non-web applications, disable web application type in the properties file.
In application.properties:
spring.main.web-application-type=none
If you use application.yml then add:
spring:
main:
web-application-type: none
For web applications, extends *SpringBootServletInitializer* in the main class.
#SpringBootApplication
public class YourAppliationName extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(YourAppliationName.class, args);
}
}
Case 3:
If you use spring-boot-starter-webflux then also add spring-boot-starter-web as dependency.
Probably you missing #SpringBootApplication in your spring boot starter class.
#SpringBootApplication
public class LoginSecurityAppApplication {
public static void main(String[] args) {
SpringApplication.run(LoginSecurityAppApplication.class, args);
}
}
The solution is:
I explicitly set the below property to none in application.yml file.
spring:
main:
web-application-type: none
My solution had to do with a bad dependency. I had:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
In my pom and I had to comment out the exclusion to get it working. It must look for this tomcat package for some reason.
In my case the issue resolved on commenting the tomcat dependencies exclusion from spring-boot-starte-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions> -->
</dependency>
You probably use this in your project:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
in which case you'll have to also add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
and the magic happens :)
PS: that's because Spring will use by default web-MVC instead of web-flux when both are available
Adding following bean worked for me.
#Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
I was running non web spring application using SpringApplication.run(MyApplication.class, args); without #SpringBootApplication annotation.
Annotate class public static void main with, for example: #SpringBootApplication
To convert an Spring boot wen application to standalone:
Either configure application.properties:
spring.main.web-application-type=none
Or Update application context with NONE web context.
ApplicationContext ctx = new SpringApplicationBuilder(MigrationRunner.class)
.web(WebApplicationType.NONE).run(args);
Using application context, you can get your beans:
myBean bean = (MyBean) ctx.getBean("myBean", MyBean.class);
bean.call_a_method(..);
I had this problem during migration to Spring Boot. I've found a advice to remove dependencies and it helped. So, I removed dependency for jsp-api Project had. Also, servlet-api dependency has to be removed as well.
compileOnly group: 'javax.servlet.jsp', name: 'jsp-api', version: '2.2'
As for me, I removed the provided scope in tomcat dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> // remove this scope
</dependency>
I did right click on my project in IntelliJ IDEA then Maven -> Reload project, problem solved.
In case you're using IntelliJ and this is happening to you (like it did to my noob-self), ensure the Run setting has Spring Boot Application and NOT plain Application.
I was getting same error while using tomcat-jasper newer version
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>10.0.6</version>
</dependency>
I replaced with the stable older version it worked fine for me.
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>9.0.46</version>
</dependency>
Apart from the possible solutions in other answers, it is also possible that somehow Maven dependency corruption has occurred on your machine. I was facing the same error on trying to run my (Web) Spring boot application, and it got resolved by running the following -
mvn dependency:purge-local-repository -DreResolve=true
followed by
mvn package
I came onto this solution looking into another issue where Eclipse wouldn't let me run the main application class from the IDE, due to a different error, similar to one on this SO thread -> The type org.springframework.context.ConfigurableApplicationContext cannot be resolved. It is indirectly referenced from required .class files
Similar to the solution of making sure org.springframework.boot:spring-boot-starter-tomcat was installed, I was missing org.eclipse.jetty:jetty-server from my build.gradle
org.springframework.boot:spring-boot-starter-web needs a server be it Tomcat, Jetty or something else - it will compile but not run without one.
I wanted to run the WAR type spring boot application, and when I was trying to run the app as spring boot application I was getting above error. So declaring the web application type in application.properties has worked for me.
spring.main.web-application-type=none
Possible web application type:
NONE - the application should not run as a web application and should not start an embedded web server.
REACTIVE - the application should run as a reactive web application and should start an embedded reactive web server.
SERVLET - the application should run as a servlet-based web application and should start an embedded servlet web server.
In my case, the problem was I didn't had a Tomcat server separately installed in my eclipse. I assumed my Springboot will start the server automatically within itself.
Since my main class extends SpringBootServletInitializer and override configure method, I definitely need a Tomcat server installed in my IDE.
To install, first download Apachce Tomcat (version 9 in my case) and create server using Servers tab.
After installation, run the main class on server.
Run As -> Run on Server
I was trying to create a web application with spring boot and I got the same error.
After inspecting I found that I was missing a dependency. So, be sure to add following dependency to your pom.xml file.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Missing dependency could be cause of this issue
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I encountered this problem when attempint to run my web application as a fat jar rather than from within my IDE (IntelliJ).
This is what worked for me. Simply adding a default profile to the application.properties file.
spring.profiles.active=default
You don't have to use default if you have already set up other specific profiles (dev/test/prod). But if you haven't this is necessary to run the application as a fat jar.
Upgrading spring-boot-starter-parent in pom.xml to the latest version fixed it for me.
In my case, I was using an TOMCAT 8 and updating to TOMCAT 9 fixed it:
<modelVersion>4.0.0</modelVersion>
<groupId>spring-boot-app</groupId>
<artifactId>spring-boot-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<tomcat.version>9.0.37</tomcat.version>
</properties>
Related issues:
https://github.com/spring-projects/spring-boot/issues?q=missing+ServletWebServerFactory+bean
https://github.com/spring-projects/spring-boot/issues/22013 - Spring Boot app as a module
https://github.com/spring-projects/spring-boot/issues/19141 - Application fails to load when main class extends a base class annotated with #SpringBootApplication when spring-boot-starter-web is included as a dependency
My problem was the same as that in the original question, only that I was running via Eclipse and not cmd. Tried all the solutions listed, but didn't work. The final working solution for me, however, was while running via cmd (or can be run similarly via Eclipse). Used a modified command appended with spring config from cmd:
start java -Xms512m -Xmx1024m <and the usual parameters as needed, like PrintGC etc> -Dspring.config.location=<propertiesfiles> -jar <jar>
I guess my issue was the spring configurations not being loaded correctly.
In my case, the gretty plugin (3.0.6) was still active. Gretty somehow influences the embedded tomcat dependency. Removing gretty fixed the error
Just comment the provided like below

Spring Boot - Cleaning up Tomcat dependencies when creating a non-executable war file

From the Spring Boot documentation:
To build a war file that is both executable and deployable into an external container you need to mark the embedded container dependencies as “provided”.
Which looks like this:
<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>
However various tomcat packages still remain as dependencies (and thus show up in my /lib folder), namely:
tomcat-embed-el (a dependency of spring-boot-starter-validation)
tomcat-jdbc (a dependency of spring-boot-starter-jdbc)
Since I will only ever need to deploy my application inside a container and never to run it standalone, how should I proceed with disposing of these dependencies?
P.S. It seems that the first dependency issue is fixed in 1.4.0.M2, see
https://github.com/spring-projects/spring-boot/issues/5454

Not Able to Resolve View Using Spring boot

I have put all jsp on classpath in views folder.
Folder structure is :
src/main/resources/
src/main/resources/static/
src/main/resources/static/views/
src/main/resources/static/views/*.jsp
src/main/resources/static/views/*.png
I am able to retrieve images file from static folder. But When It comes to jsp I am getting following error.
While hitting url:http://localhost:9001/login
There was an unexpected error (type=Not Found, status=404).
/views/login/login.jsp
However login.jsp exists on given location.
You can place your JSP files in "src/main/resources/META-INF/resources" folder location.
I have created a "WEB-INF/jsp" folder under "src/main/resources/META-INF/resources" and placed the JSP file there.It works. Check the screenshot.
https://i.stack.imgur.com/P3jUI.png
Alternatively, You can create "WEB-INF/jsp" folder under "src/main/webapp" and placed the JSP file there.But for this you have to package it as ".war" extension.
Springboot default tomcat container does not handle JSP. so we need to use below dependency to handle it :
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
And if you are using JSTL tags in JSP then add below jar as well :
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
A template such as a JSP is the exact opposite of static content such as an image file. Put your template in src/main/resources/templates.
Put them in folder :
src/main/resources/templates
2.These three dependencies could help you:
<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>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
I believe by default Spring Boot looks for html files. To change that behavior you have to change your application.properties as following to use jsp-s: spring.view.suffix: .jsp
Maybe even change spring.view.prefix as well to point to static resources.
I would personally suggest to use html-s with Thymeleaf though.
I was supposed to use war as packaging. Jar packaging does not work in case of jsp.

Resources