This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 3a46af4ec979cf769c1c6c1a1ba5df5516218949
Author: opencode <[email protected]>
AuthorDate: Wed Oct 7 12:27:12 2026 +0200

    Keep naming resource entries consistent when updated through JMX
    
    ContextEnvironmentMBean passed a changed name attribute to the resource
    before removing the entry under its new name, so a rename through JMX
    left the old entry registered, the old JNDI binding in place and a
    second MBean for the same object under the new name. Refuse the name
    change, as the sibling resource MBeans do.
    
    Both the environment and the resource MBean updated an entry by
    removing it and adding it back. When the add then rejected the new
    state, for example a resource type that is incompatible with the
    injection targets of the entry, the entry had already been dropped from
    the naming resources, its JNDI binding removed and its MBean
    unregistered, losing the entry entirely. Restore the previous values
    and add the entry back before reporting the failure to the caller.
---
 .../catalina/mbeans/ContextEnvironmentMBean.java   | 41 ++++++++++++++++++++--
 .../catalina/mbeans/ContextResourceMBean.java      | 14 ++++++--
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java 
b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
index 973029c9cd..02387a43dc 100644
--- a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
@@ -20,9 +20,13 @@ import javax.management.Attribute;
 import javax.management.AttributeNotFoundException;
 import javax.management.MBeanException;
 import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
 
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
 import org.apache.tomcat.util.descriptor.web.NamingResources;
+import org.apache.tomcat.util.res.StringManager;
 
 /**
  * A <strong>ModelMBean</strong> implementation for the
@@ -36,20 +40,51 @@ public class ContextEnvironmentMBean extends 
BaseCatalinaMBean<ContextEnvironmen
     public ContextEnvironmentMBean() {
     }
 
+    private static final Log log = 
LogFactory.getLog(ContextEnvironmentMBean.class);
+    private static final StringManager sm = 
StringManager.getManager(ContextEnvironmentMBean.class);
+
     @Override
     public void setAttribute(Attribute attribute)
             throws AttributeNotFoundException, MBeanException, 
ReflectionException {
 
-        super.setAttribute(attribute);
+        if (attribute == null) {
+            throw new RuntimeOperationsException(new 
IllegalArgumentException(sm.getString("mBean.nullAttribute")),
+                    sm.getString("mBean.nullAttribute"));
+        }
 
         ContextEnvironment ce = doGetManagedResource();
 
+        if ("name".equals(attribute.getName())) {
+            // Updating the name actually needs removing and adding back the
+            // component under the new name. Ignore the change, as the other
+            // naming resource MBeans do.
+            log.info(sm.getString("mBean.nameChange"));
+            return;
+        }
+
+        String oldType = ce.getType();
+        String oldValue = ce.getValue();
+        String oldLookup = ce.getLookupName();
+
+        super.setAttribute(attribute);
+
         // cannot use side effects. It's removed and added back each time
         // there is a modification in a resource.
         NamingResources nr = ce.getNamingResources();
         if (nr != null) {
-            nr.removeEnvironment(ce.getName());
-            nr.addEnvironment(ce);
+            try {
+                nr.removeEnvironment(ce.getName());
+                nr.addEnvironment(ce);
+            } catch (IllegalArgumentException iae) {
+                // The change is not acceptable. Restore the previous state
+                // before passing the failure to the caller, so the entry is
+                // not lost.
+                ce.setType(oldType);
+                ce.setValue(oldValue);
+                ce.setLookupName(oldLookup);
+                nr.addEnvironment(ce);
+                throw iae;
+            }
         }
     }
 }
diff --git a/java/org/apache/catalina/mbeans/ContextResourceMBean.java 
b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
index 6990edc062..beeb665571 100644
--- a/java/org/apache/catalina/mbeans/ContextResourceMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
@@ -94,6 +94,7 @@ public class ContextResourceMBean extends 
BaseCatalinaMBean<ContextResource> {
 
         ContextResource cr = doGetManagedResource();
 
+        String oldType = cr.getType();
         if ("auth".equals(name)) {
             cr.setAuth((String) value);
         } else if ("description".equals(name)) {
@@ -113,8 +114,17 @@ public class ContextResourceMBean extends 
BaseCatalinaMBean<ContextResource> {
         // there is a modification in a resource.
         NamingResources nr = cr.getNamingResources();
         if (nr != null) {
-            nr.removeResource(cr.getName());
-            nr.addResource(cr);
+            try {
+                nr.removeResource(cr.getName());
+                nr.addResource(cr);
+            } catch (IllegalArgumentException iae) {
+                // The change is not acceptable. Restore the previous type
+                // before passing the failure to the caller, so the entry is
+                // not lost.
+                cr.setType(oldType);
+                nr.addResource(cr);
+                throw iae;
+            }
         }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to