You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2023/06/17 21:59:50 UTC
[tapestry-5] branch master updated: TAP5-2756: allow non-soft references in the page cache
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 <th...@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);
+ }
}