I think this needs to be reverted / modified.
tomcatAttributes is (still) documented as attributes that should not be
replicated.
How about skipping jakarta.servlet.* and org.apache.* attributes?
Mark
On 01/10/2026 07:41, [email protected] wrote:
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 98d6dbcd618bda61eb77e131bdc57a5595f958e0
Author: opencode <[email protected]>
AuthorDate: Wed Sep 30 22:46:43 2026 +0200
Move attributes set during web application startup into the replicated
attribute map when it is installed in ReplicatedContext so they are replicated
to the other nodes
---
.../catalina/ha/context/ReplicatedContext.java | 21 +++++++++++++++++++--
webapps/docs/changelog.xml | 7 +++++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/ha/context/ReplicatedContext.java
b/java/org/apache/catalina/ha/context/ReplicatedContext.java
index a0e02ea31e..d4c3012b33 100644
--- a/java/org/apache/catalina/ha/context/ReplicatedContext.java
+++ b/java/org/apache/catalina/ha/context/ReplicatedContext.java
@@ -169,6 +169,12 @@ public class ReplicatedContext extends StandardContext
implements MapOwner {
* Application context implementation for replicated contexts.
*/
protected static class ReplApplContext extends ApplicationContext {
+ /**
+ * Attribute name used by Jasper for its application context. It holds
+ * node specific state and must therefore never be replicated.
+ */
+ private static final String JSP_APP_CONTEXT_NAME =
"org.apache.jasper.runtime.JspApplicationContextImpl";
+
/**
* Map for Tomcat-specific attributes that should not be replicated.
*/
@@ -213,6 +219,18 @@ public class ReplicatedContext extends StandardContext
implements MapOwner {
*/
public void setAttributeMap(Map<String,Object> map) {
this.attributes = map;
+ // Attributes set while the context was starting were stored in the
+ // local map. Move them to the new map so that they are handled the
+ // same way as attributes set later on, in particular replicated to
+ // the other nodes. Values that cannot be serialized are stored
+ // locally by the replicated map.
+ for (Map.Entry<String,Object> entry : tomcatAttributes.entrySet())
{
+ if (JSP_APP_CONTEXT_NAME.equals(entry.getKey())) {
+ continue;
+ }
+ map.put(entry.getKey(), entry.getValue());
+ tomcatAttributes.remove(entry.getKey());
+ }
}
@Override
@@ -230,8 +248,7 @@ public class ReplicatedContext extends StandardContext
implements MapOwner {
removeAttribute(name);
return;
}
- if ((!getParent().getState().isAvailable()) ||
-
"org.apache.jasper.runtime.JspApplicationContextImpl".equals(name)) {
+ if ((!getParent().getState().isAvailable()) ||
JSP_APP_CONTEXT_NAME.equals(name)) {
tomcatAttributes.put(name, value);
} else {
super.setAttribute(name, value);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b937aea636..d59d471101 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -401,6 +401,13 @@
<subsection name="Cluster">
<changelog>
<!-- Entries for backport and removal before 12.0.0-M1 below this line
-->
+ <fix>
+ Move context attributes that were set while the web application was
+ still starting into the replicated attribute map when it is installed
+ in <code>ReplicatedContext</code>, so that they are replicated to the
+ other nodes like attributes set later on rather than remaining local to
+ the node that started the application. (remm)
+ </fix>
<fix>
Replicate SSO session key set changes made by
<code>removeSession()</code>
and <code>sessionChangedId()</code> in
<code>ClusterSingleSignOn</code> so
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]