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

thiagohp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


The following commit(s) were added to refs/heads/master by this push:
     new 2c75fdbf2 TAP5-2756: allow non-soft references in the page cache
2c75fdbf2 is described below

commit 2c75fdbf2cb07ca926144541a41e572a48bc878c
Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
AuthorDate: Sat Jun 17 18:59:39 2023 -0300

    TAP5-2756: allow non-soft references in the page cache
---
 .../internal/services/PageSourceImpl.java          | 55 +++++++++++++++++-----
 .../apache/tapestry5/modules/PageLoadModule.java   | 20 ++++++++
 .../pageload/PageCachingReferenceTypeService.java  | 38 +++++++++++++++
 .../tapestry5/services/pageload/ReferenceType.java | 34 +++++++++++++
 .../integration/app1/services/AppModule.java       | 10 ++++
 5 files changed, 145 insertions(+), 12 deletions(-)

diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
index fe92fe3df..48a004fd8 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
@@ -40,8 +40,10 @@ import org.apache.tapestry5.services.ComponentMessages;
 import org.apache.tapestry5.services.ComponentTemplates;
 import org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer;
 import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
+import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService;
 import org.apache.tapestry5.services.pageload.PageClassLoaderContext;
 import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
+import org.apache.tapestry5.services.pageload.ReferenceType;
 import org.slf4j.Logger;
 
 public class PageSourceImpl implements PageSource
@@ -56,6 +58,8 @@ public class PageSourceImpl implements PageSource
     
     private final PageClassLoaderContextManager pageClassLoaderContextManager;
     
+    private final PageCachingReferenceTypeService 
pageCachingReferenceTypeService;
+    
     private final Logger logger;
     
     final private boolean productionMode;
@@ -100,12 +104,13 @@ public class PageSourceImpl implements PageSource
         
     }
 
-    private final Map<CachedPageKey, SoftReference<Page>> pageCache = 
CollectionFactory.newConcurrentMap();
+    private final Map<CachedPageKey, Object> pageCache = 
CollectionFactory.newConcurrentMap();
 
     public PageSourceImpl(PageLoader pageLoader, 
ComponentRequestSelectorAnalyzer selectorAnalyzer,
             ComponentDependencyRegistry componentDependencyRegistry,
             ComponentClassResolver componentClassResolver,
             PageClassLoaderContextManager pageClassLoaderContextManager,
+            PageCachingReferenceTypeService pageCachingReferenceTypeService,
             @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode,
             @Symbol(SymbolConstants.MULTIPLE_CLASSLOADERS) boolean 
multipleClassLoaders,
             Logger logger)
@@ -115,6 +120,7 @@ public class PageSourceImpl implements PageSource
         this.componentDependencyRegistry = componentDependencyRegistry;
         this.componentClassResolver = componentClassResolver;
         this.productionMode = productionMode;
+        this.pageCachingReferenceTypeService = pageCachingReferenceTypeService;
         this.multipleClassLoaders = multipleClassLoaders;
         this.pageClassLoaderContextManager = pageClassLoaderContextManager;
         this.logger = logger;
