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 39f6cb203 TAP5-2803: support for global per-thread ES module config 
callbacks
39f6cb203 is described below

commit 39f6cb20315b8b5fa7d9c6953a0863a989ba26cd
Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
AuthorDate: Sat May 3 12:38:44 2025 -0300

    TAP5-2803: support for global per-thread ES module config callbacks
---
 .../services/javascript/EsModuleManagerImpl.java   | 42 ++++++++++------
 .../javascript/EsModuleConfigurationCallback.java  | 28 +++++++++++
 .../services/javascript/EsModuleManager.java       | 57 ++++++++++++++++++++-
 .../tapestry5/integration/app1/EsModuleTests.java  |  8 +++
 .../integration/app1/pages/EsModuleDemo.java       |  5 ++
 .../integration/app1/services/AppModule.java       | 58 +++++++++++++++-------
 6 files changed, 163 insertions(+), 35 deletions(-)

diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
index 9f9bf5aea..97f95a554 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
@@ -13,6 +13,7 @@
 package org.apache.tapestry5.internal.services.javascript;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,7 +28,6 @@ import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
 import org.apache.tapestry5.internal.InternalConstants;
 import org.apache.tapestry5.internal.services.ajax.EsModuleInitializationImpl;
 import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
-import org.apache.tapestry5.ioc.annotations.PostInjection;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.services.ClasspathMatcher;
 import org.apache.tapestry5.ioc.services.ClasspathScanner;
@@ -70,10 +70,12 @@ public class EsModuleManagerImpl implements EsModuleManager
     
     private final ResourceChangeTracker resourceChangeTracker;
     
-    private final List<EsModuleConfigurationCallback> globalCallbacks;
+    private final List<EsModuleConfigurationCallback> baseCallbacks;
+    
+    private final List<EsModuleConfigurationCallback> 
globalPerRequestCallbacks;
 
     public EsModuleManagerImpl(
-                             List<EsModuleConfigurationCallback> 
globalCallbacks,
+                             List<EsModuleManagerContribution> contributions,
                              AssetSource assetSource,
                              StreamableResourceSource streamableResourceSource,
                              @Symbol(SymbolConstants.COMPACT_JSON)
@@ -86,9 +88,24 @@ public class EsModuleManagerImpl implements EsModuleManager
         this.compactJSON = compactJSON;
         this.assetSource = assetSource;
         this.classpathScanner = classpathScanner;
-        this.globalCallbacks = globalCallbacks;
         this.productionMode = productionMode;
         this.resourceChangeTracker = resourceChangeTracker;
+        
+        baseCallbacks = new ArrayList<>();
+        globalPerRequestCallbacks = new ArrayList<>();
+        
+        for (EsModuleManagerContribution contribution : contributions) 
+        {
+            if (contribution.isBase())
+            {
+                baseCallbacks.add(contribution.getCallback());
+            }
+            else
+            {
+                globalPerRequestCallbacks.add(contribution.getCallback());
+            }
+        }
+        
         importMap = new JSONObject();
 
         extensions = CollectionFactory.newSet("js");
@@ -114,12 +131,14 @@ public class EsModuleManagerImpl implements 
EsModuleManager
             imports.put(name, cache.get(name));
         }
         
-        this.importMap = executeCallbacks(importMap, globalCallbacks);
+        executeCallbacks(importMap, baseCallbacks);
         
         for (String id : imports.keySet()) 
         {
             cache.put(id, imports.getString(id));
         }
+        
+        this.importMap = importMap;
             
     }
 
@@ -145,12 +164,6 @@ public class EsModuleManagerImpl implements EsModuleManager
         }
     }
 
-    @PostInjection
-    public void setupInvalidation(ResourceChangeTracker tracker)
-    {
-        
-    }
-
     @Override
     public void writeImportMap(Element head, 
List<EsModuleConfigurationCallback> moduleConfigurationCallbacks) {
         
@@ -160,7 +173,8 @@ public class EsModuleManagerImpl implements EsModuleManager
         JSONObject newImportMap = new JSONObject(
                 EsModuleConfigurationCallback.IMPORTS_ATTRIBUTE, imports);
         
-        newImportMap = executeCallbacks(newImportMap, 
moduleConfigurationCallbacks);
+        executeCallbacks(newImportMap, moduleConfigurationCallbacks);
+        executeCallbacks(newImportMap, globalPerRequestCallbacks);
         
         head.element("script")
                 .attribute("type", "importmap")
@@ -332,14 +346,12 @@ public class EsModuleManagerImpl implements 
EsModuleManager
         script.attribute("type", "module");
     }
 
