You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2013/11/04 18:11:06 UTC

git commit: TAP5-2196: RequireJs custom path contribution - via Stacks or JavaScriptSupport

Updated Branches:
  refs/heads/master cb372b908 -> d11b50bc3


TAP5-2196: RequireJs custom path contribution - via Stacks or
JavaScriptSupport

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/d11b50bc
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/d11b50bc
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/d11b50bc

Branch: refs/heads/master
Commit: d11b50bc35d64c49076dd16c589987f7e4753517
Parents: cb372b9
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Mon Nov 4 15:10:43 2013 -0200
Committer: Thiago H. de Paula Figueiredo <th...@apache.org>
Committed: Mon Nov 4 15:10:43 2013 -0200

----------------------------------------------------------------------
 .../TapestryBeanValidationIntegrationTests.java |  2 +-
 .../internal/services/DocumentLinker.java       |  9 ++++
 .../internal/services/DocumentLinkerImpl.java   | 12 +++++-
 .../services/PartialMarkupDocumentLinker.java   |  6 +++
 .../services/ajax/JavaScriptSupportImpl.java    | 27 ++++++++----
 .../services/javascript/ModuleManagerImpl.java  | 15 +++++--
 .../services/javascript/JavaScriptSupport.java  | 10 +++++
 .../javascript/ModuleConfigurationCallback.java | 40 ++++++++++++++++++
 .../services/javascript/ModuleManager.java      |  5 ++-
 .../ModuleConfigurationCallbackTests.groovy     | 32 ++++++++++++++
 .../tapestry5/integration/app1/pages/Index.java |  5 ++-
 .../pages/ModuleConfigurationCallbackDemo.java  | 44 ++++++++++++++++++++
 .../pages/ModuleConfigurationCallbackDemo.tml   |  6 +++
 13 files changed, 198 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
index a83dafa..c4fba7c 100644
--- a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
+++ b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
@@ -18,7 +18,7 @@ import org.apache.tapestry5.test.TapestryTestConfiguration;
 import org.testng.annotations.Test;
 
 @Test(sequential = true, groups = "integration")
-@TapestryTestConfiguration(webAppFolder = "src/test/webapp", browserStartCommand = "*googlechrome")
+@TapestryTestConfiguration(webAppFolder = "src/test/webapp")
 public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
 {
     public static final String AVAILABLE_OPTIONS = "css=.palette-available select";

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinker.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinker.java
index e380160..d8b9a12 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinker.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinker.java
@@ -16,6 +16,7 @@ package org.apache.tapestry5.internal.services;
 
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.services.javascript.InitializationPriority;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.StylesheetLink;
 
 /**
@@ -48,6 +49,14 @@ public interface DocumentLinker
      * Adds a link to load a CSS stylesheet.
      */
     void addStylesheetLink(StylesheetLink stylesheet);
+    
+    /**
+     * Adds a module configuration callback for this request.
+     * 
+     * @param callback a {@link ModuleConfigurationCallback}. It cannot be null.
+     * @since 5.4
+     */
+    void addModuleConfigurationCallback(ModuleConfigurationCallback callback);
 
     /**
      * Adds JavaScript code. The code is collected into a single block that is injected just before the close body tag

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
index 0c41e82..a7cfb78 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
@@ -20,6 +20,7 @@ import org.apache.tapestry5.dom.Node;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.services.javascript.InitializationPriority;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.ModuleManager;
 import org.apache.tapestry5.services.javascript.StylesheetLink;
 
@@ -32,6 +33,8 @@ public class DocumentLinkerImpl implements DocumentLinker
     private final List<String> libraryURLs = CollectionFactory.newList();
 
     private final ModuleInitsManager initsManager = new ModuleInitsManager();
+    
+    private final List<ModuleConfigurationCallback> moduleConfigurationCallbacks = CollectionFactory.newList();
 
     private final List<StylesheetLink> includedStylesheets = CollectionFactory.newList();
 
@@ -218,7 +221,7 @@ public class DocumentLinkerImpl implements DocumentLinker
         // (in <head> or at bottom of <body>). Switching to a module approach gives us a new chance to fix this.
         // Eventually, (nearly) everything will be loaded as modules.
 
-        moduleManager.writeInitialization(body, libraryURLs, initsManager.getSortedInits());
+        moduleManager.writeInitialization(body, libraryURLs, initsManager.getSortedInits(), moduleConfigurationCallbacks);
     }
 
     private static Element createTemporaryContainer(Element headElement, String existingElementName, String otherExistingElement, String newElementName)
@@ -296,4 +299,11 @@ public class DocumentLinkerImpl implements DocumentLinker
 
         container.pop();
     }
+
+    public void addModuleConfigurationCallback(ModuleConfigurationCallback callback)
+    {
+        assert callback != null;
+        moduleConfigurationCallbacks.add(callback);
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
index 7927f20..9cde60c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
@@ -18,6 +18,7 @@ import org.apache.tapestry5.internal.InternalConstants;
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.javascript.InitializationPriority;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.StylesheetLink;
 
 import java.util.List;
@@ -60,6 +61,11 @@ public class PartialMarkupDocumentLinker implements DocumentLinker
     {
         notImplemented("addScript");
     }
+    
+    public void addModuleConfigurationCallback(ModuleConfigurationCallback callback)
+    {
+        notImplemented("moduleConfigurationCallback");
+    }
 
     public void addInitialization(InitializationPriority priority, String moduleName, String functionName, JSONArray arguments)
     {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
index 691872e..bcce095 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
@@ -14,6 +14,13 @@
 
 package org.apache.tapestry5.internal.services.ajax;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.FieldFocusPriority;
@@ -27,14 +34,13 @@ import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.util.IdAllocator;
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
-import org.apache.tapestry5.services.javascript.*;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.tapestry5.services.javascript.Initialization;
+import org.apache.tapestry5.services.javascript.InitializationPriority;
+import org.apache.tapestry5.services.javascript.JavaScriptStack;
+import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
+import org.apache.tapestry5.services.javascript.StylesheetLink;
 
 public class JavaScriptSupportImpl implements JavaScriptSupport
 {
@@ -240,6 +246,11 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
     {
         addScript(InitializationPriority.NORMAL, format, arguments);
     }
+    
+    public void addModuleConfigurationCallback(ModuleConfigurationCallback callback)
+    {
+        linker.addModuleConfigurationCallback(callback);
+    }
 
     public String allocateClientId(ComponentResources resources)
     {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleManagerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleManagerImpl.java
index 99ca34d..fb66c6d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleManagerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleManagerImpl.java
@@ -30,6 +30,7 @@ import org.apache.tapestry5.services.ResponseCompressionAnalyzer;
 import org.apache.tapestry5.services.assets.AssetPathConstructor;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
 import org.apache.tapestry5.services.javascript.JavaScriptModuleConfiguration;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.ModuleManager;
 
 import java.util.List;
@@ -82,10 +83,17 @@ public class ModuleManagerImpl implements ModuleManager
         baseConfig = buildBaseConfig(configuration, !productionMode);
     }
 
-    private String buildRequireJSConfig()
+    private String buildRequireJSConfig(List<ModuleConfigurationCallback> callbacks)
     {
         // This is the part that can vary from one request to another, based on the capabilities of the client.
         JSONObject config =  baseConfig.copy().put("baseUrl", getBaseURL());
+        
+        // TAP5-2196: allow changes to the configuration in a per-request basis.
+        for (ModuleConfigurationCallback callback : callbacks)
+        {
+            config = callback.configure(config);
+            assert config != null;
+        }
 
         return String.format("requirejs.config(%s);\n", config.toString(compactJSON));
     }
@@ -166,14 +174,15 @@ public class ModuleManagerImpl implements ModuleManager
         tracker.clearOnInvalidation(cache);
     }
 
-    public void writeInitialization(Element body, List<String> libraryURLs, List<?> inits)
+    public void writeInitialization(Element body, List<String> libraryURLs, List<?> inits,
+            List<ModuleConfigurationCallback> callbacks)
     {
         Element element = body.element("script", "type", "text/javascript");
 
         // Build it each time because we don't know if the client supports GZip or not, and
         // (in development mode) URLs for some referenced assets could change (due to URLs
         // containing a checksum on the resource content).
-        element.raw(buildRequireJSConfig());
+        element.raw(buildRequireJSConfig(callbacks));
 
         StringBuilder content = new StringBuilder(1000);
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
index 265578c..1b24e1b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
@@ -19,6 +19,7 @@ import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.FieldFocusPriority;
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.internal.services.DocumentLinker;
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.EnvironmentalShadowBuilder;
@@ -256,5 +257,14 @@ public interface JavaScriptSupport
      * @since 5.4
      */
     Initialization require(String moduleName);
+    
+    /**
+     * Adds a module configuration callback for this request.
+     * 
+     * @param callback a {@link ModuleConfigurationCallback}. It cannot be null.
+     * @see DocumentLinker#addModuleConfigurationCallback(ModuleConfigurationCallback)
+     * @since 5.4
+     */
+    void addModuleConfigurationCallback(ModuleConfigurationCallback callback);
 
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleConfigurationCallback.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleConfigurationCallback.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleConfigurationCallback.java
new file mode 100644
index 0000000..aef4ad7
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleConfigurationCallback.java
@@ -0,0 +1,40 @@
+// Copyright 2013 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.services.javascript;
+
+import org.apache.tapestry5.json.JSONObject;
+
+/**
+ * Used to change the configuration object which will be passed to 
+ * <a href="http://requirejs.org/docs/api.html#config">require.config()</a> after it was created
+ * by the {@link ModuleManager} service based on contributed {@link JavaScriptModuleConfiguration}s.
+ * This allows components, pages, mixins and services to configure Require.JS dynamically in a
+ * per-request basis by using the 
+ * {@link JavaScriptSupport#addModuleConfigurationCallback(ModuleConfigurationCallback)} method.
+ *  
+ * @see JavaScriptSupport#addModuleConfigurationCallback(ModuleConfigurationCallback)
+ * @since 5.4
+ */
+public interface ModuleConfigurationCallback
+{
+    /**
+     * Receives the current configuration, changes it it returns it.
+     * 
+     * @param configuration a {@link JSONObject} containing the current configuration.
+     * @return a {@link JSONObject} containing the changed configuration, most probably the same
+     * one received as a parameter. 
+     */
+    JSONObject configure(JSONObject configuration);
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleManager.java
index 6dcf4e9..3469022 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ModuleManager.java
@@ -51,8 +51,11 @@ public interface ModuleManager
      *         (separated by a ':', e.g. "myapp/mymodule:myfunc").
      *         When there are no arguments, the qualified function name may be used; where there are arguments, the
      *         init must be a JSONArray.
+     * @param moduleConfigurationCallbacks a list of {@link ModuleConfigurationCallback}s. It
+     *         cannot be null. 
      */
-    void writeInitialization(Element body, List<String> libraryURLs, List<?> inits);
+    void writeInitialization(Element body, List<String> libraryURLs, List<?> inits,
+            List<ModuleConfigurationCallback> moduleConfigurationCallbacks);
 
     /**
      * Given a module name (which may be a path of names separated by slashes), locates the corresponding {@link Resource}.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
new file mode 100644
index 0000000..fbe9cdb
--- /dev/null
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
@@ -0,0 +1,32 @@
+// Copyright 2013 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
+
+import org.apache.tapestry5.test.TapestryTestConfiguration;
+import org.testng.annotations.Test
+
+@TapestryTestConfiguration(webAppFolder = "src/test/app1", browserStartCommand="*googlechrome")
+class ModuleConfigurationCallbackTests extends App1TestCase {
+
+    @Test
+    void simple() {
+        
+        openLinks "ModuleConfigurationCallback Demo"
+        
+        assert getHtmlSource().contains("\"waitSeconds\" : \"13\"");
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 0145200..d02b560 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -535,7 +535,10 @@ public class Index
 							"Exact"),
 
 					new Item("UnknownActivationContextDemo", "Unknown Activation Context Demo", "Page refuse to serve if called with an unknown activation context (TAP5-2070)",
-							"Unwanted", "context")
+							"Unwanted", "context"),
+                    
+                    new Item("ModuleConfigurationCallbackDemo", "ModuleConfigurationCallback Demo", "Shows an example of changing the Require.js configuration using JavaScriptSupport.addModuleConfigurationDemo()")
+
             );
 
     static

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
new file mode 100644
index 0000000..09deb7c
--- /dev/null
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
@@ -0,0 +1,44 @@
+//  Copyright 2013 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.pages;
+
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
+
+/**
+ * Demonstrates the use of {@link ModuleConfigurationCallback} and
+ * {@link JavaScriptSupport#addModuleConfigurationCallback(ModuleConfigurationCallback)}.
+ * Based on http://www.requirejs.org/jqueryui-amd/example/webapp/app.html.
+ */
+public class ModuleConfigurationCallbackDemo
+{
+
+    @Inject
+    private JavaScriptSupport javaScriptSupport;
+    
+    void afterRender() {
+        javaScriptSupport.addModuleConfigurationCallback(new Callback());
+    }
+
+    private static final class Callback implements ModuleConfigurationCallback
+    {
+        public JSONObject configure(JSONObject configuration)
+        {
+            return configuration.put("waitSeconds", "13");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d11b50bc/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.tml
new file mode 100644
index 0000000..99c5a96
--- /dev/null
+++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.tml
@@ -0,0 +1,6 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+
+<h1>ModuleConfigurationCallback Demo</h1>
+
+
+</html>
\ No newline at end of file