@@ -151,9 +157,11 @@ public class PageSourceImpl implements PageSource
         
         while (true)
         {
-            SoftReference<Page> ref = pageCache.get(key);
-
-            Page page = ref == null ? null : ref.get();
+            
+            Page page;
+            Object object = pageCache.get(key);
+            
+            page = toPage(object);
 
             if (page != null)
             {
@@ -181,9 +189,15 @@ public class PageSourceImpl implements PageSource
 
             page = pageLoader.loadPage(canonicalPageName, selector);
 
-            ref = new SoftReference<Page>(page);
-
-            pageCache.put(key, ref);
+            final ReferenceType referenceType = 
pageCachingReferenceTypeService.get(canonicalPageName);
+            if (referenceType.equals(ReferenceType.SOFT))
+            {
+                pageCache.put(key, new SoftReference<Page>(page));
+            }
+            else
+            {
+                pageCache.put(key, page);
+            }
             
             if (!productionMode)
             {
@@ -298,10 +312,10 @@ public class PageSourceImpl implements PageSource
                 if (componentClassResolver.isPage(className))
                 {
                     pageName = 
componentClassResolver.resolvePageClassNameToPageName(className);
-                    final Iterator<Entry<CachedPageKey, SoftReference<Page>>> 
iterator = pageCache.entrySet().iterator();
+                    final Iterator<Entry<CachedPageKey, Object>> iterator = 
pageCache.entrySet().iterator();
                     while (iterator.hasNext())
                     {
-                        final Entry<CachedPageKey, SoftReference<Page>> entry 
= iterator.next();
+                        final Entry<CachedPageKey, Object> entry = 
iterator.next();
                         final String entryPageName = entry.getKey().pageName;
                         if (entryPageName.equalsIgnoreCase(pageName)) 
                         {
@@ -324,12 +338,29 @@ public class PageSourceImpl implements PageSource
 
     public Set<Page> getAllPages()
     {
-        return F.flow(pageCache.values()).map(new Mapper<SoftReference<Page>, 
Page>()
+        return F.flow(pageCache.values()).map(new Mapper<Object, Page>()
         {
-            public Page map(SoftReference<Page> element)
+            public Page map(Object object)
             {
-                return element.get();
+                return toPage(object);
             }
         }).removeNulls().toSet();
     }
+    
+    private Page toPage(Object object) 
+    {
+        Page page;
+        if (object instanceof SoftReference)
+        {
+            @SuppressWarnings("unchecked")
+            SoftReference<Page> ref = (SoftReference<Page>) object;
+            page = ref == null ? null : ref.get();
+        }
+        else
+        {
+            page = (Page) object;
+        }
+        return page;
+    }
+    
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/PageLoadModule.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/PageLoadModule.java
index 1a993ab03..8e80d0bd1 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/PageLoadModule.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/PageLoadModule.java
@@ -12,8 +12,11 @@
 
 package org.apache.tapestry5.modules;
 
+import java.util.List;
+
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.commons.MappedConfiguration;
+import org.apache.tapestry5.commons.OrderedConfiguration;
 import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
 import 
org.apache.tapestry5.internal.pageload.DefaultComponentRequestSelectorAnalyzer;
 import org.apache.tapestry5.internal.pageload.DefaultComponentResourceLocator;
@@ -25,13 +28,17 @@ import org.apache.tapestry5.ioc.ServiceBinder;
 import org.apache.tapestry5.ioc.annotations.Marker;
 import org.apache.tapestry5.ioc.annotations.Startup;
 import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.services.ChainBuilder;
+import org.apache.tapestry5.services.ComponentLibraryInfoSource;
 import org.apache.tapestry5.services.Core;
 import org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer;
 import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
+import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService;
 import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
 import 
org.apache.tapestry5.services.pageload.PageClassLoaderContextManagerImpl;
 import org.apache.tapestry5.services.pageload.PagePreloader;
 import org.apache.tapestry5.services.pageload.PreloaderMode;
+import org.apache.tapestry5.services.pageload.ReferenceType;
 
 /**
  * @since 5.3
@@ -89,5 +96,18 @@ public class PageLoadModule
             }
         }
     }
+    
+    public static PageCachingReferenceTypeService 
buildPageCachingReferenceTypeService(
+            List<PageCachingReferenceTypeService> configuration,
+            ChainBuilder chainBuilder) 
+    {
+        return chainBuilder.build(PageCachingReferenceTypeService.class, 
configuration);
+    }
+    
+    public static void contributePageCachingReferenceTypeService(
+            OrderedConfiguration<PageCachingReferenceTypeService> 
configuration)
+    {
+        configuration.add("Fallback", p -> ReferenceType.SOFT, "after:*");
+    }
 
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageCachingReferenceTypeService.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageCachingReferenceTypeService.java
new file mode 100644
index 000000000..d58d8f912
--- /dev/null
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageCachingReferenceTypeService.java
@@ -0,0 +1,38 @@
+// Copyright 2023 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.pageload;
+
+import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
+
+/**
+ * A service which defines whether cache page instances should have soft 
references pointing to
+ * it (the default) or strong, non-garbage-collectable ones. This service is a 
chain of command
+ * of itself
+ *
+ * @see ReferenceType
+ * @since 5.8.3
+ */
+@UsesOrderedConfiguration(PageCachingReferenceTypeService.class)
+public interface PageCachingReferenceTypeService
+{
+    /**
+     * Defines which reference type should be used to cache instances of the 
given page.
+     * Returning <code>null</code> means this implementation doesn't handle 
wit the given page.
+     * @param canonicalPageName the name of the page.
+     * @return a ReferenceType object or <code>null</code>
+     */
+    ReferenceType get(String canonicalPageName);
+    
+}
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/ReferenceType.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/ReferenceType.java
new file mode 100644
index 000000000..979931110
--- /dev/null
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/ReferenceType.java
@@ -0,0 +1,34 @@
+// Copyright 2023 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.services.pageload;
+
+import java.lang.ref.SoftReference;
+
+/**
+ * Defines the types of reference the page cache can use.
+ * @see PageCachingReferenceTypeService
+ * @since 5.8.3
+ */
+public enum ReferenceType
+{
+    /**
+     * Use a soft reference ({@linkplain SoftReference}) to cached page 
instances.
+     */
+    SOFT, 
+    
+    /**
+     * Use a strong (normal) reference to cached page instances.
+     */
+    STRONG
+}
\ No newline at end of file
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
index 5f57836bf..3851f684d 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
@@ -59,8 +59,10 @@ import org.apache.tapestry5.services.ValueEncoderFactory;
 import org.apache.tapestry5.services.ValueLabelProvider;
 import org.apache.tapestry5.services.compatibility.Compatibility;
 import org.apache.tapestry5.services.compatibility.Trait;
+import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService;
 import org.apache.tapestry5.services.pageload.PagePreloader;
 import org.apache.tapestry5.services.pageload.PreloaderMode;
+import org.apache.tapestry5.services.pageload.ReferenceType;
 import org.apache.tapestry5.services.rest.MappedEntityManager;
 import org.apache.tapestry5.services.security.ClientWhitelist;
 import org.apache.tapestry5.services.security.WhitelistAnalyzer;
@@ -418,5 +420,13 @@ public class AppModule
        {
            
configuration.add("org.apache.tapestry5.integration.app1.data.rest.entities");
        }
+       
+    public static void contributePageCachingReferenceTypeService(
+            OrderedConfiguration<PageCachingReferenceTypeService> 
configuration)
+    {
+        // Just some pages to make sure the feature doesn't cause regressions.
+        configuration.add("Index", p -> p.equals("Index") || p.contains("Bean")
+                ? ReferenceType.STRONG : null);
+    }
 
 }

Reply via email to