Serving JSP with Spring Boot 3

Learn to create and configure JSP view resolver in Spring Boot 3 application which uses JSP template files to render the view layer. Also, learn to build and deploy the application and serve static content in the JSP files.

1. Project Structure

For reference, the files in this application are placed as the given structure in the image.

2. Maven

To sever an application using JSP, we need the following dependencies. Note that we are using the Jakarta Servlet API which uses the Jakarta namespace required by Spring Boot 3.

  • spring-boot-starter-web
  • tomcat-embed-jasper
  • jakarta.servlet.jsp.jstl-api
  • jakarta.servlet.jsp.jstl
<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>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>jakarta.servlet.jsp.jstl</groupId>
  <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>org.glassfish.web</groupId>
  <artifactId>jakarta.servlet.jsp.jstl</artifactId>
  <version>3.0.1</version>
</dependency>

Additionally, we must use the war packaging as jar packaging is not supported as discussed in the official documentation.

<packaging>war</packaging>

3. Application Setup

3.1. Extend SpringBootServletInitializer in the Application Class

The first step in producing a deployable war file is to provide a SpringBootServletInitializer subclass and override its configure() method. This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure the application when it is launched by the Servlet container.

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

@SpringBootApplication
public class App extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(App.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(App.class);
  }
}

3.2. Web Controller

The controller class is a regular @Controller class with request mapping annotations. Please note that we should not use the @RestController annotation, by mistake.

@Controller
public class ItemController {

  @Autowired
  ItemService itemService;

  @RequestMapping("/view-items")
  public ModelAndView viewBooks(ModelAndView model) {

    model.setViewName("view-items");
    model.addObject("items", itemService.getAll());
    return model;
  }
}

3.3. Model and Service

For reference, we are using a simple POJO Item as model and ItemService for returning a list of items. The service returns two items. In a real application, it will connect to the database and fetch the details from the database or any other source.

@Service
public class ItemService {

  public List<Item> getAll() {
    return List.of(new Item(1L, "Item - 1"), new Item(2L, "Item - 2"));
  }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Item {

  private Long id;
  private String name;
}

4. Setting up JSP View Resolver

To resolve JSP files location and automatically configure the JSP view resolver, we can have two approaches:

4.1. Using application.properties

The following properties automatically configure the Spring MVC to serve the content from the configured location and register the JstlView class. It is a specialization of InternalResourceView for JSTL pages, i.e. JSP pages.

Once registered, every view name returned from a handler will be translated to a JSP resource (for example: “home” → “/WEB-INF/jsp/home.jsp“), using this view class to enable explicit JSTL support.

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

4.2. Using Java Configuration

We can configure the JSP view resolution in the Java configuration also, as follows. Do not forget to use the @EnableWebMvc which configures the other necessary beans to support a MVC application.

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

  @Bean
  public ViewResolver viewResolver() {
    final InternalResourceViewResolver bean = new InternalResourceViewResolver();
    bean.setViewClass(JstlView.class);
    bean.setPrefix("/WEB-INF/jsp/");
    bean.setSuffix(".jsp");
    return bean;
  }

  @Override
  public void configureViewResolvers(ViewResolverRegistry registry) {
    registry.viewResolver(viewResolver());
  }
}

4.3. Serving Static Content

By default, Spring MVC serves the static files (JS, CSS etc) from the following directories:

  • /src/main/resources
  • /src/main/resources/static

We can configure the custom URI and directory location as follows. The following configuration will serve a file http://localhost:8080/static/css/style.css from the location /src/main/resources/static/css/style.css.

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

  //...

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry
        .addResourceHandler("/static/**")
        .addResourceLocations("classpath:/static/")
        .setCachePeriod(3600)
        .resourceChain(true)
        .addResolver(new PathResourceResolver());
  }
}

5. JSP Files

The JSP files can be placed in /webapp/WEB-INF/jsp directory as /WEB-INF/jsp path has been configured with the view resolver. Add the webapp directory as the resources root so its content is copied to the root directory when building the project.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <title>View Items</title>
        <link href="/static/css/style.css" rel="stylesheet">
    </head>
    <body>
        <table>
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
                <c:forEach items="${items}" var="item">
                    <tr>
                        <td>${item.id}</td>
                        <td>${item.name}</td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </body>
</html>

6. Package and Run the Application

After the code has been created, we can package the application from the terminal:

mvc clean install

It will create a war file in the target directory. We can run the war file in two ways:

  • Using the java -jar command from the terminal.
  • Deploying in the Tomcat application server.

To run the application from the terminal, run the following command:

java -jar .\target\jsp-demo-1.0-SNAPSHOT.war

It will start the embedded Tomcat server and deploy the application with it.

7. Demo

After the application has been deployed, we can access a valid application URL in the browser and the JSP page will be rendered in the browser.

8. FAQs

8.1. Views are not resolved with 404 Error

In most cases, this error indicates that you are trying to run the application as embedded jar deployment or you are not using the java-jar command to run the application.

To fix this issue, you must run the application with java-jar command or deploy it inside a Tomcat server.

java -jar .\target\jsp-demo-1.0-SNAPSHOT.war

8.2. ClassNotFoundException: jakarta.servlet.jsp.jstl.core.Config

This error indicates that you are still using the javax.servlet:jstl dependency. With the latest Spring Boot release, we must use the Jakarta namespaces so add the following dependency.

<!-- Remove javax packages -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

<!-- Add jakarta packages -->
<dependency>
  <groupId>jakarta.servlet.jsp.jstl</groupId>
  <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>org.glassfish.web</groupId>
  <artifactId>jakarta.servlet.jsp.jstl</artifactId>
  <version>3.0.1</version>
</dependency>

9. Conclusion

In this Spring Boot JSP example, we learned to serve the JSP pages in a Spring boot 3 application, configure the view resolution, and serve static content with a demo. We also learned to fix some common mistakes that developers make when serving the JSP page.

Happy Learning !!

Source Code on Github

Comments

Subscribe
Notify of
guest
22 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode