Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying to add a jsp page in my Spring Boot service. My problem is that every time I try to go to that page I have this:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Apr 21 23:16:00 EEST 2015 There was an unexpected error (type=Not Found, status=404). No message available

I have added the prefix and sufix into my application.properties:

spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

This is my controller class:

@Controller
public class MarkerController {
    @RequestMapping(value="/map")
    public String trafficSpy() {
        return "index";

My Application class:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    private static Logger logger = Logger.getLogger(Application.class.getName());
    public static void main(String[] args) {
            logger.info("SPRING VERSION: " + SpringVersion.getVersion());
            SpringApplication.run(Application.class, args);

And the index.jsp:

<!DOCTYPE html>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
    <h1>Hello, World!!!</h1>
    <p>JSTL URL: ${url}</p>
</body>
</html>

And this is the src file structure:

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── internetprogramming
│   │   │               └── myserver
│   │   │                   └── server
│   │   │                       ├── Application.java
│   │   │                       ├── config
│   │   │                       │   └── DatabaseConfig.java
│   │   │                       ├── controller
│   │   │                       │   └── MarkerController.java
│   │   │                       ├── dao
│   │   │                       │   ├── MarkerDaoImplementation.java
│   │   │                       │   └── MarkerDaoInterface.java
│   │   │                       ├── Marker.java
│   │   │                       └── service
│   │   │                           ├── MarkerServiceImplementation.java
│   │   │                           └── MarkerServiceInterface.java
│   │   ├── resources
│   │   │   └── application.properties
│   │   └── webapp
│   │       └── WEB-INF
│   │           └── jsp
│   │               └── index.jsp
                localhost:8080/map I added a debug print in the method and it prints the message so the method is called.
– dephinera
                Apr 21, 2015 at 21:14
                To anyone having 404 Whitelabel Error Page when running from IntelliJ IDEA on multi-module build (i.e. you're running one of subproject apps having these JSPs). Open run configuration and make sure that working directory points to subproject dir, not the root one! I've spent two hours trying to figure out why it still producing 404 even on a minimal sample project perfectly working from maven mvn spring-boot:run. Hope this will help to someone ;)
– Stanislav Mamontov
                Apr 24, 2018 at 12:57
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

Here is a working starter project - https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-jsp

That was it! I had the jstl dependency but not the jasper. It worked after adding it. Thank you! – dephinera Apr 22, 2015 at 18:06 Also! For others with similar problems when using Spring Boot 1.3.0 you have likely missed that spring.view.prefix and spring.view.suffix properties have changed name to spring.mvc.view.prefix and spring.mvc.view.prefix respectively. More info here. – worldsayshi Dec 1, 2015 at 23:24 I had the same problem. In my case, I also had to remove the provided scope from the tomcat-embed-jasper dependency before it worked! – NickGreen Jul 28, 2016 at 8:32 @NickGreen the provided scope may cause issues in production tomcat environments as tomcat provides those libraries already. I fixed this using a profile embedded-tomcat with the custom property tomcat-embed-jasper.scope and setting it as runtime. by default this is provided when not running embedded mode. i.e. <dependency><groupId>..</..><artifactId>embed-tomcat-jasper</..><scope>${tomcat-embed-jasper.scope}</..></..> – coderatchet Jun 1, 2017 at 0:41 sure, however this is merely configuration and whilst effective in most common scenarios, it only reflects the desired location of your jsps. I could set these to spring.mvc.view.prefix=/WEB-INF/foo/bar/jsp and place all my jsps there if i wanted. – coderatchet Jun 1, 2017 at 0:26 @coderatchet actually trying arbitrary folders within the resources folder did NOT work for me in springboot 2.0 application, I had to put the exact folder structure as Ajitesh used for it to finally work. I wish your solution would work as it's more flexible. – JesseBoyd Mar 17, 2018 at 22:38 Thanks, @Ajitesh. I searched many related answers / documents and spent many times on stackoverflow and Spring website. This is the only workable solution for me😭 My workable Spring Boot example commit is here: github.com/MrMYHuang/SpringBootExample/commit/… Does anyone have a way to debug this problem? For example, making Spring Boot print all view search paths? I think it's worthless for human spending so much time and electricity on this problem? 😥 – Meng-Yuan Huang Jul 1, 2020 at 15:13 I use IntelliJ IDEA debugger and a JSP with a syntax error (for getting the file parsing exception stacktrace and then use debugger to find the JSP search paths) to find out the logic used by Spring Boot to locate JSP resources! The logic is written in this file: github.com/spring-projects/spring-boot/blob/… – Meng-Yuan Huang Jul 6, 2020 at 15:23

This is working solution for me about White label error page : Cannot find view page(jsp)

At POM.xml, Make sure packaging is "war" and add tomcat/jasper dependencies

<packaging>war</packaging>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>

Add prefix/suffix at application.properties

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

** If you use Intellij, you must set Web Resource directories. At Project Structure (ctrl+alt+shift+ S) > Facets > Select Web(your application) > Add(+) Web Resource Directories ( mine is ......\src\main\webapp)

** If you have multiple modules(At intellij), Run> Edit configuration> Select springboot your application > Configuration tab> Working directory as $MODULE_WORKING_DIR$

Me too, after a lot of wasted time the $MODULE_WORKING_DIR$ conf in Idea fixed it. Many thanks – Sebastian Zubrinic Oct 8, 2022 at 18:56

Here is simple project with the minimum config: java 17 + spring boot 3.0.5 + JSP - https://github.com/uamaxua/spring-boot-jsp-sample

We were adding Spring Boot to our system in order to run it as executable application without standalone tomcat and also faces the 404 status during JSP initialization.
What should be done for fixing it:

a) Add dependencies to your pom file (WARNING: tomcat-embed-jasper must have compile scope not provided):

<parent>
 <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.3.3.RELEASE</version>
     <relativePath/>
 </parent>
 <dependencies>
   <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>jstl</artifactId>
   </dependency>
   <dependency>
     <groupId>org.apache.tomcat.embed</groupId>
     <artifactId>tomcat-embed-jasper</artifactId>
   </dependency>
 <dependencies>

b) Add spring boot maven plugin for building your application:

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

c) Check that you are using *.war file for your artifact, not jar (because of JSP support limitation):

<packaging>war</packaging>

e) Now you should be able to run your spring boot application using maven plugin or with command line - java -jar /you/path/application-name.war:

f) But if you are using multi-module maven project and want to run spring boot application using IntelliJ Idea it is important to change "Working directory" -> $MODULE_DIR$:

UPDATE 24.02.2023: If you are spring boot >= 2.4.0 then you need some extra configuration:

  • The DefaultServlet provided by the embedded Servlet container is no longer registered by default (more information - here). But for JSP we need to register it again (with spring properties or java config):
  • server.servlet.register-default-servlet=true
    @Bean WebServerFactoryCustomizer enableDefaultServlet() { return factory -> factory.setRegisterDefaultServlet(true);
  • Default Spring MVC no longer performs .* suffix pattern matching where a controller mapped to /person is also implicitly mapped to /person.*. As a consequence path extensions are no longer used to interpret the requested content type for the response — for example, /person.pdf, /person.xml, and so on (more information - here and here).
    It is not recommended to use an extension in URL now. But if you need to use URL with suffix something like: http://localhost:8080/home.jsp then you need to add such configuration:
  • import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreAcceptHeader(false) .useRegisteredExtensionsOnly(true) .defaultContentType(MediaType.TEXT_HTML) .mediaType("jsp", MediaType.TEXT_HTML);

    And specify extension in your controller mapping:

    @GetMapping("/home.jsp")
                    Perfect. This setting did the trick and saved me. I wish I could have seen this thread and the reply a few hours ago, than even on the JetBrains Website in their documentation and manual.
    – itsraghz
                    Sep 11, 2021 at 22:47
                    what ever you have said i have added in my project in intellij , still same error. Could you please help
    – user2949241
                    Jan 12 at 23:05
                    user2949241, yes after updating spring boot to the latest version this approach does not help((( Add your answer if tou find the solution.
    – Maksym
                    Jan 15 at 15:50
                    @Maksym yes, I did. I even wrote an answer about it: stackoverflow.com/a/75822811/20692967. I can't say I understand why the form is dead in the center of the page on your screenshot, but other than that it's expected behavior
    – Sergey Zolotarev
                    Mar 25 at 20:18
    

    If you are using IDEA development tools, then you can try specifying

    Configurations -> Configuration -> environment -> Working directory
    

    The value in $MODULE_DIR$

    my issue was Spring vesrion : I found that since 1.4.3 version and above stops supporting the embedded JSPs . So I change version to 1.4.1 , it's worked for me.

    an other thing take off :

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    

    it will not work with it .

    In addition to the answers above the application needs to be deployed as war instead jar

    <groupId>com.igt</groupId>
    <artifactId>customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    

    to run

    java -jar customer-0.0.1-SNAPSHOT.war
    

    Also If you intend to start your application as a war or as an executable application, you need to share the customizations of the builder in a method that is both available to the SpringBootServletInitializer callback and the main method, something like

    package com.igt.customer;
    import java.util.Arrays;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    @SpringBootApplication
    public class CustomerApplication extends org.springframework.boot.web.support.SpringBootServletInitializer {
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(CustomerApplication.class);
        public static void main(String[] args) {
            SpringApplication.run(CustomerApplication.class, args);
         @Bean
            public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
                return args -> {
                    System.out.println("Let's inspect the beans provided by Spring Boot:");
                    String[] beanNames = ctx.getBeanDefinitionNames();
                    Arrays.sort(beanNames);
                    for (String beanName : beanNames) {
                        System.out.println(beanName);
    

    Please see

    <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <!-- jstl for jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency>

    It may be not enough.

    You must not miss this.

    <packaging>war</packaging>
    

    Otherwise when you build the package, you will get as a jar file and that does not have JSP nor the embedded tomcat.

    See runable example and its explanation here https://www.surasint.com/spring-boot-jsp/

    In case you've been struggling with this for a while and nothing helps, hear me out! I may help you! I've been there: I searched through the internet and was growing pretty desperate, but then I did this, and the problem vanished 🙌

  • You must have this Tomcat dependency
  •         <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
            </dependency>
    

    Notice that it has a default scope. The default scope is compile. It is important that you have this scope!

  • You should have these JSP/JSTL dependencies, both of them (at least, if you use something like a forEach tag)!
  •         <dependency>
                <groupId>jakarta.servlet.jsp.jstl</groupId>
                <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
                <version>3.0.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.glassfish.web</groupId>
                <artifactId>jakarta.servlet.jsp.jstl</artifactId>
                <version>3.0.1</version>
                <scope>provided</scope>
            </dependency>
    

    Notice that they belong to the jakarta package. In my case, it was important! Maybe, it may be important in your case too. Before I migrated my project to Spring Boot, I used javax dependencies, specifically these two

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
    

    When trying to open my home page with those dependencies, I received error 500

    java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.TagLibraryValidator
    

    I added some more javax dependencies to appease Spring a little

            <dependency>
                <groupId>javax.servlet.jsp.jstl</groupId>
                <artifactId>jstl-api</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.2</version>
                <scope>provided</scope>
            </dependency>
    

    and it still didn't work in Spring Boot! This time, I received ClassCastException because apparently Spring needed something specifically from the jakarta package

    java.lang.ClassCastException: class org.apache.taglibs.standard.tlv.JstlCoreTLV cannot be cast to class jakarta.servlet.jsp.tagext.TagLibraryValidator (org.apache.taglibs.standard.tlv.JstlCoreTLV and jakarta.servlet.jsp.tagext.TagLibraryValidator are in unnamed module of loader 'app')
    
  • MOST IMPORTANTLY! It appears you do need a webapp package when working with JSP views! I thought that since it's Spring Boot, I don't need that directory and may place my views in the resources/templates folder as HTML/Thymeleaf folks do. BIG MISTAKE! Even when my properties looked like this
  • spring.mvc.view.prefix=/templates/
    spring.mvc.view.suffix= .jsp
    

    or like this

    spring.mvc.view.prefix=classpath:/templates/
    spring.mvc.view.suffix= .jsp
    

    in fact, any way you could imagine (I tried to describe the directory in all possible ways), I still got that pesky 404! Not before I created a webapp directory had I managed to get rid of that problem

    Notice that tiny bluish circle on the webapp folder icon. I have a suspicion that it's important. As a matter of fact, I did try to create such a directory before, but it didn't have that little circle and moving my JSPs there had no effect on my 404. Why it didn't have that circle the first time? I don't know! But at any rate I suspect that the webapp package should be in the same directory as your source root. In this case, it's the java package. So since it's in the main folder, your webapp directory should be in the main folder too

    Fun fact! My favicon and CSS stylesheet are still in the resources directory (that is, in the resources/static directory)! Despite that, Spring has no problem figuring out where they are. So the webapp package is necessary only for your JSPs (perhaps, you can store CSSs and favicons there too, I didn't try it, but at least you don't have to)

    Why it works this way with JSP? Search me! I have no idea at all! But it's what helped me and what you should apparently do too if you experience the same issue

    You can get in touch with me and request the project's repo if that's something you need 👌

    UPD: A quick note. Some folks maintain that you need to have a WAR package for JSP projects. It doesn't appear so! But keep it in mind anyway. If you did every thing I listed and it still doesn't work, tweaking that property may be a good thing to try 🤷‍♂️

    UPD2: After I removed the WAR packaging setting, the little circle on the webapp icon disappeared. But the page still opens! So since you apparently don't need WAR packaging, you also shouldn't be concerned about the blue circle. I take that back! Or maybe, the circle has nothing to do with WAR at all as I briefly returned that property and clean-installed the project, and it didn't appear again 🤷‍♂️

    UPD3: By the way, that underlining never went away. But it's okay! It works nonetheless

    Spring MVC offers no default (fall-back) error page out-of-the-box. The most common way to set a default error page has always been the SimpleMappingExceptionResolver (since Spring V1 in fact). However Spring Boot also provides for a fallback error-handling page.

    At start-up, Spring Boot tries to find a mapping for /error. By convention, a URL ending in /error maps to a logical view of the same name: error. Generally this view maps in turn to the error.html Thymeleaf template. (If using JSP, it would map to error.jsp according to the setup of your InternalResourceViewResolver).

    Spring Boot will automatically use and configure Thymeleaf as the view rendering engine, as long as it's on the classpath.

    Thymeleaf with Maven:

    Make sure you have Maven 3 installed with the following command: mvn --version. Navigate to the directory you want to create your project in and execute Maven archtetype:

    mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=pl.codeleak.demos.sbt -DartifactId=spring-boot-thymeleaf -interactiveMode=false
    

    The above command will create a new directory spring-boot-thymeleaf. Now you can import it to your IDE. The next step is to configure the application. Open pom.xml and add a parent project:

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

    Values from the parent project will be the default for this project if they are left unspecified. The next step is to add web dependencies. In order to do so, I firstly removed all previous dependencies (junit 3.8.1 actually) and added the below dependencies:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>
    

    Now, wait a second until Maven downloads the dependencies and run mvn dependency:tree to see what dependencies are included. The next thing is a packaging configuration. Let's add Spring Boot Maven Plugin:

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

    Thymeleaf with Gradle:

    To put Thymeleaf on the classpath use

    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    

    in the gradle build file (using the relevant maven dependency is straightforward).

    In your case in order to display the index.jsp view (in accordance to the controller you are using), you need to place it under src/main/resources/templates/.

    If no mapping from /error to a View can be found, Spring Boot defines its own fall-back error page - the so-called Whitelabel Error Page (a minimal page with just the HTTP status information and any error details, such as the message from an uncaught exception).

    Thank you for your detailed answer but I don't want to map from /error. I want index.jsp to be returned and rendered when go to <whatever my adress is>/map – dephinera Apr 21, 2015 at 22:11

    You can use thymeleaf with jsp but you have to write:

    spring.thymeleaf.excluded-view-names=#jsp file without extension
    

    in application.properties file

    For spring-boot, Jsp templates or Thymeleaf templates mapping of spring MVC mapping prefix into classpath.

    Ex. /views/some_path needs to be located in the project src/main/resources/META-INF/resources/views/some_path

  • Thymeleaf templates work also in URL-based path file:///some_path
  • Jsp templates don't work in URL-based path file:///some_path
  •