This is an automated email from the ASF dual-hosted git repository. thiagohp pushed a commit to branch better-page-invalidation in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/better-page-invalidation by this push: new abdd80ea1 TAP-2742: production mode fixed, PageCatalog too abdd80ea1 is described below commit abdd80ea18e765289810d318708deb34a38cbb1e Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br> AuthorDate: Fri Apr 28 23:30:39 2023 -0300 TAP-2742: production mode fixed, PageCatalog too --- .../tapestry5/corelib/pages/PageCatalog.java | 191 ++++++++++++++++++++- .../internal/services/PageSourceImpl.java | 1 + .../PageClassloaderContextManagerImpl.java | 52 ++---- .../integration/app1/components/Border.tml | 2 +- 4 files changed, 203 insertions(+), 43 deletions(-) diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java index abaedb62d..e887c0da1 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java @@ -14,31 +14,53 @@ package org.apache.tapestry5.corelib.pages; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.alerts.AlertManager; -import org.apache.tapestry5.annotations.*; +import org.apache.tapestry5.annotations.InjectComponent; +import org.apache.tapestry5.annotations.Persist; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.annotations.UnknownActivationContextCheck; +import org.apache.tapestry5.annotations.WhitelistAccessOnly; import org.apache.tapestry5.beaneditor.Validate; import org.apache.tapestry5.beanmodel.BeanModel; import org.apache.tapestry5.beanmodel.services.BeanModelSource; import org.apache.tapestry5.commons.Messages; +import org.apache.tapestry5.commons.services.InvalidationEventHub; import org.apache.tapestry5.commons.util.CollectionFactory; import org.apache.tapestry5.corelib.components.Zone; -import org.apache.tapestry5.func.*; +import org.apache.tapestry5.dom.Element; +import org.apache.tapestry5.func.F; +import org.apache.tapestry5.func.Flow; +import org.apache.tapestry5.func.Mapper; +import org.apache.tapestry5.func.Predicate; +import org.apache.tapestry5.func.Reducer; import org.apache.tapestry5.http.TapestryHttpSymbolConstants; +import org.apache.tapestry5.http.services.Request; import org.apache.tapestry5.internal.PageCatalogTotals; +import org.apache.tapestry5.internal.services.ComponentDependencyGraphvizGenerator; +import org.apache.tapestry5.internal.services.ComponentDependencyRegistry; import org.apache.tapestry5.internal.services.PageSource; import org.apache.tapestry5.internal.services.ReloadHelper; +import org.apache.tapestry5.internal.structure.ComponentPageElement; import org.apache.tapestry5.internal.structure.Page; import org.apache.tapestry5.ioc.OperationTracker; +import org.apache.tapestry5.ioc.annotations.ComponentClasses; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.ioc.annotations.Symbol; import org.apache.tapestry5.ioc.internal.util.InternalUtils; +import org.apache.tapestry5.runtime.Component; import org.apache.tapestry5.services.ComponentClassResolver; +import org.apache.tapestry5.services.ajax.AjaxResponseRenderer; +import org.apache.tapestry5.services.javascript.JavaScriptSupport; import org.apache.tapestry5.services.pageload.ComponentResourceSelector; -import java.util.Collection; -import java.util.List; -import java.util.Set; - /** * Lists out the currently loaded pages, using a {@link org.apache.tapestry5.corelib.components.Grid}. * Provides an option to force all pages to be loaded. In development mode, includes an option to clear the page cache. @@ -64,6 +86,9 @@ public class PageCatalog @Inject private ComponentClassResolver resolver; + + @Inject + private ComponentDependencyRegistry componentDependencyRegistry; @Inject private AlertManager alertManager; @@ -71,8 +96,17 @@ public class PageCatalog @Property private Page page; + @Property + private Page selectedPage; + + @Property + private String dependency; + @InjectComponent private Zone pagesZone; + + @InjectComponent + private Zone pageStructureZone; @Persist private Set<String> failures; @@ -90,13 +124,32 @@ public class PageCatalog @Inject private BeanModelSource beanModelSource; - + @Inject private Messages messages; @Property public static BeanModel<Page> model; + @Inject + private Request request; + + @Inject + @ComponentClasses + private InvalidationEventHub classesInvalidationEventHub; + + @Inject + private JavaScriptSupport javaScriptSupport; + + @Inject + private ComponentDependencyGraphvizGenerator componentDependencyGraphvizGenerator; + + @Inject + private ComponentClassResolver componentClassResolver; + + @Inject + private AjaxResponseRenderer ajaxResponseRenderer; + void pageLoaded() { model = beanModelSource.createDisplayModel(Page.class, messages); @@ -105,6 +158,7 @@ public class PageCatalog model.addExpression("assemblyTime", "stats.assemblyTime"); model.addExpression("componentCount", "stats.componentCount"); model.addExpression("weight", "stats.weight"); + model.add("clear", null); model.reorder("name", "selector", "assemblyTime", "componentCount", "weight"); } @@ -153,7 +207,16 @@ public class PageCatalog { return pageSource.getAllPages(); } - + + Object onClearPage(String className) + { + final String logicalName = resolver.getLogicalName(className); + classesInvalidationEventHub.fireInvalidationEvent(Arrays.asList(className)); + alertManager.warn(String.format("Page %s (%s) has been cleared from the page cache", + className, logicalName)); + return pagesZone.getBody(); + } + Object onSuccessFromSinglePageLoad() { boolean found = !F.flow(getPages()).filter(new Predicate<Page>() @@ -270,6 +333,19 @@ public class PageCatalog return pagesZone.getBody(); } + + Object onActionFromStoreDependencyInformation() + { + + componentDependencyRegistry.writeFile(); + + alertManager.warn(String.format( + "Component dependency information written to %s.", + ComponentDependencyRegistry.FILENAME)); + + return pagesZone.getBody(); + + } Object onActionFromRunGC() { @@ -291,4 +367,103 @@ public class PageCatalog { return String.format("%,.3f ms", millis); } + + public List<String> getDependencies() + { + List<String> dependencies = new ArrayList<>(componentDependencyRegistry.getDependencies(getSelectedPageClassName())); + Collections.sort(dependencies); + return dependencies; + } + + public void onPageStructure(String pageName) + { + selectedPage = pageSource.getPage(pageName); + ajaxResponseRenderer.addRender("pageStructureZone", pageStructureZone.getBody()); + } + + public String getDisplayLogicalName() + { + return getDisplayLogicalName(dependency); + } + + public String getPageClassName() + { + return getClassName(page); + } + + public String getSelectedPageClassName() + { + return getClassName(selectedPage); + } + + private String getClassName(Page page) + { + return page.getRootComponent().getComponentResources().getComponentModel().getComponentClassName(); + } + + private String getClassName(Component component) + { + return component.getComponentResources().getComponentModel().getComponentClassName(); + } + + public void onComponentTree(MarkupWriter writer) + { + render(selectedPage.getRootElement(), writer); + } + + private void render(ComponentPageElement componentPageElement, MarkupWriter writer) + { + final Element li = writer.element("li"); + final String className = getClassName(componentPageElement.getComponent()); + final Set<String> embeddedElementIds = componentPageElement.getEmbeddedElementIds(); + + if (componentPageElement.getComponent().getComponentResources().getComponentModel().isPage()) + { + li.text(componentPageElement.getPageName()); + } + else { + li.text(String.format("%s (%s)", getDisplayLogicalName(className), componentPageElement.getId())); + } + + if (!embeddedElementIds.isEmpty()) + { + writer.element("ul"); + for (String id : embeddedElementIds) + { + render(componentPageElement.getEmbeddedElement(id), writer); + } + writer.end(); + } + + writer.end(); + } + + private String getDisplayLogicalName(final String className) + { + final String logicalName = resolver.getLogicalName(className); + String displayName = logicalName; + if (logicalName == null || logicalName.trim().length() == 0) + { + if (className.contains(".base.")) + { + displayName = "(base class)"; + } + if (className.contains(".mixins.")) + { + displayName = "(mixin)"; + } + } + return displayName; + } + + public String getLogicalName(String className) + { + return resolver.getLogicalName(className); + } + + public String getGraphvizValue() + { + return componentDependencyGraphvizGenerator.generate(getClassName(selectedPage)); + } + } 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 b442646c6..a93720f72 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 @@ -182,6 +182,7 @@ public class PageSourceImpl implements PageSource pageCache.put(key, ref); + // TODO: remove this? if (!productionMode) { final ComponentPageElement rootElement = page.getRootElement(); diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java index 054129f44..52fb9300c 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java @@ -24,14 +24,12 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; -import org.apache.tapestry5.SymbolConstants; import org.apache.tapestry5.commons.internal.util.TapestryException; import org.apache.tapestry5.commons.services.InvalidationEventHub; import org.apache.tapestry5.commons.services.PlasticProxyFactory; import org.apache.tapestry5.internal.services.ComponentDependencyRegistry; import org.apache.tapestry5.internal.services.InternalComponentInvalidationEventHub; import org.apache.tapestry5.ioc.annotations.ComponentClasses; -import org.apache.tapestry5.ioc.annotations.Symbol; import org.apache.tapestry5.plastic.PlasticUtils; import org.apache.tapestry5.services.ComponentClassResolver; import org.slf4j.Logger; @@ -55,8 +53,6 @@ public class PageClassloaderContextManagerImpl implements PageClassloaderContext private final InvalidationEventHub componentClassesInvalidationEventHub; - private final boolean productionMode; - private final static ThreadLocal<Integer> NESTED_MERGE_COUNT = ThreadLocal.withInitial(() -> 0); private final static ThreadLocal<Boolean> INVALIDATING_CONTEXT = ThreadLocal.withInitial(() -> false); @@ -71,15 +67,13 @@ public class PageClassloaderContextManagerImpl implements PageClassloaderContext final ComponentDependencyRegistry componentDependencyRegistry, final ComponentClassResolver componentClassResolver, final InternalComponentInvalidationEventHub invalidationHub, - final @ComponentClasses InvalidationEventHub componentClassesInvalidationEventHub, - @Symbol(SymbolConstants.PRODUCTION_MODE) final boolean productionMode) + final @ComponentClasses InvalidationEventHub componentClassesInvalidationEventHub) { super(); this.componentDependencyRegistry = componentDependencyRegistry; this.componentClassResolver = componentClassResolver; this.invalidationHub = invalidationHub; this.componentClassesInvalidationEventHub = componentClassesInvalidationEventHub; - this.productionMode = productionMode; invalidationHub.addInvalidationCallback(this::listen); NESTED_MERGE_COUNT.set(0); } @@ -105,38 +99,28 @@ public class PageClassloaderContextManagerImpl implements PageClassloaderContext { PageClassloaderContext context; - if (productionMode) - { - root.addClass(className); - context = root; - } - else + final String enclosingClassName = PlasticUtils.getEnclosingClassName(className); + context = root.findByClassName(enclosingClassName); + + if (context == null) { + Set<String> classesToInvalidate = new HashSet<>(); - final String enclosingClassName = PlasticUtils.getEnclosingClassName(className); - context = root.findByClassName(enclosingClassName); + context = processUsingDependencies( + enclosingClassName, + root, + () -> getUnknownContext(root, plasticProxyFactoryProvider), + plasticProxyFactoryProvider, + classesToInvalidate); - if (context == null) + if (!classesToInvalidate.isEmpty()) { - Set<String> classesToInvalidate = new HashSet<>(); - - context = processUsingDependencies( - enclosingClassName, - root, - () -> getUnknownContext(root, plasticProxyFactoryProvider), - plasticProxyFactoryProvider, - classesToInvalidate); - - if (!classesToInvalidate.isEmpty()) - { - invalidate(classesToInvalidate); - } + invalidate(classesToInvalidate); + } - if (!className.equals(enclosingClassName)) - { - loadClass(className, context); - } - + if (!className.equals(enclosingClassName)) + { + loadClass(className, context); } } diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/Border.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/Border.tml index 2a2941e0e..908c91961 100644 --- a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/Border.tml +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/Border.tml @@ -44,7 +44,7 @@ <t:devtool class="pull-right"/> <t:remove>alert-class is for the AlertsTest.check_informal_parameters test</t:remove> - <pre>${pccm.root.toRecursiveString().trim()}</pre> +<!-- <pre>${pccm.root.toRecursiveString().trim()}</pre> --> <t:alerts class="alert-class"/> <t:body/>