[Java][JSP][Spring Boot] Spring Boot + good old JSP/Tags = disaster

This article is not about profiling, this time I want to warn you about the Spring Boot defaults, that combined with the JSP pages ang tags can cause functional issues in your application. This issue was found by my friend, I’m just an article writer :)

I know that you may think that no one uses the JSPs anymore. This issue occurred in one of our six-year-old applications, that we migrated from the core Spring at the standalone Tomcat to the Spring Boot.

The application

You can find the source code on my GitHub

Let’s create a simple Spring Boot application with JSP

@SpringBootApplication
public class JspApplication extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(JspApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(JspApplication.class, args);
    }
}
@Controller
class JspController {
    @GetMapping("/")
    public String hello() {
        return "hello";
    }

    @GetMapping("/2")
    public String hello2() {
        return "hello2";
    }
}

… with the properties:

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
logging.level.root=DEBUG

Let’s create two JSP pages hello.jsp and hello2.jsp with the same content:

<!DOCTYPE html>
<%@taglib prefix="inc" tagdir="/WEB-INF/tags" %>

<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
Hello
<inc:included/>
</body>
</html>

… and one tag file included.tag:

<%@tag pageEncoding="UTF-8" %>
<b>Included hello</b>

The Spring logs

Let’s run the application and open URLs:

In the Spring logs we can find:

org.apache.jasper.compiler.Compiler      : Generated /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/tag/web/included_tag.java total=5 generate=4 validate=1
org.apache.jasper.compiler.JDTCompiler   : Compiled /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/tag/web/included_tag.java 133ms
org.apache.jasper.compiler.Compiler      : Generated /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/WEB_002dINF/jsp/hello2_jsp.java total=168 generate=4 validate=12
org.apache.jasper.compiler.JDTCompiler   : Compiled /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/WEB_002dINF/jsp/hello2_jsp.java 56ms
org.apache.jasper.compiler.Compiler      : Generated /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/WEB_002dINF/jsp/hello_jsp.java total=5 generate=2 validate=3
org.apache.jasper.compiler.JDTCompiler   : Compiled /tmp/tomcat.8080.12985973738122585578/work/Tomcat/localhost/ROOT/org/apache/jsp/WEB_002dINF/jsp/hello_jsp.java 48ms

The scary part is that the Java files from the JSP/Tags are generated and compiled in /tmp directory. That directory can be deleted any time by any of your administrators, by the cron job or other external tools like tmpfiles.d. Here is an explanation when CentOS removes files from /tmp.

Let’s cause the disaster

Here is how to create an error:

You will get HTTP 500. In the logs we can see:

2021-04-05 17:27:01.558 ERROR 45318 --- [nio-8080-exec-4] o.a.c.c.C.[.[localhost].[/].[jsp]        : Servlet.service() for servlet [jsp] threw exception

org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: [10] in the jsp file: [/WEB-INF/jsp/hello2.jsp]
org.apache.jsp.tag.web.included_tag cannot be resolved to a type
7: </head>
8: <body>
9: Hello
10: <inc:included/>
11: </body>
12: </html>


An error occurred at line: [10] in the jsp file: [/WEB-INF/jsp/hello2.jsp]
org.apache.jsp.tag.web.included_tag cannot be resolved to a type
7: </head>
8: <body>
9: Hello
10: <inc:included/>
11: </body>
12: </html>

Fix

You need to set the base directory of your embedded Tomcat to some more persistent location. You can set it in application.properties:

server.tomcat.basedir=/path/to/persistent/location

Update: issue at Spring Boot project

I’ve created an issue 25890.