-    private JSONObject executeCallbacks(JSONObject importMap, 
List<EsModuleConfigurationCallback> callbacks) 
+    private void executeCallbacks(JSONObject importMap, 
List<EsModuleConfigurationCallback> callbacks) 
     {
         for (EsModuleConfigurationCallback callback : callbacks) 
         {
             callback.configure(importMap);
         }
-        
-        return importMap;
     }
 
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleConfigurationCallback.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleConfigurationCallback.java
index eb0e6adf9..2916b6374 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleConfigurationCallback.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleConfigurationCallback.java
@@ -13,6 +13,7 @@
 package org.apache.tapestry5.services.javascript;
 
 import org.apache.tapestry5.json.JSONObject;
+import 
org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
 
 /**
  * Interface used to  to change the JSON configuration object which will be 
used in the
@@ -59,4 +60,31 @@ public interface EsModuleConfigurationCallback
     {
         object.in(IMPORTS_ATTRIBUTE).put(id, url);
     }
+    
+    /**
+     * Creates a base contribution (one that contributes a callback used 
+     * when creating the base import map to be used for all requests).
+     * Utility method to call {@linkplain 
EsModuleManagerContribution#base(EsModuleConfigurationCallback)}
+     * @param callback an {@linkplain EsModuleConfigurationCallback} instance.
+     * @return a corresponding {@linkplain EsModuleManagerContribution}.
+     */
+    public static EsModuleManagerContribution 
toBaseContribution(EsModuleConfigurationCallback callback)
+    {
+        return EsModuleManagerContribution.base(callback);
+    }
+    
+    /**
+     * Creates a global per-request contribution (one that contributes a 
callback used 
+     * in all requests after the callbacks added through 
+     * {@linkplain 
JavaScriptSupport#addEsModuleConfigurationCallback(EsModuleConfigurationCallback)}
 
+     * were called).
+     * Utility method to call {@linkplain 
EsModuleManagerContribution#globalPerRequest(EsModuleConfigurationCallback)}
+     * @param callback an {@linkplain EsModuleConfigurationCallback} instance.
+     * @return a corresponding {@linkplain EsModuleManagerContribution}.
+     */
+    public static EsModuleManagerContribution 
toGlobalPerRequestContribution(EsModuleConfigurationCallback callback)
+    {
+        return EsModuleManagerContribution.globalPerRequest(callback);
+    }
+    
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
index 19cfec30b..70a3b00b0 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
@@ -16,6 +16,7 @@ import java.util.List;
 
 import org.apache.tapestry5.dom.Element;
 import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
+import 
org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
 
 /**
  * Responsible for managing access to the ES modules. This service's 
distributed
@@ -25,7 +26,7 @@ import 
org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
  * @since 5.10.0
  * @see EsModuleConfigurationCallback
  */
