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]
