[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:
http://localhost:8080/
http://localhost:8080/2
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:
- Start the application
- Open
http://localhost:8080/
- Remove
work
directory:rm -fr /tmp/tomcat*
- Open
http://localhost:8080/2
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.