This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 8b0259c31cad672e227db14dd4bcc47f2d238845
Author: ddekany <ddek...@apache.org>
AuthorDate: Sat Dec 9 15:30:23 2023 +0100

    Switched to Java 17 as the minimum Java version. Forward ported changes 
from 2.3-gae that was done there to allow tests running with Java 16. Forward 
ported FreemarkerServlet debug error page fix too.
---
 .../build/module/common/FreemarkerJavaPlugin.kt    |   2 +-
 .../org/apache/freemarker/core/DateFormatTest.java |  31 ++--
 .../model/impl/RestrictedObjectWrapperTest.java    |  42 ++----
 .../core/valueformat/NumberFormatTest.java         |   2 +-
 .../core/templatesuite/expected/number-format.txt  |   4 +-
 .../core/model/impl/ClassIntrospector.java         |  53 ++-----
 .../org/apache/freemarker/core/util/_Java21.java   |  28 ++--
 .../apache/freemarker/core/util/_Java21Impl.java   |  26 ++--
 .../apache/freemarker/core/util/_JavaVersions.java |  51 ++-----
 .../java/org/apache/freemarker/dom/NodeModel.java  |  53 +------
 .../dom/SunInternalXalanXPathSupport.java          | 160 ---------------------
 .../dom/DefaultObjectWrapperExtensionTest.java     |  16 ++-
 freemarker-servlet/build.gradle.kts                |  28 ++--
 .../freemarker/servlet/FreemarkerServlet.java      |  83 ++++++-----
 .../servlet/DummyMockServletContext.java           |  20 ++-
 .../freemarker/servlet/test/WebAppTestCase.java    |  51 +++++--
 .../src/main/resources/logback-test.xml            |   3 +-
 osgi.bnd                                           |   2 +-
 settings.gradle.kts                                |   2 -
 19 files changed, 191 insertions(+), 466 deletions(-)

diff --git 
a/buildSrc/module-common/src/main/kotlin/org/apache/freemarker/build/module/common/FreemarkerJavaPlugin.kt
 
b/buildSrc/module-common/src/main/kotlin/org/apache/freemarker/build/module/common/FreemarkerJavaPlugin.kt
index 1d44d5f2..e71c8fb3 100644
--- 
a/buildSrc/module-common/src/main/kotlin/org/apache/freemarker/build/module/common/FreemarkerJavaPlugin.kt
+++ 
b/buildSrc/module-common/src/main/kotlin/org/apache/freemarker/build/module/common/FreemarkerJavaPlugin.kt
@@ -34,7 +34,7 @@ import org.gradle.kotlin.dsl.withType
 fun getDefaultJavaVersion(project: Project): JavaLanguageVersion {
     return project.providers
         .gradleProperty("freemarkerDefaultJavaVersion")
-        .getOrElse("8")
+        .getOrElse("17")
         .let { JavaLanguageVersion.of(it) }
 }
 
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
index ae9fc027..2c7eab9f 100644
--- 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
@@ -18,26 +18,12 @@
  */
 package org.apache.freemarker.core;
 
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
+import com.google.common.collect.ImmutableMap;
 import org.apache.freemarker.core.model.TemplateDateModel;
 import org.apache.freemarker.core.model.impl.SimpleDate;
 import 
org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
 import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
-import org.apache.freemarker.core.userpkg.AppMetaTemplateDateFormatFactory;
-import 
org.apache.freemarker.core.userpkg.EpochMillisDivTemplateDateFormatFactory;
-import org.apache.freemarker.core.userpkg.EpochMillisTemplateDateFormatFactory;
-import org.apache.freemarker.core.userpkg.HTMLISOTemplateDateFormatFactory;
-import 
org.apache.freemarker.core.userpkg.LocAndTZSensitiveTemplateDateFormatFactory;
+import org.apache.freemarker.core.userpkg.*;
 import org.apache.freemarker.core.valueformat.TemplateDateFormat;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.UndefinedCustomFormatException;
@@ -45,7 +31,16 @@ import 
org.apache.freemarker.core.valueformat.impl.AliasTemplateDateFormatFactor
 import org.apache.freemarker.test.TemplateTest;
 import org.junit.Test;
 
