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

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


The following commit(s) were added to refs/heads/javax by this push:
     new fecc3e966 TAP5-2813: Better workaround
fecc3e966 is described below

commit fecc3e96671719fc9b3298d5009ed293724aca7b
Author: Thiago H. de Paula Figueiredo <[email protected]>
AuthorDate: Sun Oct 12 10:31:13 2025 -0300

    TAP5-2813: Better workaround
---
 .../internal/services/PropertyAccessImpl.java      | 37 +++++++++++++++++++---
 .../tapestry5/internal/transform/CachedWorker.java |  7 +---
 .../tapestry5/integration/app1/GenericsClass.java  | 18 ++++++++++-
 .../app1/base/AbstractCachedGenerics.java          |  9 ++++--
 .../app1/components/AtCachedSubclass.java          | 30 ++++++++++++++++++
 .../app1/components/AtCachedSuperclass.java        | 30 ++++++++++++++++++
 .../app1/components/CachedGenerics.java            |  2 +-
 .../app1/components/AtCachedSubclass.tml           |  4 +++
 .../app1/components/AtCachedSuperclass.tml         |  5 +++
 .../integration/app1/pages/CachedPage.tml          |  8 +++++
 .../ioc/test/InterfaceWithDefaultMethod.java       |  2 +-
 11 files changed, 137 insertions(+), 15 deletions(-)

diff --git 
a/beanmodel/src/main/java/org/apache/tapestry5/beanmodel/internal/services/PropertyAccessImpl.java
 
b/beanmodel/src/main/java/org/apache/tapestry5/beanmodel/internal/services/PropertyAccessImpl.java
index 88eac222a..74ea07d59 100644
--- 
a/beanmodel/src/main/java/org/apache/tapestry5/beanmodel/internal/services/PropertyAccessImpl.java
+++ 
b/beanmodel/src/main/java/org/apache/tapestry5/beanmodel/internal/services/PropertyAccessImpl.java
@@ -96,7 +96,7 @@ public class PropertyAccessImpl implements PropertyAccess
 
         try
         {
-            BeanInfo info = Introspector.getBeanInfo(forClass);
+            BeanInfo info = getBeanInfo(forClass);
 
             List<PropertyDescriptor> descriptors = CollectionFactory.newList();
 
@@ -109,7 +109,6 @@ public class PropertyAccessImpl implements PropertyAccess
 
             addPropertiesFromScala(forClass, descriptors);
 
-
             return new ClassPropertyAdapterImpl(forClass, descriptors);
         }
         catch (Throwable ex)
@@ -118,6 +117,36 @@ public class PropertyAccessImpl implements PropertyAccess
         }
     }
 
+    private BeanInfo getBeanInfo(Class<?> forClass) throws 
IntrospectionException 
+    {
+        BeanInfo beanInfo;
+        try 
+        {
+            beanInfo = Introspector.getBeanInfo(forClass);
+        } catch (IntrospectionException | NullPointerException e) 
+        {
+            
+            // TAP5-2813: if we get a problem while trying to inspect 
+            // the transformed class, let's try inspecting the original
+            // class. This problem only happens in multiple classloader mode
+            // AND using the @Cached annotation in a method that returns
+            // a type with generics. Quite specific.
+            Class<?> untransformedClass;
+            try
+            {
+                untransformedClass = this.getClass().getClassLoader()
+                        .loadClass(forClass.getName());
+                beanInfo = Introspector.getBeanInfo(untransformedClass);
+            }
+            catch (ClassNotFoundException e2)
+            {
+                throw new RuntimeException(e2);
+            }
+            
+        }
+        return beanInfo;
+    }
+    
     private static <T> void addAll(List<T> list, T[] array)
     {
         if (array.length > 0){
@@ -135,7 +164,7 @@ public class PropertyAccessImpl implements PropertyAccess
         }
     }
 
