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();

Reply via email to