Bug 65599 - Tomcat 8.5 cannot compile JSPs with Java 17 (System cannot be resolved)
Summary: Tomcat 8.5 cannot compile JSPs with Java 17 (System cannot be resolved)
Status: RESOLVED WONTFIX
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Jasper (show other bugs)
Version: 8.5.71
Hardware: PC All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-27 20:54 UTC by Denis Fuenzalida
Modified: 2022-11-21 04:45 UTC (History)
0 users



Attachments
Catalina output with the stacktrace when attempting to compile the JSP in Java 17 (12.10 KB, text/plain)
2021-09-27 20:54 UTC, Denis Fuenzalida
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Denis Fuenzalida 2021-09-27 20:54:50 UTC
Created attachment 38049 [details]
Catalina output with the stacktrace when attempting to compile the JSP in Java 17

When running the latest Tomcat 8.5.71 with Java 17, it seems the version of ECL bundled with Tomcat is too old and cannot load the classes from the JDK, resulting in an error when compiling trivial JSPs like the following:

	<%@ page session="false" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
	<!DOCTYPE html>
	<html>
	  <body>
		<%= System.getProperty("os.name") %>
	  </body>
	</html>

The error looks like:

	HTTP Status 500 – Internal Server Error
	Type Exception Report

	Message Unable to compile class for JSP:

	Description The server encountered an unexpected condition that prevented it from fulfilling the request.

	Exception

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

	An error occurred at line: [5] in the jsp file: [/index.jsp]
	System cannot be resolved
	2: <!DOCTYPE html>
	3: <html>
	4:   <body>
	5:     <%= System.getProperty("os.name") %>
	6:   </body>
	7: </html>

We've found that replacing the ECL Jar bundled with Tomcat 8.5.71 (ecj-4.6.3.jar) with the version from Tomcat 9.0.53 (ecj-4.20.jar) fixes the issue.

We've tested this occurs with JDKs from multiple vendors including Adoptium, Oracle (from jdk.java.net) and Azul.

Kind regards,

-- Denis
Comment 1 Mark Thomas 2021-09-27 21:02:59 UTC
This is as expected.

Tomcat 8.5.x is required (by the Java EE specification) to run on Java 7. The version of ECJ that ships with Tomcat 8.5.x is the most recent that runs on Java 7.

Tomcat has been written so that if you replace the ECJ Jar with a newer version (and run on a newer version of Java) you can compile against more recent versions of Java. The other option is to switch to using Ant as the compiler.
Comment 2 Konstantin Kolinko 2021-10-02 15:48:04 UTC
Additional notes:
1. This is reproducible with Tomcat 8.5.72 (RC) and Java 17.0.0

a) The following unit test is failing (for all connectors):
org.apache.catalina.mapper.TestMapperWebapps

b) In the examples web application the following pages are failing to compile:
Servlet Examples -> async1 and async3
JSP Examples -> Include
http://localhost:8080/examples/async/async1
http://localhost:8080/examples/async/async3
http://localhost:8080/examples/jsp/include/include.jsp

All other pages are OK.


2. Looking the "Include" page example, when the error occurs,
there are TWO errors that are logged:

a) In localhost.*.log

The same error message, as seen on the failing JSP page,
[[[
02-Oct-2021 18:19:06.305 SEVERE [http-nio-8080-exec-1] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [jsp] in context with path [/examples] threw exception [Unable to compile class for JSP: 

An error occurred at line: [17] in the jsp file: [/jsp/include/foo.jsp]
System cannot be resolved
14:   See the License for the specific language governing permissions and
15:   limitations under the License.
16: 
17: --%><%= System.currentTimeMillis() %>


Stacktrace:] with root cause
 org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: [17] in the jsp file: [/jsp/include/foo.jsp]
System cannot be resolved
14:   See the License for the specific language governing permissions and
15:   limitations under the License.
16: 
17: --%><%= System.currentTimeMillis() %>


Stacktrace:
  at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:101)
  at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:213)
  at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:556)
  at org.apache.jasper.compiler.Compiler.compile(Compiler.java:380)
  at org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
  at org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
  at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:597)
  at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:398)
  at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:383)
  at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:331)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:126)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:109)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:196)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
  at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:364)
  at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:624)
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1650)
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  at java.base/java.lang.Thread.run(Thread.java:833)
]]]


b) In catalina.*.log there is an additional error that is logged AT THE SAME time,

[[[
02-Oct-2021 18:19:06.305 SEVERE [http-nio-8080-exec-1] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() для сервлета [jsp] в контексте с путем [/examples] выбросил исключение [Unable to compile class for JSP: 

An error occurred at line: [17] in the jsp file: [/jsp/include/foo.jsp]
System cannot be resolved
14:   See the License for the specific language governing permissions and
15:   limitations under the License.
16: 
17: --%><%= System.currentTimeMillis() %>


Stacktrace:] с первопричиной
	org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: [17] in the jsp file: [/jsp/include/foo.jsp]
System cannot be resolved
14:   See the License for the specific language governing permissions and
15:   limitations under the License.
16: 
17: --%><%= System.currentTimeMillis() %>


Stacktrace:
		at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:101)
		at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:213)
		at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:556)
		at org.apache.jasper.compiler.Compiler.compile(Compiler.java:380)
		at org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
		at org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
		at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:597)
		at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:398)
		at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:383)
		at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:331)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:126)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:109)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:196)
		at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
		at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
		at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
		at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
		at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
		at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
		at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:364)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:624)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1650)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.base/java.lang.Thread.run(Thread.java:833)
]]]


3. Regarding the second error:
a) I wonder why is it logged into Tomcat-wide catalina log instead of localhost log.
b) The message string for key "jsp.error.compilation.dependent" is missing.


4. If I define a message string (for 3.b)), I can see the name of the class file that fails to load.

To do so:
a) I created directory lib/org/apache/jasper/resources/
b) Extracted there the LocalStrings.properties file from lib/jasper.jar (from org/apache/jasper/resources/ within it)
c) Added the following line to the file:
jsp.error.compilation.dependent=The "jsp.error.compilation.dependent" error for class [{0}]

With this change the error message above changes to be

[[[
02-Oct-2021 18:19:06.264 SEVERE [http-nio-8080-exec-1] org.apache.jasper.compiler.JDTCompiler$1.findType The "jsp.error.compilation.dependent" error for class [java.lang.System]
	org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException
		at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.<init>(ClassFileReader.java:406)
		at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:231)
		at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:207)

]]]


5. Concluding,
So this means that the compiler tries to read the java.lang.System class and fails.
There is nothing that we can do to workaround that failure in Tomcat / Jasper code.

The only feasible approach is to suggest upgrading the bundled compiler,
as Mark answered in Comment 1.

I am changing resolution from INVALID to WONTFIX, as this is something that needs to be documented.
Improving the error handling (3.b)) is a separate issue.
Comment 3 Konstantin Kolinko 2022-11-21 04:45:17 UTC
See also discussion
"ECJ, Tomcat 8.5.x and Java 17", started 2021-10-07 on dev@t.a.o
https://lists.apache.org/thread/5489jyfry6zypr3x43qypqoxx02dqz08

including an Ant build file to pack several versions of jdt into a Multi-Release jar.
https://lists.apache.org/thread/p37z53018189r9t0k852sz0jcqb60tox