-    private static void addPropertiesFromExtendedInterfaces(Class forClass, 
List<PropertyDescriptor> descriptors)
+    private void addPropertiesFromExtendedInterfaces(Class forClass, 
List<PropertyDescriptor> descriptors)
             throws IntrospectionException
     {
 
@@ -151,7 +180,7 @@ public class PropertyAccessImpl implements PropertyAccess
         {
             Class c = queue.removeFirst();
 
-            BeanInfo info = Introspector.getBeanInfo(c);
+            BeanInfo info = getBeanInfo(c);
 
             // Duplicates occur and are filtered out in ClassPropertyAdapter 
which stores
             // a property name to descriptor map.
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
index 643abdd63..142804497 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
@@ -275,16 +275,11 @@ public class CachedWorker implements 
ComponentClassTransformWorker2
     {
         final MethodDescription description = method.getDescription();
         
-        // TAP5-2813
-        final String genericSignature = description.genericSignature != null ?
-                description.genericSignature.replaceAll("<[^>]+>", "") : null;
-        
-        
         return new JSONObject(
                 MODIFIERS, description.modifiers,
                 RETURN_TYPE, description.returnType,
                 NAME, description.methodName,
-                GENERIC_SIGNATURE, genericSignature,
+                GENERIC_SIGNATURE, description.genericSignature,
                 ARGUMENT_TYPES, new JSONArray(description.argumentTypes),
                 CHECKED_EXCEPTION_TYPES, new 
JSONArray(description.checkedExceptionTypes),
                 WATCH, method.getAnnotation(Cached.class).watch());
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/GenericsClass.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/GenericsClass.java
index dd004b952..395f97add 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/GenericsClass.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/GenericsClass.java
@@ -1,6 +1,22 @@
 package org.apache.tapestry5.integration.app1;
 
+import java.util.List;
 
-public class GenericsClass<T, H> {
+public class GenericsClass<T, H> 
+{
 
+    final private List<T> list;
+
+    public GenericsClass(List<T> list) 
+    {
+        super();
+        this.list = list;
+    }
+
+    @Override
+    public String toString() 
+    {
+        return "GenericsClass [list=" + list + "]";
+    }
+    
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/base/AbstractCachedGenerics.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/base/AbstractCachedGenerics.java
index 053279e6d..ad93c9e4f 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/base/AbstractCachedGenerics.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/base/AbstractCachedGenerics.java
@@ -1,6 +1,7 @@
 package org.apache.tapestry5.integration.app1.base;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.tapestry5.annotations.Cached;
@@ -8,13 +9,17 @@ import org.apache.tapestry5.integration.app1.GenericsClass;
 
 public abstract class AbstractCachedGenerics<T, H> 
 {
-
+    
     protected abstract GenericsClass<T, H> createTable(List<T> 
itemsInCurrentPage);
 
+    @SuppressWarnings("unchecked")
     @Cached
     public GenericsClass<T, H> getEmptyTable() 
     {
-        return createTable(new ArrayList<>());
+        final String timestamp = String.valueOf(System.currentTimeMillis());
+//        System.out.println("XXXXX " + timestamp);
+        return createTable(new ArrayList(Arrays.asList("value1", "value2", 
+                timestamp)));
     }
     
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.java
new file mode 100644
index 000000000..c189efed9
--- /dev/null
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.java
@@ -0,0 +1,30 @@
+// Copyright 2025 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.integration.app1.components;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.annotations.Cached;
+
+public class AtCachedSubclass extends AtCachedSuperclass
+{
+    @Cached
+    public List<String> getSource()
+    {
+        return Arrays.asList("Subclass", 
String.valueOf(System.currentTimeMillis()));
+    }
+    
+}
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.java
new file mode 100644
index 000000000..8b3f7b770
--- /dev/null
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.java
@@ -0,0 +1,30 @@
+// Copyright 2025 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.integration.app1.components;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.annotations.Cached;
+
+public class AtCachedSuperclass
+{
+    @Cached
+    public List<String> getSource()
+    {
+        return Arrays.asList("Subclass", 
String.valueOf(System.currentTimeMillis()));
+    }
+    
+}
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/CachedGenerics.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/CachedGenerics.java
index 8e0fef614..8d4541466 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/CachedGenerics.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/CachedGenerics.java
@@ -12,7 +12,7 @@ public class CachedGenerics extends 
AbstractCachedGenerics<GenericsEntity, Strin
     @Override
     protected GenericsClass<GenericsEntity, String> 
createTable(List<GenericsEntity> itemsInCurrentPage) 
     {
-        return new GenericsClass<>();
+        return new GenericsClass<>(itemsInCurrentPage);
     }
 
 }
diff --git 
a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.tml
 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.tml
new file mode 100644
index 000000000..75df1ba3e
--- /dev/null
+++ 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSubclass.tml
@@ -0,0 +1,4 @@
+<div xmlns="http://www.w3.org/1999/xhtml"; 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";>
+       <p id="subclassValue0">${source.get(0)}</p>
+       <p id="subclassValue1">${source.get(1)}</p>
+</div>
diff --git 
a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.tml
 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.tml
new file mode 100644
index 000000000..ea99d32c9
--- /dev/null
+++ 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/AtCachedSuperclass.tml
@@ -0,0 +1,5 @@
+<div xmlns="http://www.w3.org/1999/xhtml"; 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";>
+       <p>@Cached superclass</p>
+       <p id="superclassValue0">${source.get(0)}</p>
+       <p id="superclassValue1">${source.get(1)}</p>
+</div>
diff --git 
a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/CachedPage.tml
 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/CachedPage.tml
index 9c62288dd..1da6fe1bd 100644
--- 
a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/CachedPage.tml
+++ 
b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/CachedPage.tml
@@ -10,4 +10,12 @@
        <span class="watch">${value3}</span>
        ${incrWatchValue()}
        <span class="watch">${value3}</span>
+
+       <div>
+               <h2>@Cached subclass</h2>
+               <t:atCachedSubclass/>
+               <h2>@Cached superclass</h2>
+               <t:atCachedSuperclass/>
+       </div>
+       
 </html>
diff --git 
a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/InterfaceWithDefaultMethod.java
 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/InterfaceWithDefaultMethod.java
index bb1e820e9..8ab87fd63 100644
--- 
a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/InterfaceWithDefaultMethod.java
+++ 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/InterfaceWithDefaultMethod.java
@@ -6,7 +6,7 @@ public interface InterfaceWithDefaultMethod
 
     public static final String STATIC_METHOD_RETURN_VALUE = "whatever";
 
-    static String staticMethod() 
+    public static String staticMethod() 
     {
         return STATIC_METHOD_RETURN_VALUE;
     }

Reply via email to