-@UsesOrderedConfiguration(EsModuleConfigurationCallback.class)
+@UsesOrderedConfiguration(EsModuleManagerContribution.class)
 public interface EsModuleManager
 {
     /**
@@ -53,5 +54,59 @@ public interface EsModuleManager
      *         specify initialization on the page, based on loading modules, 
extacting functions from modules, and invoking those functions
      */
     void writeImports(Element root, List<EsModuleInitialization> inits);
+    
+    /**
+     * Encapsulates a contribution to {@linkplain EsModuleManager}.
+     *
+     * @since 5.10.0
+     * @see EsModuleManager
+     * @see EsModuleConfigurationCallback
+     */
+    public final class EsModuleManagerContribution
+    {
+        private final EsModuleConfigurationCallback callback;
+        
+        private final boolean isBase;
+
+        EsModuleManagerContribution(EsModuleConfigurationCallback callback, 
boolean isBase) 
+        {
+            super();
+            this.callback = callback;
+            this.isBase = isBase;
+        }
+        
+        /**
+         * Creates a base contribution (one that contributes a callback used 
+         * when creating the base import map to be used for all requests).
+         * @param callback an {@linkplain EsModuleConfigurationCallback} 
instance.
+         * @return a corresponding {@linkplain EsModuleManagerContribution}.
+         */
+        public static EsModuleManagerContribution 
base(EsModuleConfigurationCallback callback) 
+        {
+            return new EsModuleManagerContribution(callback, true);
+        }
+
+        /**
+         * Creates a global per-request contribution (one that contributes a 
callback used 
+         * in all requests after the callbacks added through 
+         * {@linkplain 
JavaScriptSupport#addEsModuleConfigurationCallback(EsModuleConfigurationCallback)}
 
+         * were called).
+         * @param callback an {@linkplain EsModuleConfigurationCallback} 
instance.
+         * @return a corresponding {@linkplain EsModuleManagerContribution}.
+         */
+        public static EsModuleManagerContribution 
globalPerRequest(EsModuleConfigurationCallback callback) 
+        {
+            return new EsModuleManagerContribution(callback, false);
+        }
+        
+        public EsModuleConfigurationCallback getCallback() {
+            return callback;
+        }
+        
+        public boolean isBase() {
+            return isBase;
+        }
+
+    }
 
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
index 786d9ce0b..aeb433496 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
@@ -12,10 +12,13 @@
 
 package org.apache.tapestry5.integration.app1;
 
+
 import static 
org.apache.tapestry5.integration.app1.services.AppModule.NON_OVERRIDDEN_ES_MODULE_ID;
 import static 
org.apache.tapestry5.integration.app1.services.AppModule.NON_OVERRIDDEN_ES_MODULE_URL;
 import static 
org.apache.tapestry5.integration.app1.services.AppModule.OVERRIDDEN_ES_MODULE_ID;
 import static 
org.apache.tapestry5.integration.app1.services.AppModule.OVERRIDDEN_ES_MODULE_NEW_URL;
+import static 
org.apache.tapestry5.integration.app1.services.AppModule.OVERRIDDEN_GLOBALLY_ES_MODULE_ID;
+import static 
org.apache.tapestry5.integration.app1.services.AppModule.OVERRIDDEN_GLOBALLY_ES_MODULE_NEW_URL;
 
 import org.apache.tapestry5.annotations.Import;
 import org.apache.tapestry5.integration.app1.pages.EsModuleDemo;
@@ -83,6 +86,11 @@ public class EsModuleTests extends App1TestCase
         JSONObject importMap = getImportMap();
         assertModuleUrl(NON_OVERRIDDEN_ES_MODULE_ID, 
NON_OVERRIDDEN_ES_MODULE_URL, importMap);
         assertModuleUrl(OVERRIDDEN_ES_MODULE_ID, 
EsModuleDemo.REQUEST_OVERRIDEN_MODULE_URL, importMap);
+
+        // Module first defined through callback added to JavaScriptSupport,
+        // then overriden by a global per-request callback.
+        assertModuleUrl(OVERRIDDEN_GLOBALLY_ES_MODULE_ID, 
OVERRIDDEN_GLOBALLY_ES_MODULE_NEW_URL, importMap);
+
         
         // Now without import map changed by request callbacks, so we can test
         // the global import map wasn't affected.
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
index 49c38710d..e6eb761e3 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
@@ -79,6 +79,11 @@ public class EsModuleDemo
                             AppModule.OVERRIDDEN_ES_MODULE_ID, 
REQUEST_OVERRIDEN_MODULE_URL));
         }
         
+        javaScriptSupport.addEsModuleConfigurationCallback(
+                o -> EsModuleConfigurationCallback.setImport(o, 
+                        AppModule.OVERRIDDEN_GLOBALLY_ES_MODULE_ID, 
+                            
AppModule.OVERRIDDEN_GLOBALLY_ES_MODULE_ORIGINAL_URL));
+        
     }
 
     void onActivate(boolean overrideEsModuleImportAgain)
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 e8b91f4d0..d067f8cac 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
@@ -14,6 +14,9 @@ package org.apache.tapestry5.integration.app1.services;
 import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static 
org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback.setImport;
+import static 
org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback.toBaseContribution;
+import static 
org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback.toGlobalPerRequestContribution;
 
 import java.io.IOException;
 import java.lang.annotation.Documented;
