clusterValveClass;
-- static {
-- Class> clazz = null;
-- try {
-- clazz = Class.forName("org.apache.catalina.ha.ClusterValve");
-- } catch (ClassNotFoundException e) {
-- // Expected when clustering JARs are not present
-- }
-- clusterValveClass = clazz;
-- }
--
- /**
- * Store the specified Engine properties.
- *
-@@ -74,7 +64,7 @@
- if (valves != null && valves.length > 0) {
- List engineValves = new ArrayList<>();
- for (Valve valve : valves) {
-- if (clusterValveClass == null || !clusterValveClass.isInstance(valve)) {
-+ if (!(valve instanceof ClusterValve)) {
- engineValves.add(valve);
- }
- }
-diff --git a/java/org/apache/catalina/storeconfig/StandardHostSF.java b/java/org/apache/catalina/storeconfig/StandardHostSF.java
-index 60d473982b..1e8f2d3a58 100644
---- a/java/org/apache/catalina/storeconfig/StandardHostSF.java
-+++ b/java/org/apache/catalina/storeconfig/StandardHostSF.java
-@@ -26,23 +26,13 @@
- import org.apache.catalina.Realm;
- import org.apache.catalina.Valve;
- import org.apache.catalina.core.StandardHost;
-+import org.apache.catalina.ha.ClusterValve;
-
- /**
- * Store server.xml Element Host
- */
- public class StandardHostSF extends StoreFactoryBase {
-
-- private static final Class> clusterValveClass;
-- static {
-- Class> clazz = null;
-- try {
-- clazz = Class.forName("org.apache.catalina.ha.ClusterValve");
-- } catch (ClassNotFoundException e) {
-- // Expected when clustering JARs are not present
-- }
-- clusterValveClass = clazz;
-- }
--
- /**
- * Store the specified Host properties and children (Listener,Alias,Realm,Valve,Cluster, Context)
- *
-@@ -78,7 +68,7 @@
- if (valves != null && valves.length > 0) {
- List hostValves = new ArrayList<>();
- for (Valve valve : valves) {
-- if (clusterValveClass == null || !clusterValveClass.isInstance(valve)) {
-+ if (!(valve instanceof ClusterValve)) {
- hostValves.add(valve);
- }
- }
-diff --git a/java/org/apache/catalina/storeconfig/StoreRegistry.java b/java/org/apache/catalina/storeconfig/StoreRegistry.java
-index c17dd3817e..ee803abe36 100644
---- a/java/org/apache/catalina/storeconfig/StoreRegistry.java
-+++ b/java/org/apache/catalina/storeconfig/StoreRegistry.java
-@@ -16,9 +16,7 @@
- */
- package org.apache.catalina.storeconfig;
-
--import java.util.ArrayList;
- import java.util.HashMap;
--import java.util.List;
- import java.util.Map;
-
- import javax.naming.directory.DirContext;
-@@ -30,6 +28,17 @@
- import org.apache.catalina.Valve;
- import org.apache.catalina.WebResourceRoot;
- import org.apache.catalina.WebResourceSet;
-+import org.apache.catalina.ha.CatalinaCluster;
-+import org.apache.catalina.ha.ClusterDeployer;
-+import org.apache.catalina.ha.ClusterListener;
-+import org.apache.catalina.tribes.Channel;
-+import org.apache.catalina.tribes.ChannelInterceptor;
-+import org.apache.catalina.tribes.ChannelReceiver;
-+import org.apache.catalina.tribes.ChannelSender;
-+import org.apache.catalina.tribes.Member;
-+import org.apache.catalina.tribes.MembershipService;
-+import org.apache.catalina.tribes.MessageListener;
-+import org.apache.catalina.tribes.transport.DataSender;
- import org.apache.coyote.UpgradeProtocol;
- import org.apache.juli.logging.Log;
- import org.apache.juli.logging.LogFactory;
-@@ -52,74 +61,11 @@
- private String version;
-
- // Access Information
-- // Lazily initialized to gracefully handle optional features like clustering
-- private static volatile Class>[] interfaces = null;
--
-- /**
-- * Initialize the interfaces array with all available classes.
-- * Uses dynamic loading for optional classes (e.g., clustering) to avoid
-- * ClassNotFoundException when those JARs are not present. This approach
-- * is consistent with how Catalina.addClusterRuleSet() handles clustering.
-- */
-- private static Class>[] getInterfaces() {
-- if (interfaces == null) {
-- synchronized (StoreRegistry.class) {
-- if (interfaces == null) {
-- // Required interfaces - always present
-- List> list = new ArrayList<>();
-- list.add(Realm.class);
-- list.add(Manager.class);
-- list.add(DirContext.class);
-- list.add(LifecycleListener.class);
-- list.add(Valve.class);
-- list.add(WebResourceRoot.class);
-- list.add(WebResourceSet.class);
-- list.add(CredentialHandler.class);
-- list.add(UpgradeProtocol.class);
-- list.add(CookieProcessor.class);
--
-- // Optional clustering interfaces - load dynamically to support
-- // deployments where clustering JARs may not be present
-- tryAddClass(list, "org.apache.catalina.ha.CatalinaCluster");
-- tryAddClass(list, "org.apache.catalina.tribes.ChannelSender");
-- tryAddClass(list, "org.apache.catalina.tribes.ChannelReceiver");
-- tryAddClass(list, "org.apache.catalina.tribes.Channel");
-- tryAddClass(list, "org.apache.catalina.tribes.MembershipService");
-- tryAddClass(list, "org.apache.catalina.ha.ClusterDeployer");
-- tryAddClass(list, "org.apache.catalina.ha.ClusterListener");
-- tryAddClass(list, "org.apache.catalina.tribes.MessageListener");
-- tryAddClass(list, "org.apache.catalina.tribes.transport.DataSender");
-- tryAddClass(list, "org.apache.catalina.tribes.ChannelInterceptor");
-- tryAddClass(list, "org.apache.catalina.tribes.Member");
--
-- interfaces = list.toArray(new Class>[0]);
--
-- if (log.isDebugEnabled()) {
-- log.debug(sm.getString("registry.interfacesLoaded", Integer.valueOf(interfaces.length)));
-- }
-- }
-- }
-- }
-- return interfaces;
-- }
--
-- /**
-- * Try to load a class by name and add it to the list if successful.
-- * Logs at TRACE level if the class is not available.
-- */
-- private static void tryAddClass(List> list, String className) {
-- try {
-- Class> clazz = Class.forName(className, false, StoreRegistry.class.getClassLoader());
-- list.add(clazz);
-- if (log.isTraceEnabled()) {
-- log.trace(sm.getString("registry.optionalClassLoaded", className));
-- }
-- } catch (ClassNotFoundException | NoClassDefFoundError e) {
-- if (log.isTraceEnabled()) {
-- log.trace(sm.getString("registry.optionalClassNotFound", className));
-- }
-- }
-- }
-+ private static final Class>[] interfaces = { CatalinaCluster.class, ChannelSender.class, ChannelReceiver.class,
-+ Channel.class, MembershipService.class, ClusterDeployer.class, Realm.class, Manager.class, DirContext.class,
-+ LifecycleListener.class, Valve.class, ClusterListener.class, MessageListener.class, DataSender.class,
-+ ChannelInterceptor.class, Member.class, WebResourceRoot.class, WebResourceSet.class,
-+ CredentialHandler.class, UpgradeProtocol.class, CookieProcessor.class };
-
- /**
- * @return the name
-@@ -170,10 +116,9 @@
- }
- if (aClass != null) {
- desc = descriptors.get(aClass.getName());
-- Class>[] availableInterfaces = getInterfaces();
-- for (int i = 0; desc == null && i < availableInterfaces.length; i++) {
-- if (availableInterfaces[i].isAssignableFrom(aClass)) {
-- desc = descriptors.get(availableInterfaces[i].getName());
-+ for (int i = 0; desc == null && i < interfaces.length; i++) {
-+ if (interfaces[i].isAssignableFrom(aClass)) {
-+ desc = descriptors.get(interfaces[i].getName());
- }
- }
- }
-diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
-index 012b607f18..17f639d669 100644
---- a/webapps/docs/changelog.xml
-+++ b/webapps/docs/changelog.xml
-@@ -2830,6 +2830,13 @@
- The rewrite valve should not do a rewrite if the output is identical
- to the input. (remm)
-
-+
-+ Update StoreRegistry to dynamically load optional clustering
-+ classes rather than statically referencing them. This matches the pattern
-+ used in Catalina.addClusterRuleSet() and prevents
-+ NoClassDefFoundError when StoreConfigLifecycleListener
-+ is configured but clustering classes are not available. (csutherl)
-+
-
- Add a new valveSkip (or VS) rule flag to the
- rewrite valve to allow skipping over the next valve in the Catalina
-
diff --git a/tomcat.spec b/tomcat.spec
index 2b14df9..41177bc 100644
--- a/tomcat.spec
+++ b/tomcat.spec
@@ -54,7 +54,7 @@
Name: tomcat
Epoch: 1
Version: %{major_version}.%{minor_version}.%{micro_version}
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: Apache Servlet/JSP Engine, RI for Servlet %{servletspec}/JSP %{jspspec} API
License: Apache-2.0
@@ -81,7 +81,6 @@ Patch5: %{name}-%{major_version}.%{minor_version}-JDTCompiler.patch
Patch6: rhbz-1857043.patch
# Patch 7 can be dropped when ECJ is updated to a newer version
Patch7: build-with-java-25.patch
-patch8: rhel-168577.patch
BuildArch: noarch
ExclusiveArch: %{java_arches} noarch
@@ -209,7 +208,6 @@ find . -type f \( -name "*.bat" -o -name "*.class" -o -name Thumbs.db -o -name "
%patch 5 -p0
%patch 6 -p0
%patch 7 -p0
-%patch 8 -p1
# Remove webservices naming resources as it's generally unused
%{__rm} -rf java/org/apache/naming/factory/webservices
@@ -557,6 +555,9 @@ exit 0
%{appdir}/ROOT
%changelog
+* Mon Jul 6 2026 Pietro Meloni - 1:10.1.49-3
+- Related: RHEL-168577 Remove unnecessary patch
+
* Thu Jun 4 2026 Pietro Meloni - 1:10.1.49-2
- Resolves: RHEL-168577 Remove tomcat clustering JAR from RPM builds
Resolves: CVE-2026-29146