Visit NES for Apache Struts Home Page

Apache Struts 1.3.x Forward Compatibility Container Support

Verified application server and JDK combinations for NES for Apache Struts 1.3.x Forward Compatibility

Overview

NES for Apache Struts 1.3.x Forward Compatibility targets Jakarta EE 9 (Servlet 5.0) and Java 11. It also runs on newer servlet containers and newer JDKs. This page records the combinations that have been verified by running the full Struts example application suite against each one, and the configuration each container family requires.

Verified combinations

Each cell was exercised by deploying the eight Struts example applications and requesting a page from each, plus a multipart/form-data upload.

Application serverServletJakarta EEJava 11Java 17Java 21
Apache Tomcat 10.16.010YesYesYes
Apache Tomcat 11.06.111YesYes
Eclipse Jetty 126.010YesYes
WildFly 306.010YesYesYes
WildFly 406.111YesYes
GlassFish 86.111Yes

A dash means the application server itself does not support that JDK, not that Struts fails there:

  • Tomcat 11, Jetty 12 and WildFly 40 require Java 17 or later.
  • GlassFish 8 requires Java 21.

The core framework — struts-core, struts-taglib, struts-tiles and struts-el — works on every combination marked Yes. The struts-faces module is subject to the limitation described below.

Jakarta EE application servers

Full Jakarta EE servers such as WildFly and GlassFish supply their own Jakarta Faces and CDI implementations, which changes what your application has to provide.

Add a CDI bean archive marker

On a Jakarta EE server, Jakarta Faces 4 initializes for every deployed web module and refuses to start unless the module is a CDI bean archive. Without this, deployment fails with IllegalStateException: CDI is not available, even for an application that uses no Faces and no CDI at all.

Add an empty bean archive marker to each web application:

src/main/webapp/WEB-INF/beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                           https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
       version="3.0"
       bean-discovery-mode="annotated">
</beans>

This is required on GlassFish 8 for all web applications. On WildFly it is required only for applications that use Jakarta Faces.

Do not bundle a CDI implementation

If your web application bundles weld-servlet-shaded so that CDI is available on a plain servlet container, remove it before deploying to a Jakarta EE server. Its ServletContainerInitializer collides with the CDI implementation the server already provides, and deployment fails with:

Error invoking ServletContainerInitializer org.jboss.weld.environment.servlet.EnhancedListener

Package every tag library class you reference

GlassFish instantiates every tag class in every TLD on the classpath at deployment time, where Tomcat and Jetty load a tag class only when a page actually uses it. A tag library whose implementation classes are missing therefore deploys fine on Tomcat and fails to start on GlassFish.

The common case is struts-el, which ships struts-tiles-el.tld but declares struts-tiles as an optional dependency. If you use struts-el, add struts-tiles explicitly:

Maven (pom.xml)
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts-tiles</artifactId>
  <version>1.3.10-struts-1.4.5</version>
</dependency>

Otherwise deployment fails with NoClassDefFoundError: org/apache/struts/tiles/taglib/InsertTag.

Jakarta Faces support

The struts-faces tag library is built on the Jakarta Faces JSP tag API — UIComponentELTag and UIComponentClassicTagBase. That API was deprecated in Faces 3.0 and removed in Faces 4.0, which supports Facelets views only. As a result:

  • Supported: servlet containers where you supply Jakarta Faces yourself and can pin a 3.x implementation, such as Tomcat 10.1 and Jetty 12.
  • Not supported: Jakarta EE 10 and 11 application servers, which ship Faces 4 and use it in preference to any implementation bundled in your application. On WildFly 30 and later and on GlassFish 8, Faces views resolve as Facelets and requests fail with FacesException: /<view>.xhtml Not Found in ExternalContext as a Resource.
  • Not supported: Apache Tomcat 11. Jakarta Pages 4.0 does not run the Faces 3.x JSP view path correctly; pages render an empty response body.

Applications that use struts-faces should stay on a Jakarta EE 9 or 10 servlet container with Faces 3.x. Migrating the views from JSP to Facelets is required before moving to a Faces 4 environment.

Request character encoding

Apache Tomcat sets a default request character encoding in its conf/web.xml:

<request-character-encoding>UTF-8</request-character-encoding>

Most other containers, including Jetty and WildFly's Undertow, leave the request encoding unset when the client does not send one. Code that assumes ServletRequest.getCharacterEncoding() returns a value will behave differently on those containers.

Scripting support

struts-scripting uses Apache BSF to run script actions. If you use it with Groovy, the Groovy version matters on newer JDKs.

Groovy 1.x calls setAccessible on JDK-internal members. JEP 396 made that a hard failure in Java 16, so on Java 17 and later the engine fails to load and the request fails with:

org.apache.bsf.BSFException: unable to load language: groovy

Use Groovy 3 with its BSF engine, which needs no --add-opens flags on Java 11, 17 or 21:

Maven (pom.xml)
<dependency>
  <groupId>org.codehaus.groovy</groupId>
  <artifactId>groovy</artifactId>
  <version>3.0.25</version>
</dependency>
<dependency>
  <groupId>org.codehaus.groovy</groupId>
  <artifactId>groovy-bsf</artifactId>
  <version>3.0.25</version>
</dependency>

Groovy 3 is the newest line that ships a BSF engine; groovy-bsf was discontinued after Groovy 4.0.0-alpha-2.