-import com.google.common.collect.ImmutableMap;
+import java.io.IOException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.*;
 
 public class DateFormatTest extends TemplateTest {
     
@@ -372,7 +367,7 @@ public class DateFormatTest extends TemplateTest {
                 + "<#setting locale='en_GB_Win'>${d} "
                 + "<#setting locale='fr_FR'>${d} "
                 + "<#setting locale='hu_HU'>${d}",
-                "2015-Sep_en 2015-Sep_en_GB 2015-Sep_en_GB 2015-sept._fr_FR 
2015-szept.");
+                "2015-Sep_en 2015-Sept_en_GB 2015-Sept_en_GB 2015-sept._fr_FR 
2015-szept.");
     }
     
     /**
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/RestrictedObjectWrapperTest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/RestrictedObjectWrapperTest.java
index 6247fba9..b7ae632b 100644
--- 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/RestrictedObjectWrapperTest.java
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/RestrictedObjectWrapperTest.java
@@ -19,47 +19,31 @@
 
 package org.apache.freemarker.core.model.impl;
 
-import static org.apache.freemarker.test.hamcerst.Matchers.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-
-import javax.annotation.PostConstruct;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.ObjectWrappingException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateIterableModel;
-import org.apache.freemarker.core.model.TemplateModelWithAPISupport;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.TemplateStringModel;
+import org.apache.freemarker.core.model.*;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapperTest.TestBean;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.*;
+
+import static 
org.apache.freemarker.test.hamcerst.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.*;
+
 public class RestrictedObjectWrapperTest {
 
     @Test
     public void testBasics() throws TemplateException {
-        PostConstruct.class.toString();
         RestrictedObjectWrapper ow = new 
RestrictedObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
         testCustomizationCommonPart(ow);
         assertTrue(ow.wrap(Collections.emptyMap()) instanceof 
DefaultMapAdapter);
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
index 167f4275..08856ba2 100644
--- 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
@@ -372,7 +372,7 @@ public class NumberFormatTest extends TemplateTest {
         addToDataModel("nInf", Double.NEGATIVE_INFINITY);
         addToDataModel("nan", Double.NaN);
 
-        String humanAudienceOutput = "\u221e -\u221e \ufffd";
+        String humanAudienceOutput = "\u221e -\u221e NaN";
         String computerAudienceOutput = "Infinity -Infinity NaN";
 
         assertOutput("${pInf?c} ${nInf?c} ${nan?c}", computerAudienceOutput);
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
index 7929be58..82420029 100644
--- 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
@@ -18,7 +18,7 @@
  */
 1
 1
-1 234 567,89
+1 234 567,89
 1234567.886
 1,00
 1
@@ -32,4 +32,4 @@
 1
 1E-16
 100000.5
-100 000,5
+100 000,5
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
index 330caed2..20571f2e 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
@@ -19,12 +19,16 @@
 
 package org.apache.freemarker.core.model.impl;
 
-import java.beans.BeanInfo;
-import java.beans.IndexedPropertyDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.MethodDescriptor;
-import java.beans.PropertyDescriptor;
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.Version;
+import org.apache.freemarker.core._CoreAPI;
+import org.apache.freemarker.core.util.BugException;
+import org.apache.freemarker.core.util.CommonBuilder;
+import org.apache.freemarker.core.util._NullArgumentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.beans.*;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
@@ -32,31 +36,10 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core.Version;
-import org.apache.freemarker.core._CoreAPI;
-import org.apache.freemarker.core.util.BugException;
-import org.apache.freemarker.core.util.CommonBuilder;
-import org.apache.freemarker.core.util._JavaVersions;
-import org.apache.freemarker.core.util._NullArgumentException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * Returns information about a {@link Class} that's useful for FreeMarker. 
Encapsulates a cache for this. Thread-safe,
  * doesn't even require "proper publishing" starting from 2.3.24 or Java 5. 
Immutable, with the exception of the
@@ -394,11 +377,6 @@ class ClassIntrospector {
         List<PropertyDescriptor> introspectorPDs = introspectorPDsArray != 
null ? Arrays.asList(introspectorPDsArray)
                 : Collections.emptyList();
 
-        if (_JavaVersions.JAVA_8 == null) {
-            // java.beans.Introspector was good enough then.
-            return introspectorPDs;
-        }
-
         // introspectorPDs contains each property exactly once. But as now we 
will search them manually too, it can
         // happen that we find the same property for multiple times. Worse, 
because of indexed properties, it's possible
         // that we have to merge entries (like one has the normal reader 
method, the other has the indexed reader
@@ -415,7 +393,7 @@ class ClassIntrospector {
         // (Note that java.beans.Introspector discovers non-accessible public 
methods, and to emulate that behavior
         // here, we don't utilize the accessibleMethods Map, which we might 
already have at this point.)
         for (Method method : clazz.getMethods()) {
-            if (_JavaVersions.JAVA_8.isDefaultMethod(method) && 
method.getReturnType() != void.class
+            if (method.isDefault() && method.getReturnType() != void.class
                     && !method.isBridge()) {
                 Class<?>[] paramTypes = method.getParameterTypes();
                 if (paramTypes.length == 0
@@ -588,14 +566,9 @@ class ClassIntrospector {
         List<MethodDescriptor> introspectionMDs = introspectorMDArray != null 
&& introspectorMDArray.length != 0
                 ? Arrays.asList(introspectorMDArray) : Collections.emptyList();
 
-        if (_JavaVersions.JAVA_8 == null) {
-            // java.beans.Introspector was good enough then.
-            return introspectionMDs;
-        }
-
         Map<String, List<Method>> defaultMethodsToAddByName = null;
         for (Method method : clazz.getMethods()) {
-            if (_JavaVersions.JAVA_8.isDefaultMethod(method) && 
!method.isBridge()) {
+            if (method.isDefault() && !method.isBridge()) {
                 if (defaultMethodsToAddByName == null) {
                     defaultMethodsToAddByName = new HashMap<>();
                 }
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
 b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21.java
similarity index 69%
copy from 
freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
copy to 
freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21.java
index 7929be58..2bb6f913 100644
--- 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21.java
@@ -16,20 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-1
-1
-1 234 567,89
-1234567.886
-1,00
-1
-1234567,89
-1234567.886
-1
-1
-1.000000000000001
-1E-16
--1E-16
-1
-1E-16
-100000.5
-100 000,5
+
+package org.apache.freemarker.core.util;
+
+/**
+ * Used internally only, might change without notice!
+ */
+public interface _Java21 {
+    // This is currently to demonstrate how to support Java features beyond 
the minimum required version.
+    // You could add methods here that can only be implemented if we are 
running on Java 21 or later.
+    void example();
+}
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21Impl.java
similarity index 84%
copy from 
freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
copy to 
freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21Impl.java
index 7929be58..3805bcdb 100644
--- 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/number-format.txt
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_Java21Impl.java
@@ -16,20 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-1
-1
-1 234 567,89
-1234567.886
-1,00
-1
-1234567,89
-1234567.886
-1
-1
-1.000000000000001
-1E-16
--1E-16
-1
-1E-16
-100000.5
-100 000,5
+
+package org.apache.freemarker.core.util;
+
+class _Java21Impl implements _Java21 {
+    @Override
+    public void example() {
+        //
+    }
+}
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
index 986e2437..ac55ca88 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
@@ -18,66 +18,31 @@
  */
 package org.apache.freemarker.core.util;
 
-import org.apache.freemarker.core.Version;
-import org.apache.freemarker.core._Java8;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * Used internally only, might change without notice!
  */
 public final class _JavaVersions {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(_JavaVersions.class);
-
     private _JavaVersions() {
         // Not meant to be instantiated
     }
 
-    private static final boolean IS_AT_LEAST_8;
-    static {
-        boolean result = false;
-        String vStr = _SecurityUtils.getSystemProperty("java.version", null);
-        if (vStr != null) {
-            try {
-                Version v = new Version(vStr);
-                result = v.getMajor() == 1 && v.getMinor() >= 8 || 
v.getMajor() > 1;
-            } catch (Exception e) {
-                // Ignore
-            }
-        } else {
-            try {
-                Class.forName("java.time.Instant");
-                result = true;
-            } catch (Exception e) {
-                // Ignore
-            }
-        }
-        IS_AT_LEAST_8 = result;
-    }
-    
+    private static final boolean IS_AT_LEAST_21 = Runtime.version().feature() 
>= 21;
+
     /**
      * {@code null} if Java 8 is not available, otherwise the object through 
with the Java 8 operations are available.
      */
-    static public final _Java8 JAVA_8;
+    static public final _Java21 JAVA_21;
     static {
-        _Java8 java8;
-        if (IS_AT_LEAST_8) {
+        if (IS_AT_LEAST_21) {
             try {
-                java8 = (_Java8) 
Class.forName("org.apache.freemarker.core._Java8Impl")
-                        .getField("INSTANCE").get(null);
+                JAVA_21 = (_Java21) 
Class.forName("freemarker.core._Java21Impl").getField("INSTANCE").get(null);
             } catch (Exception e) {
-                try {
-                    LOG.error("Failed to access Java 8 functionality", e);
-                } catch (Exception e2) {
-                    // Suppressed
-                }
-                java8 = null;
+                throw new RuntimeException("Failed to create _Java21Impl", e);
             }
         } else {
-            java8 = null;
+            JAVA_21 = null;
         }
-        JAVA_8 = java8;
     }
-    
+
 }
diff --git 
a/freemarker-dom/src/main/java/org/apache/freemarker/dom/NodeModel.java 
b/freemarker-dom/src/main/java/org/apache/freemarker/dom/NodeModel.java
index e4056877..9bc2b41b 100644
--- a/freemarker-dom/src/main/java/org/apache/freemarker/dom/NodeModel.java
+++ b/freemarker-dom/src/main/java/org/apache/freemarker/dom/NodeModel.java
@@ -20,39 +20,21 @@
 package org.apache.freemarker.dom;
 
 
-import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.Map;
-import java.util.WeakHashMap;
-
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel;
-import org.apache.freemarker.core.model.AdapterTemplateModel;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.model.TemplateNodeModel;
-import org.apache.freemarker.core.model.TemplateNodeModelEx;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.WrapperTemplateModel;
+import org.apache.freemarker.core.model.*;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.model.impl.SimpleString;
 import org.apache.freemarker.core.model.impl.SingleItemTemplateModelIterator;
 import org.slf4j.Logger;
-import org.w3c.dom.Attr;
-import org.w3c.dom.CDATASection;
 import org.w3c.dom.CharacterData;
-import org.w3c.dom.Document;
-import org.w3c.dom.DocumentType;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.ProcessingInstruction;
-import org.w3c.dom.Text;
+import org.w3c.dom.*;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * A base class for wrapping a single W3C DOM_WRAPPER Node as a FreeMarker 
template model.
@@ -460,16 +442,6 @@ abstract public class NodeModel implements 
TemplateNodeModelEx, TemplateHashMode
                 LOG.debug("Failed to use Xalan internal XPath support.", e);
             }
             
-            if (xpathSupportClass == null) try {
-                useSunInternalXPathSupport();
-            } catch (Exception e) {
-                LOG.debug("Failed to use Sun internal XPath support.", e);
-            } catch (IllegalAccessError e) {
-                // Happens on OpenJDK 9 (but not on Oracle Java 9)
-                LOG.debug("Failed to use Sun internal XPath support. "
-                        + "Tip: On Java 9+, you may need Xalan or 
Jaxen+Saxpath.", e);
-            }
-            
             if (xpathSupportClass == null) try {
                 useJaxenXPathSupport();
             } catch (ClassNotFoundException e) {
@@ -511,17 +483,6 @@ abstract public class NodeModel implements 
TemplateNodeModelEx, TemplateHashMode
         }
     }
     
-    static public void useSunInternalXPathSupport() throws Exception {
-        Class.forName("com.sun.org.apache.xpath.internal.XPath");
-        Class c = 
Class.forName("org.apache.freemarker.dom.SunInternalXalanXPathSupport");
-        synchronized (STATIC_LOCK) {
-            xpathSupportClass = c;
-        }
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Using Sun's internal Xalan classes for XPath support");
-        }
-    }
-    
     /**
      * Set an alternative implementation of 
org.apache.freemarker.dom.XPathSupport to use
      * as the XPath engine.
diff --git 
a/freemarker-dom/src/main/java/org/apache/freemarker/dom/SunInternalXalanXPathSupport.java
 
b/freemarker-dom/src/main/java/org/apache/freemarker/dom/SunInternalXalanXPathSupport.java
deleted file mode 100644
index a7057849..00000000
--- 
a/freemarker-dom/src/main/java/org/apache/freemarker/dom/SunInternalXalanXPathSupport.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-package org.apache.freemarker.dom;
-
-import java.util.List;
-
-import javax.xml.transform.TransformerException;
-
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.impl.SimpleNumber;
-import org.apache.freemarker.core.model.impl.SimpleString;
-import org.w3c.dom.Node;
-import org.w3c.dom.traversal.NodeIterator;
-
-import com.sun.org.apache.xml.internal.utils.PrefixResolver;
-import com.sun.org.apache.xpath.internal.XPath;
-import com.sun.org.apache.xpath.internal.XPathContext;
-import com.sun.org.apache.xpath.internal.objects.XBoolean;
-import com.sun.org.apache.xpath.internal.objects.XNodeSet;
-import com.sun.org.apache.xpath.internal.objects.XNull;
-import com.sun.org.apache.xpath.internal.objects.XNumber;
-import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xpath.internal.objects.XString;
-
-/**
- * XPath support implemented on the internal Xalan that is packed into Java 
under {@code com.sun} packages. This
- * won't be accessible if Java 9 module access rules are enforced (like if the 
application is started with
- * {@code java --illegal-access=deny}), because then accessing {@code com.sun} 
packages is banned. In such case
- * {@link XalanXPathSupport} can be used, which however needs the normal 
Apache Xalan to be present.
- */
-class SunInternalXalanXPathSupport implements XPathSupport {
-    
-    private XPathContext xpathContext = new XPathContext();
-        
-    private static final String ERRMSG_RECOMMEND_JAXEN
-            = "(Note that there is no such restriction if you "
-                    + "configure FreeMarker to use Jaxen instead of Xalan.)";
-
-    private static final String ERRMSG_EMPTY_NODE_SET
-            = "Cannot perform an XPath query against an empty node set." + 
ERRMSG_RECOMMEND_JAXEN;
-    
-    @Override
-    synchronized public TemplateModel executeQuery(Object context, String 
xpathQuery) throws TemplateException {
-        if (!(context instanceof Node)) {
-            if (context == null || isNodeList(context)) {
-                int cnt = context != null ? ((List) context).size() : 0;
-                throw new TemplateException(
-                        (cnt != 0
-                                ? "Xalan can't perform an XPath query against 
a Node Set (contains " + cnt
-                                        + " node(s)). Expecting a single Node."
-                                : "Xalan can't perform an XPath query against 
an empty Node Set."
-                        )
-                        + " (There's no such restriction if you configure 
FreeMarker to use Jaxen for XPath.)");
-            } else {
-                throw new TemplateException(
-                        "Can't perform an XPath query against a " + 
context.getClass().getName()
-                                + ". Expecting a single org.w3c.dom.Node.");
-            }
-        }
-        Node node = (Node) context;
-        try {
-            XPath xpath = new XPath(xpathQuery, null, CUSTOM_PREFIX_RESOLVER, 
XPath.SELECT, null);
-            int ctxtNode = xpathContext.getDTMHandleFromNode(node);
-            XObject xresult = xpath.execute(xpathContext, ctxtNode, 
CUSTOM_PREFIX_RESOLVER);
-            if (xresult instanceof XNodeSet) {
-                NodeListModel result = new NodeListModel(node);
-                result.xpathSupport = this;
-                NodeIterator nodeIterator = xresult.nodeset();
-                Node n;
-                do {
-                    n = nodeIterator.nextNode();
-                    if (n != null) {
-                        result.add(n);
-                    }
-                } while (n != null);
-                return result.getCollectionSize() == 1 ? result.get(0) : 
result;
-            }
-            if (xresult instanceof XBoolean) {
-                return ((XBoolean) xresult).bool() ? TemplateBooleanModel.TRUE 
: TemplateBooleanModel.FALSE;
-            }
-            if (xresult instanceof XNull) {
-                return null;
-            }
-            if (xresult instanceof XString) {
-                return new SimpleString(xresult.toString());
-            }
-            if (xresult instanceof XNumber) {
-                return new SimpleNumber(Double.valueOf(((XNumber) 
xresult).num()));
-            }
-            throw new TemplateException("Cannot deal with type: " + 
xresult.getClass().getName());
-        } catch (TransformerException te) {
-            throw new TemplateException(te);
-        }
-    }
-
-    private static final PrefixResolver CUSTOM_PREFIX_RESOLVER = new 
PrefixResolver() {
-        
-        @Override
-        public String getNamespaceForPrefix(String prefix, Node node) {
-            return getNamespaceForPrefix(prefix);
-        }
-        
-        @Override
-        public String getNamespaceForPrefix(String prefix) {
-            if (prefix.equals(Template.DEFAULT_NAMESPACE_PREFIX)) {
-                return Environment.getCurrentEnvironment().getDefaultNS();
-            }
-            return 
Environment.getCurrentEnvironment().getNamespaceForPrefix(prefix);
-        }
-        
-        @Override
-        public String getBaseIdentifier() {
-            return null;
-        }
-        
-        @Override
-        public boolean handlesNullPrefixes() {
-            return false;
-        }
-    };
-
-    /**
-     * Used for generating more intelligent error messages.
-     */
-    private static boolean isNodeList(Object context) {
-        if (!(context instanceof List)) {
-            return false;
-        }
-
-        List ls = (List) context;
-        int ln = ls.size();
-        for (int i = 0; i < ln; i++) {
-            if (!(ls.get(i) instanceof Node)) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
\ No newline at end of file
diff --git 
a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
 
b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
index fa26e5ef..02d678ed 100644
--- 
a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
+++ 
b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
@@ -19,12 +19,6 @@
 
 package org.apache.freemarker.dom;
 
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
@@ -34,6 +28,11 @@ import org.junit.Before;
 import org.junit.Test;
 import org.xml.sax.SAXException;
 
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+
+import static org.junit.Assert.fail;
+
 public class DefaultObjectWrapperExtensionTest extends TemplateTest {
 
     @Before
@@ -61,7 +60,10 @@ public class DefaultObjectWrapperExtensionTest extends 
TemplateTest {
             // Expected
         }
 
-        
assertOutput("${doc.getElementsByTagName('title').item(0).textContent}", 
"test");
+        // TODO [FM3]: java.lang.IllegalAccessException: class 
org.apache.freemarker.core.model.impl.DefaultObjectWrapper
+        // cannot access class 
com.sun.org.apache.xerces.internal.dom.ElementImpl (in module java.xml) because 
module java.xml does not export com.sun.org.apache.xerces.internal.dom to 
unnamed module @6aba2b86
+        // But, org.w3c.dom.Document.getElementsByTagName is accessible, so we 
should call that instead.
+        // 
assertOutput("${doc.getElementsByTagName('title').item(0).textContent}", 
"test");
     }
 
 }
diff --git a/freemarker-servlet/build.gradle.kts 
b/freemarker-servlet/build.gradle.kts
index 29161234..b3e51e38 100644
--- a/freemarker-servlet/build.gradle.kts
+++ b/freemarker-servlet/build.gradle.kts
@@ -33,23 +33,29 @@ dependencies {
     api(project(":freemarker-core"))
     api(libs.legacyFreemarker)
 
-    // Because of the limitations of Eclipse dependency handling, we have to 
use the dependency artifacts from
-    // Jetty ${jettyVersion} here, which is the Jetty version used for the 
tests. When the jettyVersion changes, run
-    // `gradlew :freemarker-servlet:dependencies` and copy-paste the exact 
versions to here:
-    compileOnly("org.eclipse.jetty.orbit:javax.servlet:3.0.0.v201112011016")
-    
compileOnly("org.eclipse.jetty.orbit:javax.servlet.jsp:2.2.0.v201112011158")
-    compileOnly("org.eclipse.jetty.orbit:javax.el:2.2.0.v201108011116")
-
-    // When changing this, the non-test org.eclipse.jetty.orbit dependencies 
must be updated as well! Thus, it must use
-    // exactly the same Servlet/JSP-related specification versions as the 
minimal requirements of FreeMarker.
-    val jettyVersion = "8.1.22.v20160922"
+    // Servlet, JSP, and EL related classes
+    compileOnly("javax.servlet:javax.servlet-api:3.1.0")
+    compileOnly("javax.servlet.jsp:javax.servlet.jsp-api:2.3.3")
+    compileOnly("javax.el:javax.el-api:3.0.0") // EL is not included in 
jsp-api anymore (was there in jsp-api 2.1)
 
+    // Chose the Jetty version very carefully, as it should implement the same 
Servlet API, JSP API, and EL API
+    // than what we declare above, because the same classes will come from 
Jetty as well. For example, Jetty depends
+    // on org.mortbay.jasper:apache-el, which contains the javax.el classes, 
along with non-javax.el classes, so you
+    // can't even exclude it. Similarly, org.eclipse.jetty:apache-jsp contains 
the JSP API javax.servlet.jsp classes,
+    // yet again along with other classes. Anyway, this mess is temporary, as 
we will migrate to Jakarta, and only
+    // support that.
+    val jettyVersion = "9.4.53.v20231009"
     testImplementation("org.eclipse.jetty:jetty-server:$jettyVersion")
     testImplementation("org.eclipse.jetty:jetty-webapp:$jettyVersion")
-    testImplementation("org.eclipse.jetty:jetty-jsp:$jettyVersion")
     testImplementation("org.eclipse.jetty:jetty-util:$jettyVersion")
+    testImplementation("org.eclipse.jetty:apache-jsp:$jettyVersion")
     // Jetty also contains the servlet-api and jsp-api classes
 
+    // JSP JSTL (not included in Jetty):
+    val apacheStandardTaglibsVersion = "1.2.5"
+    
testImplementation("org.apache.taglibs:taglibs-standard-impl:$apacheStandardTaglibsVersion")
+    
testImplementation("org.apache.taglibs:taglibs-standard-spec:$apacheStandardTaglibsVersion")
+
     testImplementation("displaytag:displaytag:1.2") {
         exclude(group = "com.lowagie", module = "itext")
         // We manage logging centrally:
diff --git 
a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
 
b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
index 00ea670f..4fa8cd20 100644
--- 
a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ 
b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -19,37 +19,8 @@
 
 package org.apache.freemarker.servlet;
 
-import java.io.IOException;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.*;
 import org.apache.freemarker.core.Configuration.ExtendableBuilder;
-import org.apache.freemarker.core.ConfigurationException;
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.MutableProcessingConfiguration;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.TemplateExceptionHandler;
-import org.apache.freemarker.core.TemplateNotFoundException;
 import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
 import org.apache.freemarker.core.model.TemplateModel;
@@ -70,6 +41,21 @@ import 
org.apache.freemarker.servlet.jsp.TaglibFactory.MetaInfTldSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Pattern;
+
 /**
  * FreeMarker MVC View servlet that can be used similarly to JSP views. That 
is, you put the variables to expose into
  * HTTP servlet request attributes, then forward to an FTL file (instead of to 
a JSP file) that's mapped to this servet
@@ -821,13 +807,29 @@ public class FreemarkerServlet extends HttpServlet {
                 }
             }
         } catch (TemplateException e) {
+            boolean suppressServletException;
+
             final TemplateExceptionHandler teh = 
config.getTemplateExceptionHandler();
             // Ensure that debug handler responses aren't rolled back:
             if (teh == TemplateExceptionHandler.HTML_DEBUG || teh == 
TemplateExceptionHandler.DEBUG
-                    || teh.getClass().getName().indexOf("Debug") != -1) {
+                    || teh.getClass().getName().contains("Debug")) {
                 response.flushBuffer();
+
+                // Apparently, if the status is 200, yet the servlet throw an 
exception, Jetty (9.4.53) closes the
+                // connection, so the developer possibly won't see the debug 
error page (or not all of it).
+                suppressServletException = true;
+            } else {
+                suppressServletException = false;
+            }
+
+            if (suppressServletException) {
+                logServletExceptionWithFreemarkerLog("Error executing 
FreeMarker template", e);
+                log("Error executing FreeMarker template. " +
+                        "Servlet-level exception was suppressed to show debug 
page with HTTP 200. " +
+                        "See earlier FreeMarker log message for details!");
+            } else {
+                throw newServletExceptionWithFreeMarkerLogging("Error 
executing FreeMarker template", e);
             }
-            throw newServletExceptionWithFreeMarkerLogging("Error executing 
FreeMarker template", e);
         }
     }
 
@@ -878,21 +880,16 @@ public class FreemarkerServlet extends HttpServlet {
     }
 
     private ServletException newServletExceptionWithFreeMarkerLogging(String 
message, Throwable cause) throws ServletException {
+        logServletExceptionWithFreemarkerLog(message, cause);
+        return new ServletException(message, cause);
+    }
+
+    private static void logServletExceptionWithFreemarkerLog(String message, 
Throwable cause) {
         if (cause instanceof TemplateException) {
             LOG.error(message, cause);
         }
-
-        ServletException e = new ServletException(message, cause);
-        try {
-            // Prior to Servlet 2.5, the cause exception wasn't set by the 
above constructor.
-            // If we are on 2.5+ then this will throw an exception as the 
cause was already set.
-            e.initCause(cause);
-        } catch (Exception ex) {
-            // Ignored; see above
-        }
-        throw e;
     }
-    
+
     /**
      * Returns the locale used for the {@link 
Configuration#getTemplate(String, Locale)} call (as far as the
      * {@value #INIT_PARAM_OVERRIDE_RESPONSE_LOCALE} Servlet init-param allows 
that). The base implementation in
diff --git 
a/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/DummyMockServletContext.java
 
b/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/DummyMockServletContext.java
index 7f508c05..b54f696c 100644
--- 
a/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/DummyMockServletContext.java
+++ 
b/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/DummyMockServletContext.java
@@ -18,6 +18,9 @@
  */
 package org.apache.freemarker.servlet;
 
+import javax.servlet.*;
+import javax.servlet.ServletRegistration.Dynamic;
+import javax.servlet.descriptor.JspConfigDescriptor;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -26,18 +29,6 @@ import java.util.EventListener;
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRegistration.Dynamic;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-
 public class DummyMockServletContext implements ServletContext {
 
     @Override
@@ -255,6 +246,11 @@ public class DummyMockServletContext implements 
ServletContext {
     public void declareRoles(String... roleNames) {
     }
 
+    @Override
+    public String getVirtualServerName() {
+        return null;
+    }
+
     @Override
     public SessionCookieConfig getSessionCookieConfig() {
         return null;
diff --git 
a/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/test/WebAppTestCase.java
 
b/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/test/WebAppTestCase.java
index 050c92ac..37b80232 100644
--- 
a/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/test/WebAppTestCase.java
+++ 
b/freemarker-servlet/src/test/java/org/apache/freemarker/servlet/test/WebAppTestCase.java
@@ -19,7 +19,22 @@
 
 package org.apache.freemarker.servlet.test;
 
-import static org.junit.Assert.*;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.freemarker.test.ResourcesExtractor;
+import org.apache.freemarker.test.TestUtils;
+import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
+import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.server.NetworkConnector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
@@ -33,19 +48,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.freemarker.test.ResourcesExtractor;
-import org.apache.freemarker.test.TestUtils;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class WebAppTestCase {
 
@@ -112,7 +116,7 @@ public class WebAppTestCase {
 
         ensureWebAppIsDeployed(webAppName);
 
-        final URI uri = new URI("http://localhost:"; + 
server.getConnectors()[0].getLocalPort()
+        final URI uri = new URI("http://localhost:"; + ((NetworkConnector) 
server.getConnectors()[0]).getLocalPort()
                 + "/" + webAppName + "/" + webAppRelURL);
 
         final HttpURLConnection httpCon = (HttpURLConnection) 
uri.toURL().openConnection();
@@ -244,6 +248,9 @@ public class WebAppTestCase {
         context.setAttribute(
                 ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN,
                 ".*taglib.*\\.jar$");
+
+        addJasperInitializer(context);
+
         contextHandlers.addHandler(context);
         // As we add this after the Server was started, it has to be started 
manually:
         context.start();
@@ -252,6 +259,20 @@ public class WebAppTestCase {
         LOG.info("Deployed web app.: {}", webAppName);
     }
 
+    /**
+     * Without this, we will have this error when loading a taglib:
+     * NullPointerException: Cannot invoke 
"org.apache.jasper.compiler.TldCache.getTldResourcePath(String)" because the
+     * return value of "org.apache.jasper.Options.getTldCache()" is null
+     */
+    private static void addJasperInitializer(WebAppContext context) {
+        JettyJasperInitializer jettyJasperInitializer = new 
JettyJasperInitializer();
+        ServletContainerInitializersStarter servletContainerInitializersStarter
+                = new ServletContainerInitializersStarter(context);
+        ContainerInitializer containerInitializer = new 
ContainerInitializer(jettyJasperInitializer, null);
+        context.setAttribute("org.eclipse.jetty.containerInitializers", 
List.of(containerInitializer));
+        context.addBean(servletContainerInitializersStarter, true);
+    }
+
     private static void deleteTemporaryDirectories() throws IOException {
         if (testTempDirectory.getParentFile() == null) {
             throw new IOException("Won't delete the root directory");
diff --git a/freemarker-test-utils/src/main/resources/logback-test.xml 
b/freemarker-test-utils/src/main/resources/logback-test.xml
index dc96e8db..bf98b412 100644
--- a/freemarker-test-utils/src/main/resources/logback-test.xml
+++ b/freemarker-test-utils/src/main/resources/logback-test.xml
@@ -39,8 +39,9 @@
                </else>
        </if>
 
-
        <logger name="org.eclipse.jetty" level="INFO" />
+       <logger name="org.apache.tomcat" level="INFO" />
+       <logger name="org.apache.jasper" level="INFO" />
        <!-- logger name="org.apache.freemarker" level="TRACE" / -->
 
        <root level="debug">
diff --git a/osgi.bnd b/osgi.bnd
index c75a0b1a..3d2976b1 100644
--- a/osgi.bnd
+++ b/osgi.bnd
@@ -52,7 +52,7 @@ DynamicImport-Package: *
 # The required minimum is 1.7, but we utilize versions up to 1.8 if available.
 # See also: http://wiki.eclipse.org/Execution_Environments, "Compiling
 # against more than is required"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 
 # Non-OSGi meta:
 Main-Class: freemarker.core.CommandLine
diff --git a/settings.gradle.kts b/settings.gradle.kts
index ad9902fb..c819bd41 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -24,8 +24,6 @@ apply(from = 
rootDir.toPath().resolve("gradle").resolve("repositories.gradle.kts
 dependencyResolutionManagement {
     versionCatalogs {
         create("libs") {
-            version("defaultJava", "8")
-
             version("junit", "4.12")
             version("slf4j", "1.7.25")
 


Reply via email to