@@ -60,6 +63,7 @@ import org.apache.tapestry5.services.ResourceDigestGenerator;
 import org.apache.tapestry5.services.ValueEncoderFactory;
 import org.apache.tapestry5.services.ValueLabelProvider;
 import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
+import 
org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
 import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService;
 import org.apache.tapestry5.services.pageload.PagePreloader;
 import org.apache.tapestry5.services.pageload.PreloaderMode;
@@ -488,32 +492,48 @@ public class AppModule
     public static final String OVERRIDDEN_ES_MODULE_ORIGINAL_URL = 
"/originalURL";
     
     public static final String OVERRIDDEN_ES_MODULE_NEW_URL = "/overridenURL";
+
+    public static final String OVERRIDDEN_GLOBALLY_ES_MODULE_ID = 
"globallyPerRequestOverriden";
+
+    public static final String OVERRIDDEN_GLOBALLY_ES_MODULE_ORIGINAL_URL = 
"/globallyPerRequestOverridenOriginalURL";
+    
+    public static final String OVERRIDDEN_GLOBALLY_ES_MODULE_NEW_URL = 
"/globallyPerRequestOverridenURL";
+    
     
     public static void contributeEsModuleManager(
-            OrderedConfiguration<EsModuleConfigurationCallback> configuration,
+            OrderedConfiguration<EsModuleManagerContribution> configuration,
             AssetSource assetSource)
     {
-        final String original = "OriginalCallback";
-        final String override = "OverrideCallback";
+        final String originalId = "OriginalCallback";
+        final String overrideId = "OverrideCallback";
         
-        configuration.add(override, 
-                o -> EsModuleConfigurationCallback.setImport(o, 
OVERRIDDEN_ES_MODULE_ID, OVERRIDDEN_ES_MODULE_NEW_URL),
-                "after:" + original);
+        configuration.add(overrideId, 
+                toBaseContribution(o -> setImport(o, OVERRIDDEN_ES_MODULE_ID, 
OVERRIDDEN_ES_MODULE_NEW_URL)),
+                "after:" + originalId);
+        
+        configuration.add(originalId, 
+                toBaseContribution(
+                    o -> { 
+                        setImport(o, NON_OVERRIDDEN_ES_MODULE_ID, 
NON_OVERRIDDEN_ES_MODULE_URL);
+                        setImport(o, OVERRIDDEN_ES_MODULE_ID, 
OVERRIDDEN_ES_MODULE_ORIGINAL_URL);
+                    }));
+        
+        final String outsideMetaInfAssetUrl = assetSource
+                
.getClasspathAsset("/org/apache/tapestry5/integration/app1/es-module-outside-metainf.js")
+                .toClientURL();
+        
+        configuration.add("Outside META-INF", 
+                toBaseContribution(o -> setImport(o, "outside-metainf", 
outsideMetaInfAssetUrl)));
+
+        configuration.add("External URL", toBaseContribution(
+                o -> setImport(o, "external/url", 
"https://example.com/module.js";)));
         
-        configuration.add(original, 
-                o -> { 
-                    EsModuleConfigurationCallback.setImport(o, 
NON_OVERRIDDEN_ES_MODULE_ID, NON_OVERRIDDEN_ES_MODULE_URL);
-                    EsModuleConfigurationCallback.setImport(o, 
OVERRIDDEN_ES_MODULE_ID, OVERRIDDEN_ES_MODULE_ORIGINAL_URL);
-                });
+        configuration.add("Globally per-request overriden", 
+                toGlobalPerRequestContribution(
+                    o -> setImport(o, 
+                            OVERRIDDEN_GLOBALLY_ES_MODULE_ID,
+                            OVERRIDDEN_GLOBALLY_ES_MODULE_NEW_URL)));
         
-        configuration.add("Outside META-INF", o -> 
-            EsModuleConfigurationCallback.setImport(o, "outside-metainf", 
-                    
assetSource.getClasspathAsset("/org/apache/tapestry5/integration/app1/es-module-outside-metainf.js").toClientURL())
-        );
-
-        configuration.add("External URL", o -> 
-            EsModuleConfigurationCallback.setImport(o, "external/url", 
"https://example.com/module.js";)
-        );
 
     }
 

Reply via email to