You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/10/01 06:41:31 UTC
(tomcat) 08/25: Fire ServletContextAttributeListener events for attributes stored in the local map of a ReplicatedContext by extracting the event firing logic of ApplicationContext into overridable hooks
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 be1f1d151d7221afe5ea8b2cf78d626b70f8a410
Author: opencode <re...@apache.org>
AuthorDate: Wed Sep 30 22:51:14 2026 +0200
Fire ServletContextAttributeListener events for attributes stored in the local map of a ReplicatedContext by extracting the event firing logic of ApplicationContext into overridable hooks
---
.../apache/catalina/core/ApplicationContext.java | 31 +++++++++++++++++-----
.../catalina/ha/context/ReplicatedContext.java | 13 +++++++--
2 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/java/org/apache/catalina/core/ApplicationContext.java b/java/org/apache/catalina/core/ApplicationContext.java
index d499bbe0ab..48a19e0bd6 100644
--- a/java/org/apache/catalina/core/ApplicationContext.java
+++ b/java/org/apache/catalina/core/ApplicationContext.java
@@ -561,6 +561,17 @@ public class ApplicationContext implements ServletContext {
return;
}
+ fireContextAttributeRemoved(name, value);
+ }
+
+
+ /**
+ * Notify the application's <code>ServletContextAttributeListener</code>s of an attribute removal.
+ *
+ * @param name The name of the attribute
+ * @param value The value the attribute had before it was removed
+ */
+ protected void fireContextAttributeRemoved(String name, Object value) {
// Notify interested application event listeners
Object[] listeners = context.getApplicationEventListeners();
if (listeners == null || listeners.length == 0) {
@@ -606,17 +617,25 @@ public class ApplicationContext implements ServletContext {
Object oldValue = attributes.put(name, value);
boolean replaced = oldValue != null;
+ fireContextAttributeAddedOrReplaced(replaced, name, replaced ? oldValue : value);
+ }
+
+
+ /**
+ * Notify the application's <code>ServletContextAttributeListener</code>s of an attribute addition or replacement.
+ *
+ * @param replaced Whether the attribute was replaced rather than added
+ * @param name The name of the attribute
+ * @param value The value for the event: the previous value when the attribute was replaced, otherwise the new
+ * value
+ */
+ protected void fireContextAttributeAddedOrReplaced(boolean replaced, String name, Object value) {
// Notify interested application event listeners
Object[] listeners = context.getApplicationEventListeners();
if (listeners == null || listeners.length == 0) {
return;
}
- ServletContextAttributeEvent event;
- if (replaced) {
- event = new ServletContextAttributeEvent(context.getServletContext(), name, oldValue);
- } else {
- event = new ServletContextAttributeEvent(context.getServletContext(), name, value);
- }
+ ServletContextAttributeEvent event = new ServletContextAttributeEvent(context.getServletContext(), name, value);
for (Object obj : listeners) {
if (!(obj instanceof ServletContextAttributeListener listener)) {
diff --git a/java/org/apache/catalina/ha/context/ReplicatedContext.java b/java/org/apache/catalina/ha/context/ReplicatedContext.java
index d4c3012b33..4dda906f1a 100644
--- a/java/org/apache/catalina/ha/context/ReplicatedContext.java
+++ b/java/org/apache/catalina/ha/context/ReplicatedContext.java
@@ -235,8 +235,14 @@ public class ReplicatedContext extends StandardContext implements MapOwner {
@Override
public void removeAttribute(String name) {
- tomcatAttributes.remove(name);
+ Object localValue = tomcatAttributes.remove(name);
+ boolean inAttributeMap = attributes.containsKey(name);
super.removeAttribute(name);
+ if (localValue != null && !inAttributeMap) {
+ // The attribute was only stored locally, so the removal event
+ // was not fired by the attribute map
+ fireContextAttributeRemoved(name, localValue);
+ }
}
@Override
@@ -249,7 +255,10 @@ public class ReplicatedContext extends StandardContext implements MapOwner {
return;
}
if ((!getParent().getState().isAvailable()) || JSP_APP_CONTEXT_NAME.equals(name)) {
- tomcatAttributes.put(name, value);
+ Object oldValue = tomcatAttributes.put(name, value);
+ // The attribute is stored locally, so the event has to be fired
+ // here rather than by the attribute map
+ fireContextAttributeAddedOrReplaced(oldValue != null, name, oldValue != null ? oldValue : value);
} else {
super.setAttribute(name, value);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org