spring-boot: Document that the jdk.util.jar.enableMultiRelease system property must be set to false when using JSPs with Boot 3.0 and java -jar
Spring Boot 3.0.1 + JDK 17 + packaing war Startup Error by java -jar demo-springboot-jsp.war
I create a simple spring boot project , and config to support very simple jsp, and packing to war.
then run java -jar demo-springboot-jsp.war
if config spring boot 2.7.6 will run and startup success.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
if config spring boot 3.0.1 will run and startup fail.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Error Description first
$ java -jar demo-springboot-jsp.war
...
2022-12-26T13:43:01.062+08:00 INFO 21566 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.4]
2022-12-26T13:43:01.293+08:00 ERROR 21566 --- [ main] org.apache.catalina.core.ContainerBase : A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:na]
...
Compare two version war
Spring boot 2.7.6 , built war , has org/springframework/boot/loader/data/RandomAccessDataFile$1.class
Spring boot 3.0.1, built war , does not have this file.
My Project
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
│ └── demospringbootjsp
│ ├── DemoSpringbootJspApplication.java
│ └── HelloJSPController.java
├── resources
│ └── application.properties
└── webapp
├── index.jsp
└── WEB-INF
└── jsp
└── hello.jsp
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!--<version>3.0.1</version>-->
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-springboot-jsp</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>demo-springboot-jsp</name>
<description>Demo Spring Boot JSP</description>
<properties>
<java.version>17</java.version>
</properties>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
DemoSpringbootJspApplication.java
package com.example.demospringbootjsp;
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 DemoSpringbootJspApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(DemoSpringbootJspApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoSpringbootJspApplication.class, args);
}
}
HelloJSPController.java
package com.example.demospringbootjsp;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
@Controller
public class HelloJSPController {
@RequestMapping(value="/hellojsp", method = RequestMethod.GET)
public ModelAndView hello(Map<String, Object> model) {
System.out.println("HelloJSP Controller hello");
model.put("message", "HelloJSP Controller hello");
// /WEB-INF/jsp/hello.jsp
return new ModelAndView("hello");
}
}
hello.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello</title>
</head>
<%
// debug
System.out.println("webapp / WEB-INF / jsp / hello.jsp ");
%>
<body>
<h1 class="color-red">SpringBoot hello.jsp!! ${message} </h1>
</body>
</html>
Build
mvn clean package
Run
cd target
java -jar demo-springboot-jsp.war
Spring boot 3.0.1
Spring boot 3.0.1 / 3.0.0 demo-springboot-jsp.war , can run ok in standalone apache-tomcat-10.1.4 (some dependency need add scope provided)
but can’t use java -jar demo-springboot-jsp.war
run and startup fail.
Same code, only change to 2.7.6
It can use java -jar demo-springboot-jsp.war
run and startup OK.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 10
- Comments: 24 (12 by maintainers)
Commits related to this issue
- Repair bug in Spring Boot 3.0.5 Issue describe: https://github.com/spring-projects/spring-boot/issues/33633 — committed to ichal6/Follow-the-money-server by ichal6 a year ago
I am facing exactly the same issue. It seems to be caused by tomcat-embed-jasper (JSP support for Tomcat).
The application was working just fine in Spring Boot 2.7. Then, I upgraded it to Spring Boot 3 and I was able to execute it without errors both in my Eclipse environment and from the command line by typing mvn -o spring-boot:run.
Then, I was able to generate the war file using a standard “mvn clean install”. But when I run Spring Boot using “java -jar myFile.war” I got the following error message:
After many trials and errors, I found the problem comes from Jasper. I tried different combinations of versions (Tomcat, Jasper) but nothing was working effectively.
Some other people got the problem too, see for example: https://stackoverflow.com/questions/74913190/spring-boot-apps-jar-not-working-issue-with-tomcat-embed-jasper
This incident is important because otherwise it is impossible to make JSP work with Spring Boot 3.
That might have to do until we can get to the JarFile rewrite.
That’s a good idea. It fixes the sample above:
Perhaps we should just document it rather than disabling multi-release jars out of the box?
Thanks very much, @syphr42. The change is indeed in 10.1.6 and later. Closing in favour of https://github.com/spring-projects/spring-boot/issues/34582 where we upgraded to 10.1.7. I have also updated the migration guide to remove the section on JSPs as this should now work out of the box with Spring Boot 3.0.5 and later or with earlier versions and a manual Tomcat upgrade.
Thanks for the offer, @garretwilson. We’ve added a small section to the migration guide but I think it may also be worth adding a bullet to the list of JSP limitations in the reference documentation. A pull request that does so would certainly be welcome. The source for that section of the documentation is https://github.com/spring-projects/spring-boot/blob/3.0.x/spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/servlet.adoc#jsp-limitations.
As a workaround you could unpack the jar and run it with something like: