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

cziegeler pushed a commit to branch SLING-12372
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git


The following commit(s) were added to refs/heads/SLING-12372 by this push:
     new 571b816  SLING-12372 : ModelAdapterFactory is not cleaning up the 
requests correctly
571b816 is described below

commit 571b816dc513cf937b86b3660a87b40428240ca9
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Tue Jul 9 07:54:30 2024 +0200

    SLING-12372 : ModelAdapterFactory is not cleaning up the requests correctly
---
 .gitignore                                         |   1 +
 .../sling/models/impl/ModelAdapterFactory.java     | 132 ++++++---------------
 .../sling/models/impl/AdapterFactoryTest.java      |   2 -
 3 files changed, 35 insertions(+), 100 deletions(-)

diff --git a/.gitignore b/.gitignore
index 12746f7..0a3f3d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 /target
+.vscode
 .idea
 .classpath
 .metadata
diff --git 
a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java 
b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
index 8a4c821..47e4a47 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -22,7 +22,6 @@ import javax.annotation.PostConstruct;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletRequestEvent;
 import javax.servlet.ServletRequestListener;
-import javax.servlet.ServletRequestWrapper;
 
 import java.lang.ref.PhantomReference;
 import java.lang.ref.ReferenceQueue;
@@ -38,7 +37,6 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
@@ -54,8 +52,6 @@ import org.apache.sling.api.adapter.Adaptable;
 import org.apache.sling.api.adapter.AdapterFactory;
 import org.apache.sling.api.adapter.AdapterManager;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.commons.metrics.Gauge;
-import org.apache.sling.commons.metrics.MetricsService;
 import org.apache.sling.commons.osgi.RankedServices;
 import org.apache.sling.models.annotations.Model;
 import org.apache.sling.models.annotations.ValidationStrategy;
@@ -130,8 +126,6 @@ public class ModelAdapterFactory implements AdapterFactory, 
Runnable, ModelFacto
 
     private static final String REQUEST_MARKER_ATTRIBUTE = 
ModelAdapterFactory.class.getName() + ".RealRequest";
 
-    private static final Object REQUEST_MARKER_VALUE = new Object();
-
     private static final String REQUEST_CACHE_ATTRIBUTE = 
ModelAdapterFactory.class.getName() + ".AdapterCache";
 
     private static class DisposalCallbackRegistryImpl implements 
DisposalCallbackRegistry, Disposable {
@@ -155,63 +149,14 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
         }
     }
 
-    private static class CombinedDisposable implements Disposable {
-        private final Collection<Disposable> delegates = 
Collections.synchronizedCollection(new HashSet<Disposable>());
-
-        private void add(Disposable disposable) {
-            delegates.add(disposable);
-        }
-
-        @Override
-        public void onDisposed() {
-            for (Disposable delegate : delegates) {
-                delegate.onDisposed();
-            }
-        }
-    }
-
     private interface Disposable {
         void onDisposed();
     }
 
-    private static class RequestDisposalCallbacks {
-        private ConcurrentHashMap<ServletRequest, Disposable> callbacks = new 
ConcurrentHashMap<>();
-
-        public Collection<Disposable> values() {
-            return callbacks.values();
-        }
-
-        public Disposable remove(ServletRequest request) {
-            return callbacks.remove(request);
-        }
-
-        public void put(ServletRequest request, Disposable registry) {
-            synchronized (callbacks) {
-                CombinedDisposable combinedDisposable = null;
-                Disposable current = callbacks.get(request);
-                if (current == null) {
-                    callbacks.put(request, registry);
-                    return;
-                } else if (current instanceof CombinedDisposable) {
-                    combinedDisposable = (CombinedDisposable) current;
-                } else {
-                    combinedDisposable = new CombinedDisposable();
-                    combinedDisposable.add(current);
-                    callbacks.put(request, combinedDisposable);
-                }
-                combinedDisposable.add(registry);
-            }
-        }
-    }
-
     private ReferenceQueue<Object> queue;
 
     private ConcurrentMap<java.lang.ref.Reference<Object>, Disposable> 
disposalCallbacks;
 
-    private RequestDisposalCallbacks requestDisposalCallbacks;
-    // exposes the number of elements in the RequestDisposableCallback's map
-    Gauge<Integer> requestsPendingCleanup;
-
     @Override
     public void run() {
         clearDisposalCallbackRegistryQueue();
@@ -265,9 +210,6 @@ public class ModelAdapterFactory implements AdapterFactory, 
Runnable, ModelFacto
     @Reference
     AdapterManager adapterManager;
 
-    @Reference
-    MetricsService metricsService;
-
     ModelPackageBundleListener listener;
 
     final AdapterImplementations adapterImplementations = new 
AdapterImplementations();
@@ -745,6 +687,7 @@ public class ModelAdapterFactory implements AdapterFactory, 
Runnable, ModelFacto
         return null;
     }
 
+    @SuppressWarnings("unchecked")
     private <ModelType> Result<InvocationHandler> createInvocationHandler(
             final Object adaptable, final ModelClass<ModelType> modelClass) {
         InjectableMethod[] injectableMethods = 
modelClass.getInjectableMethods();
@@ -770,11 +713,15 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
         if (!registry.callbacks.isEmpty()) {
             registry.seal();
 
-            if (adaptable instanceof SlingHttpServletRequest
-                    && ((SlingHttpServletRequest) 
adaptable).getAttribute(REQUEST_MARKER_ATTRIBUTE)
-                            == REQUEST_MARKER_VALUE) {
-                registerRequestCallbackRegistry((SlingHttpServletRequest) 
adaptable, registry);
-            } else {
+            boolean registered = false;
+            if (adaptable instanceof SlingHttpServletRequest) {
+                final Object list = ((SlingHttpServletRequest) 
adaptable).getAttribute(REQUEST_MARKER_ATTRIBUTE);
+                if (list instanceof List) {
+                    ((List<Disposable>) list).add(registry);
+                    registered = true;
+                }
+            }
+            if (!registered) {
                 registerCallbackRegistry(handler, registry);
             }
         }
@@ -794,18 +741,6 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
         disposalCallbacks.put(reference, registry);
     }
 
-    private void registerRequestCallbackRegistry(ServletRequest request, 
DisposalCallbackRegistryImpl registry) {
-        request = unwrapRequest(request);
-        requestDisposalCallbacks.put(request, registry);
-    }
-
-    private static ServletRequest unwrapRequest(ServletRequest request) {
-        while (request instanceof ServletRequestWrapper) {
-            request = ((ServletRequestWrapper) request).getRequest();
-        }
-        return request;
-    }
-
     @SuppressWarnings("unchecked")
     private <ModelType> Result<ModelType> createObject(final Object adaptable, 
final ModelClass<ModelType> modelClass)
             throws InstantiationException, InvocationTargetException, 
IllegalAccessException {
@@ -860,11 +795,15 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
         if (!registry.callbacks.isEmpty()) {
             registry.seal();
 
-            if (adaptable instanceof SlingHttpServletRequest
-                    && ((SlingHttpServletRequest) 
adaptable).getAttribute(REQUEST_MARKER_ATTRIBUTE)
-                            == REQUEST_MARKER_VALUE) {
-                registerRequestCallbackRegistry((SlingHttpServletRequest) 
adaptable, registry);
-            } else {
+            boolean registered = false;
+            if (adaptable instanceof SlingHttpServletRequest) {
+                final Object list = ((SlingHttpServletRequest) 
adaptable).getAttribute(REQUEST_MARKER_ATTRIBUTE);
+                if (list instanceof List) {
+                    ((List<Disposable>) list).add(registry);
+                    registered = true;
+                }
+            }
+            if (!registered) {
                 registerCallbackRegistry(object, registry);
             }
         }
@@ -1275,7 +1214,6 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
         BundleContext bundleContext = ctx.getBundleContext();
         this.queue = new ReferenceQueue<>();
         this.disposalCallbacks = new ConcurrentHashMap<>();
-        this.requestDisposalCallbacks = new RequestDisposalCallbacks();
         Hashtable<String, Object> properties = new Hashtable<>();
         properties.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
         properties.put(Constants.SERVICE_DESCRIPTION, "Sling Models OSGi 
Service Disposal Job");
@@ -1302,21 +1240,11 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
 
         this.configPrinterRegistration = bundleContext.registerService(
                 Object.class, new ModelConfigurationPrinter(this, 
bundleContext, adapterImplementations), printerProps);
-
-        requestsPendingCleanup = metricsService.gauge(
-                
"org.apache.sling.models.ModelAdapterFactory.requestsPendingCleanup",
-                requestDisposalCallbacks.callbacks::size);
     }
 
     @Deactivate
     protected void deactivate() {
         this.adapterCache = null;
-        if (this.requestDisposalCallbacks != null) {
-            for (final Disposable requestRegistries : 
this.requestDisposalCallbacks.values()) {
-                requestRegistries.onDisposed();
-            }
-        }
-        this.requestDisposalCallbacks = null;
         this.clearDisposalCallbackRegistryQueue();
         this.listener.unregisterAll();
         this.adapterImplementations.removeAll();
@@ -1524,16 +1452,24 @@ public class ModelAdapterFactory implements 
AdapterFactory, Runnable, ModelFacto
     }
 
     @Override
-    public void requestDestroyed(ServletRequestEvent sre) {
-        ServletRequest request = unwrapRequest(sre.getServletRequest());
-        Disposable registry = requestDisposalCallbacks.remove(request);
-        if (registry != null) {
-            registry.onDisposed();
+    public void requestDestroyed(final ServletRequestEvent sre) {
+        final Object list = 
sre.getServletRequest().getAttribute(REQUEST_MARKER_ATTRIBUTE);
+        if (list != null) {
+            sre.getServletRequest().removeAttribute(REQUEST_MARKER_ATTRIBUTE);
+            if (list instanceof List) {
+                final List<?> disposalCallbacks = (List<?>) list;
+                for (final Object disposable : disposalCallbacks) {
+                    if (disposable instanceof Disposable) {
+                        ((Disposable) disposable).onDisposed();
+                    }
+                }
+                disposalCallbacks.clear();
+            }
         }
     }
 
     @Override
-    public void requestInitialized(ServletRequestEvent sre) {
-        sre.getServletRequest().setAttribute(REQUEST_MARKER_ATTRIBUTE, 
REQUEST_MARKER_VALUE);
+    public void requestInitialized(final ServletRequestEvent sre) {
+        sre.getServletRequest().setAttribute(REQUEST_MARKER_ATTRIBUTE, new 
ArrayList<>());
     }
 }
diff --git a/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java 
b/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
index a09ed67..314dd3d 100644
--- a/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
+++ b/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
@@ -27,7 +27,6 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.commons.metrics.MetricsService;
 import org.apache.sling.models.annotations.Model;
 import org.apache.sling.models.annotations.injectorspecific.Self;
 import org.apache.sling.models.export.spi.ModelExporter;
@@ -84,7 +83,6 @@ public class AdapterFactoryTest {
         Converter c = Converters.standardConverter();
         Map<String, String> map = new HashMap<>();
         ModelAdapterFactoryConfiguration config = 
c.convert(map).to(ModelAdapterFactoryConfiguration.class);
-        factory.metricsService = Mockito.mock(MetricsService.class);
         factory.activate(componentCtx, config);
         factory.injectAnnotationProcessorFactories = Collections.emptyList();
         factory.injectAnnotationProcessorFactories2 = Collections.emptyList();

Reply via email to