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 5c719e3f0 TAP5-2772: ClassCastException sometimes when in production mode 5c719e3f0 is described below commit 5c719e3f05dc3a206516658d4ad6781902b3aa98 Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br> AuthorDate: Sun Mar 24 23:22:18 2024 -0300 TAP5-2772: ClassCastException sometimes when in production mode --- .../services/ComponentDependencyRegistryImpl.java | 13 ++++--- .../services/ComponentInstantiatorSourceImpl.java | 3 +- .../apache/tapestry5/modules/PageLoadModule.java | 14 ++++++++ .../PageClassLoaderContextManagerImpl.java | 40 ++++++++++++++-------- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java index 7f794f6ea..594cb72ef 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java @@ -587,13 +587,16 @@ public class ComponentDependencyRegistryImpl implements ComponentDependencyRegis Objects.requireNonNull(dependency, "Parameter type cannot be null"); synchronized (map) { - Set<Dependency> dependents = map.get(dependency); - if (dependents == null) + if (!component.equals(dependency)) { - dependents = new HashSet<>(); - map.put(dependency, dependents); + Set<Dependency> dependents = map.get(dependency); + if (dependents == null) + { + dependents = new HashSet<>(); + map.put(dependency, dependents); + } + dependents.add(new Dependency(component, type)); } - dependents.add(new Dependency(component, type)); } } diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java index 1faeecf23..3573b474b 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java @@ -321,7 +321,8 @@ public final class ComponentInstantiatorSourceImpl implements ComponentInstantia if (rootPageClassloaderContext == null) { - logger.info("Initializing page pool. Multiple classloaders " + (!productionMode && multipleClassLoaders ? "enabled" : "disabled") + "."); + logger.info("Initializing page pool. Production mode " + (productionMode ? "enabled" : "disabled") + + ". Multiple classloaders " + (!productionMode && multipleClassLoaders ? "enabled" : "disabled") + "."); pageClassLoaderContextManager.clear(); 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 5ca2f3715..ae6e76a77 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 @@ -31,6 +31,7 @@ import org.apache.tapestry5.internal.services.TemplateParser; import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker; import org.apache.tapestry5.ioc.ServiceBinder; import org.apache.tapestry5.ioc.annotations.Marker; +import org.apache.tapestry5.ioc.annotations.Order; import org.apache.tapestry5.ioc.annotations.Startup; import org.apache.tapestry5.ioc.annotations.Symbol; import org.apache.tapestry5.ioc.services.ChainBuilder; @@ -87,6 +88,7 @@ public class PageLoadModule } @Startup + @Order("before:*") public void preloadPageClassLoaderContexts( PageClassLoaderContextManager pageClassLoaderContextManager, ComponentDependencyRegistry componentDependencyRegistry, @@ -104,6 +106,18 @@ public class PageLoadModule } } } + // Preload the dependency information for all pages + // when in production mode. Without that, exceptions during + // page assembly will occurr. This should add just a few + // seconds to page initialization. If it takes too long, + // we can create a version of preload() that accepts a boolean + // parameter defining whether templates should be parsed or not + // (the exception occurrs when a superclass isn't loaded + // and transformed before a subclass) + else if (productionMode) + { + pageClassLoaderContextManager.preload(); + } } public static PageCachingReferenceTypeService buildPageCachingReferenceTypeService( 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 5a9b52e39..dd437a3cf 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 @@ -58,6 +58,8 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext private final boolean multipleClassLoaders; + 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); @@ -73,6 +75,7 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext final ComponentClassResolver componentClassResolver, final InternalComponentInvalidationEventHub invalidationHub, final @ComponentClasses InvalidationEventHub componentClassesInvalidationEventHub, + final @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode, final @Symbol(SymbolConstants.MULTIPLE_CLASSLOADERS) boolean multipleClassLoaders) { super(); @@ -81,6 +84,7 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext this.invalidationHub = invalidationHub; this.componentClassesInvalidationEventHub = componentClassesInvalidationEventHub; this.multipleClassLoaders = multipleClassLoaders; + this.productionMode = productionMode; invalidationHub.addInvalidationCallback(this::listen); NESTED_MERGE_COUNT.set(0); } @@ -114,14 +118,11 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext Objects.requireNonNull(plasticProxyFactoryProvider); this.root = root; this.plasticProxyFactoryProvider = plasticProxyFactoryProvider; - if (multipleClassLoaders) - { - LOGGER.debug("Root context: {}", root); - } + LOGGER.info("Root context: {}", root); } @Override - public PageClassLoaderContext get(final String className) + public synchronized PageClassLoaderContext get(final String className) { PageClassLoaderContext context; @@ -226,12 +227,9 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext { context = root; } else { - if ( + if (!productionMode && ( !componentDependencyRegistry.contains(className) || - !multipleClassLoaders - // TODO: review this -// && componentDependencyRegistry.getDependents(className).isEmpty() - ) + !multipleClassLoaders)) { context = unknownContextProvider.get(); } @@ -273,7 +271,11 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext } } - if (contextDependencies.size() == 0) + if (!multipleClassLoaders) + { + context = root; + } + else if (contextDependencies.size() == 0) { context = new PageClassLoaderContext( getContextName(className), @@ -300,8 +302,11 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext plasticProxyFactoryProvider.apply(parentContext.getClassLoader()), this::get); } - - context.getParent().addChild(context); + + if (multipleClassLoaders) + { + context.getParent().addChild(context); + } // Ensure non-page class is initialized in the correct context and classloader. // Pages get their own context and classloader, so this initialization @@ -312,7 +317,10 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext loadClass(className, context); } - LOGGER.debug("New context: {}", context); + if (multipleClassLoaders) + { + LOGGER.debug("New context: {}", context); + } } } @@ -651,6 +659,10 @@ public class PageClassLoaderContextManagerImpl implements PageClassLoaderContext { throw new RuntimeException(e); } + catch (Exception e) + { + LOGGER.warn("Exception while preloading page " + page, e); + } } long finish = System.currentTimeMillis();