You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/09/11 21:28:41 UTC
git commit: Centralize logic for forcing a reload Add options to the
default ExceptionReport page to jump back to the failed page (w/ optional
reload)
Updated Branches:
refs/heads/master 954c905d0 -> 7419eed30
Centralize logic for forcing a reload
Add options to the default ExceptionReport page to jump back to the failed page (w/ optional reload)
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/7419eed3
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/7419eed3
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/7419eed3
Branch: refs/heads/master
Commit: 7419eed304339bb2ef71aa7e1b28ff10cf91c50c
Parents: 954c905
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Wed Sep 11 12:27:48 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed Sep 11 12:28:32 2013 -0700
----------------------------------------------------------------------
.../tapestry5/corelib/components/DevTool.java | 24 +--
.../corelib/pages/ExceptionReport.java | 60 ++++++-
.../tapestry5/corelib/pages/PageCatalog.java | 33 +---
.../services/ComponentMessagesSourceImpl.java | 36 ++--
.../services/ComponentTemplateSourceImpl.java | 45 +++--
.../internal/services/ForceReload.java | 25 +++
...ternalComponentInvalidationEventHubImpl.java | 17 +-
.../internal/services/MessagesSourceImpl.java | 19 ++-
.../internal/services/ReloadHelper.java | 35 ++++
.../internal/services/ReloadHelperImpl.java | 60 +++++++
.../tapestry5/modules/InternalModule.java | 3 +-
.../tapestry5/corelib/components/DevTool.tml | 2 +-
.../tapestry5/corelib/pages/ExceptionReport.tml | 171 +++++++++++--------
.../tapestry5/corelib/pages/PageCatalog.tml | 12 +-
14 files changed, 388 insertions(+), 154 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
index 470a826..320e1cd 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
@@ -22,7 +22,7 @@ import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
-import org.apache.tapestry5.internal.services.ComponentInstantiatorSource;
+import org.apache.tapestry5.internal.services.ReloadHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.Request;
@@ -33,6 +33,16 @@ import org.apache.tapestry5.services.javascript.JavaScriptSupport;
* Renders a dropdown menu of useful options when developing. By default, the DevTool is disabled (invisible)
* during production.
* <p/>
+ * The DevTool provides the following options:
+ * <ul>
+ * <li>Reset the page state, discarding any persistent page properties</li>
+ * <li>Kill the HttpSession (discarding any server-side state)</li>
+ * <li>Re-render the page (useful after changing the page or template)</li>
+ * <li>Re-render the page with rendering comments</li>
+ * <li>Reload all pages and components: classes, messages, templates</li>
+ * <li>Open the T5 Dashboard page in a new window</li>
+ * </ul>
+ * <p/>
* Note that due to conflicts between Prototype and jQuery, the dev tool is hidden after selecting an item from the menu.
*
* @tapestrydoc
@@ -85,7 +95,7 @@ public class DevTool
private ComponentResources resources;
@Inject
- private ComponentInstantiatorSource componentInstantiatorSource;
+ private ReloadHelper reloadHelper;
public String getZoneElement()
{
@@ -153,15 +163,7 @@ public class DevTool
Object onActionFromReload()
{
- if (productionMode)
- {
- alertManager.error("Forcing a class reload is only allowed when executing in development mode.");
- return null;
- }
-
- componentInstantiatorSource.forceComponentInvalidation();
-
- alertManager.info("Forced a component class reload.");
+ reloadHelper.forceReload();
return devmodezone.getBody();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
index 954d4db..4a2bbc2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2012 The Apache Software Foundation
+// Copyright 2006-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.
@@ -14,17 +14,21 @@
package org.apache.tapestry5.corelib.pages;
+import org.apache.tapestry5.EventContext;
import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.alerts.AlertManager;
import org.apache.tapestry5.annotations.ContentType;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.internal.services.PageActivationContextCollector;
+import org.apache.tapestry5.internal.services.ReloadHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.services.ExceptionReporter;
-import org.apache.tapestry5.services.Request;
-import org.apache.tapestry5.services.Session;
+import org.apache.tapestry5.services.*;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.List;
import java.util.regex.Pattern;
@@ -72,13 +76,61 @@ public class ExceptionReport implements ExceptionReporter
@Property
private String propertyName;
+ @Property
+ private String failurePage;
+
+ @Inject
+ private RequestGlobals requestGlobals;
+
+ @Inject
+ private AlertManager alertManager;
+
+ @Inject
+ private PageActivationContextCollector pageActivationContextCollector;
+
+ @Inject
+ private PageRenderLinkSource linkSource;
+
+ @Inject
+ private BaseURLSource baseURLSource;
+
+ @Inject
+ private ReloadHelper reloadHelper;
+
+ @Property
+ private String rootURL;
+
private final String pathSeparator = System.getProperty(PATH_SEPARATOR_PROPERTY);
public void reportException(Throwable exception)
{
rootException = exception;
+
+ failurePage = request.isXHR() ? null : requestGlobals.getActivePageName();
+
+ rootURL = baseURLSource.getBaseURL(request.isSecure());
+ }
+
+ public Object[] getReloadContext()
+ {
+ return pageActivationContextCollector.collectPageActivationContext(failurePage);
}
+ Object onActionFromReloadFirst(EventContext reloadContext)
+ {
+ reloadHelper.forceReload();
+
+ return linkSource.createPageRenderLinkWithContext(request.getParameter("loadPage"), reloadContext);
+ }
+
+ Object onActionFromReloadRoot() throws MalformedURLException
+ {
+ reloadHelper.forceReload();
+
+ return new URL(baseURLSource.getBaseURL(request.isSecure()));
+ }
+
+
public boolean getHasSession()
{
return request.getSession(false) != null;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
index ff9f66b..9576b47 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
@@ -25,8 +25,8 @@ import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.func.*;
import org.apache.tapestry5.internal.PageCatalogTotals;
-import org.apache.tapestry5.internal.services.ComponentInstantiatorSource;
import org.apache.tapestry5.internal.services.PageSource;
+import org.apache.tapestry5.internal.services.ReloadHelper;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.OperationTracker;
@@ -88,7 +88,7 @@ public class PageCatalog
private OperationTracker operationTracker;
@Inject
- private ComponentInstantiatorSource componentInstantiatorSource;
+ private ReloadHelper reloadHelper;
@Inject
private BeanModelSource beanModelSource;
@@ -156,23 +156,6 @@ public class PageCatalog
return pageSource.getAllPages();
}
- Object onActionFromReloadClasses()
- {
- if (productionMode)
- {
- alertManager.error("Forcing a class reload is only allowed when executing in development mode.");
- return null;
- }
-
- pageName = null;
-
- componentInstantiatorSource.forceComponentInvalidation();
-
- alertManager.info("Forced a component class reload.");
-
- return pagesZone.getBody();
- }
-
Object onSuccessFromSinglePageLoad()
{
boolean found = !F.flow(getPages()).filter(new Predicate<Page>()
@@ -281,20 +264,12 @@ public class PageCatalog
return pagesZone.getBody();
}
- Object onActionFromClearCache()
+ Object onActionFromClearCaches()
{
- if (productionMode)
- {
- alertManager.error("Clearing the cache is only allowed in development mode.");
- return null;
- }
-
- pageSource.clearCache();
+ reloadHelper.forceReload();
failures = null;
- alertManager.info("Page cache cleared.");
-
return pagesZone.getBody();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
index 47837bb..8f0fa00 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
+// Copyright 2006-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.
@@ -14,17 +14,11 @@
package org.apache.tapestry5.internal.services;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.func.Worker;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.PostInjection;
import org.apache.tapestry5.ioc.annotations.Symbol;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.URLChangeTracker;
import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
import org.apache.tapestry5.model.ComponentModel;
@@ -35,9 +29,13 @@ import org.apache.tapestry5.services.messages.PropertiesFileParser;
import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
public class ComponentMessagesSourceImpl implements ComponentMessagesSource, UpdateListener
{
- private final MessagesSource messagesSource;
+ private final MessagesSourceImpl messagesSource;
private final MessagesBundle appCatalogBundle;
@@ -72,20 +70,20 @@ public class ComponentMessagesSourceImpl implements ComponentMessagesSource, Upd
}
public ComponentMessagesSourceImpl(@Symbol(SymbolConstants.PRODUCTION_MODE)
- boolean productionMode, List<Resource> appCatalogResources, PropertiesFileParser parser,
- ComponentResourceLocator resourceLocator, ClasspathURLConverter classpathURLConverter)
+ boolean productionMode, List<Resource> appCatalogResources, PropertiesFileParser parser,
+ ComponentResourceLocator resourceLocator, ClasspathURLConverter classpathURLConverter)
{
this(productionMode, appCatalogResources, resourceLocator, parser, new URLChangeTracker(classpathURLConverter));
}
ComponentMessagesSourceImpl(boolean productionMode, Resource appCatalogResource,
- ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
+ ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
{
this(productionMode, Arrays.asList(appCatalogResource), resourceLocator, parser, tracker);
}
ComponentMessagesSourceImpl(boolean productionMode, List<Resource> appCatalogResources,
- ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
+ ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
{
messagesSource = new MessagesSourceImpl(productionMode, productionMode ? null : tracker, resourceLocator,
parser);
@@ -93,6 +91,18 @@ public class ComponentMessagesSourceImpl implements ComponentMessagesSource, Upd
appCatalogBundle = createAppCatalogBundle(appCatalogResources);
}
+ @PostInjection
+ public void setupReload(ReloadHelper reloadHelper)
+ {
+ reloadHelper.addReloadCallback(new Runnable()
+ {
+ public void run()
+ {
+ messagesSource.invalidate();
+ }
+ });
+ }
+
public void checkForUpdates()
{
messagesSource.checkForUpdates();
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
index bbf7ed9..d651625 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
+// Copyright 2006-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.
@@ -14,11 +14,6 @@
package org.apache.tapestry5.internal.services;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.TapestryConstants;
import org.apache.tapestry5.internal.event.InvalidationEventHubImpl;
@@ -41,6 +36,11 @@ import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
import org.apache.tapestry5.services.templates.ComponentTemplateLocator;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
/**
* Service implementation that manages a cache of parsed component templates.
*/
@@ -99,15 +99,15 @@ public final class ComponentTemplateSourceImpl extends InvalidationEventHubImpl
};
public ComponentTemplateSourceImpl(@Inject
- @Symbol(SymbolConstants.PRODUCTION_MODE)
- boolean productionMode, TemplateParser parser, ComponentResourceLocator locator,
- ClasspathURLConverter classpathURLConverter)
+ @Symbol(SymbolConstants.PRODUCTION_MODE)
+ boolean productionMode, TemplateParser parser, ComponentResourceLocator locator,
+ ClasspathURLConverter classpathURLConverter)
{
this(productionMode, parser, locator, new URLChangeTracker(classpathURLConverter));
}
ComponentTemplateSourceImpl(boolean productionMode, TemplateParser parser, ComponentResourceLocator locator,
- URLChangeTracker tracker)
+ URLChangeTracker tracker)
{
super(productionMode);
@@ -122,6 +122,18 @@ public final class ComponentTemplateSourceImpl extends InvalidationEventHubImpl
hub.addUpdateListener(this);
}
+ @PostInjection
+ public void setupReload(ReloadHelper helper)
+ {
+ helper.addReloadCallback(new Runnable()
+ {
+ public void run()
+ {
+ invalidate();
+ }
+ });
+ }
+
public ComponentTemplate getTemplate(ComponentModel componentModel, ComponentResourceSelector selector)
{
String componentName = componentModel.getComponentClassName();
@@ -206,13 +218,18 @@ public final class ComponentTemplateSourceImpl extends InvalidationEventHubImpl
{
if (tracker.containsChanges())
{
- tracker.clear();
- templateResources.clear();
- templates.clear();
- fireInvalidationEvent();
+ invalidate();
}
}
+ private void invalidate()
+ {
+ tracker.clear();
+ templateResources.clear();
+ templates.clear();
+ fireInvalidationEvent();
+ }
+
public InvalidationEventHub getInvalidationEventHub()
{
return this;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ForceReload.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ForceReload.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ForceReload.java
new file mode 100644
index 0000000..2cb7ba1
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ForceReload.java
@@ -0,0 +1,25 @@
+// 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.internal.services;
+
+/**
+ * Forces a reload of all caches and invalidates the component class cache. This is only allowed
+ *
+ * @since 5.4
+ */
+public interface ForceReload
+{
+ boolean forceReload();
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java
index 2c52c31..fe43063 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalComponentInvalidationEventHubImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2011 The Apache Software Foundation
+// Copyright 2011-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.
@@ -16,17 +16,30 @@ package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.event.InvalidationEventHubImpl;
+import org.apache.tapestry5.ioc.annotations.PostInjection;
import org.apache.tapestry5.ioc.annotations.Symbol;
public class InternalComponentInvalidationEventHubImpl extends InvalidationEventHubImpl implements
InternalComponentInvalidationEventHub
{
public InternalComponentInvalidationEventHubImpl(@Symbol(SymbolConstants.PRODUCTION_MODE)
- boolean productionMode)
+ boolean productionMode)
{
super(productionMode);
}
+ @PostInjection
+ public void setupReload(ReloadHelper helper)
+ {
+ helper.addReloadCallback(new Runnable()
+ {
+ public void run()
+ {
+ fireInvalidationEvent();
+ }
+ });
+ }
+
public void classInControlledPackageHasChanged()
{
fireInvalidationEvent();
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MessagesSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MessagesSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MessagesSourceImpl.java
index 119bee6..e2238e7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MessagesSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MessagesSourceImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2010, 2011, 2012 The Apache Software Foundation
+// Copyright 2006-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.
@@ -83,14 +83,19 @@ public class MessagesSourceImpl extends InvalidationEventHubImpl implements Mess
{
if (tracker != null && tracker.containsChanges())
{
- messagesByBundleIdAndSelector.clear();
- cookedProperties.clear();
- rawProperties.clear();
+ invalidate();
+ }
+ }
- tracker.clear();
+ public void invalidate()
+ {
+ messagesByBundleIdAndSelector.clear();
+ cookedProperties.clear();
+ rawProperties.clear();
- fireInvalidationEvent();
- }
+ tracker.clear();
+
+ fireInvalidationEvent();
}
public Messages getMessages(MessagesBundle bundle, ComponentResourceSelector selector)
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelper.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelper.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelper.java
new file mode 100644
index 0000000..53b44ec
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelper.java
@@ -0,0 +1,35 @@
+// 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.internal.services;
+
+/**
+ * Forces a reload of all caches and invalidates the component class cache. This is only allowed
+ *
+ * @since 5.4
+ */
+public interface ReloadHelper
+{
+ /**
+ * Force a reload (if in production mode). Writes an {@link org.apache.tapestry5.alerts.AlertManager} alert message.
+ */
+ void forceReload();
+
+ /**
+ * Adds a callback to be invoked from {@link #forceReload()}.
+ *
+ * @param callback
+ */
+ void addReloadCallback(Runnable callback);
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelperImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelperImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelperImpl.java
new file mode 100644
index 0000000..d2c669d
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ReloadHelperImpl.java
@@ -0,0 +1,60 @@
+// 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.internal.services;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.alerts.AlertManager;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+import java.util.List;
+
+public class ReloadHelperImpl implements ReloadHelper
+{
+ private final AlertManager alertManager;
+
+ private final boolean productionMode;
+
+ private final List<Runnable> callbacks = CollectionFactory.newThreadSafeList();
+
+ public ReloadHelperImpl(AlertManager alertManager, @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode)
+ {
+ this.alertManager = alertManager;
+ this.productionMode = productionMode;
+ }
+
+ public void forceReload()
+ {
+ if (productionMode)
+ {
+ alertManager.error("Can not force a reload in production mode.");
+ return;
+ }
+
+ for (Runnable c : callbacks)
+ {
+ c.run();
+ }
+
+ alertManager.info("Component classes, templates, and messages reloaded.");
+ }
+
+ public void addReloadCallback(Runnable callback)
+ {
+ assert callback != null;
+
+ callbacks.add(callback);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
index f5e190b..5067a33 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
@@ -69,7 +69,8 @@ public class InternalModule
binder.bind(InternalComponentInvalidationEventHub.class);
binder.bind(PageSource.class, PageSourceImpl.class);
binder.bind(PageLoader.class, PageLoaderImpl.class).preventReloading();
- binder.bind(UnknownActivationContextHandler.class, UnknownActivationContextHandlerImpl.class);
+ binder.bind(UnknownActivationContextHandler.class, UnknownActivationContextHandlerImpl.class);
+ binder.bind(ReloadHelper.class, ReloadHelperImpl.class);
}
public static CookieSource buildCookieSource(final RequestGlobals requestGlobals)
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DevTool.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DevTool.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DevTool.tml
index 6142748..3e073c3 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DevTool.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/DevTool.tml
@@ -28,7 +28,7 @@
<li class="divider"/>
<t:if test="!productionMode">
<li>
- <t:actionlink zone="^" t:id="reload">Reload Component Classes</t:actionlink>
+ <t:actionlink zone="^" t:id="reload">Reload All Pages</t:actionlink>
</li>
</t:if>
<li>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
index abac44b..1ae084c 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
@@ -1,79 +1,116 @@
<html xml:space="default" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter">
-<head>
- <title>Application Exception</title>
-</head>
-<body>
-<div class="navbar navbar-inverse navbar-fixed-top">
- <div class="container">
- <div class="navbar-header">
- <ul class="nav navbar-nav">
- <li>
- <h4 class="navbar-text">Application Exception</h4>
- </li>
- <li class="divider-vertical"/>
- <li>
- <p class="navbar-text">
- Tapestry Version: ${tapestryVersion}
- </p>
- </li>
- <li class="divider-vertical"/>
- <li>
- <p class="navbar-text">
- Application Version: ${applicationVersion}
- </p>
- </li>
- </ul>
+ <head>
+ <title>Application Exception</title>
+ </head>
+ <body>
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <ul class="nav navbar-nav">
+ <li>
+ <h4 class="navbar-text">Application Exception</h4>
+ </li>
+ <li class="divider-vertical"/>
+ <li>
+ <p class="navbar-text">
+ Tapestry Version: ${tapestryVersion}
+ </p>
+ </li>
+ <li class="divider-vertical"/>
+ <li>
+ <p class="navbar-text">
+ Application Version: ${applicationVersion}
+ </p>
+ </li>
+ </ul>
+ </div>
+ </div>
</div>
- </div>
-</div>
-<div class="container">
+ <div class="container">
- <div class="alert alert-danger">
- <h2>An exception has occurred processing this request.</h2>
+ <div class="panel panel-danger">
+ <div class="panel-heading">
+ <h2 class="panel-title">An exception has occurred processing this request.</h2>
+ </div>
+ <div class="panel-body">
+ ${rootException.message}
+ </div>
+ <t:if test="! productionMode">
- <p>${rootException.message}</p>
- </div>
+ <div class="panel-footer">
- <t:if test="! productionMode">
+ <div class="btn-toolbar col-md-12">
- <t:exceptiondisplay exception="rootException"/>
+ <t:if test="failurePage">
+ <t:pagelink page="prop:failurePage" class="btn btn-default">Go to page
+ <strong>${failurePage}</strong>
+ </t:pagelink>
+ <t:actionlink t:id="reloadFirst" parameters="{'loadPage': failurePage}"
+ context="reloadContext" class="btn btn-default">Go to page
+ <strong>${failurePage}</strong>
+ (with reload)
+ </t:actionlink>
+ </t:if>
+ <a href="/" class="btn btn-default">Go to
+ <strong>${rootURL}</strong>
+ </a>
+ <t:actionLink t:id="reloadRoot" class="btn btn-default">
+ Go to
+ <strong>${rootURL}</strong>
+ (with reload)
+ </t:actionLink>
+ </div>
+ </div>
+ </t:if>
+ </div>
- <h3>Request</h3>
- <t:renderobject object="request"/>
+ <t:if test="! productionMode">
- <t:if test="hasSession">
- <h2>Session</h2>
- <dl>
- <t:loop source="session.attributeNames" value="attributeName">
- <dt>${attributeName}</dt>
- <dd>
- <t:renderobject object="attributeValue"/>
- </dd>
- </t:loop>
- </dl>
- </t:if>
+ <p class="help-text col-md-12"><strong>with reload</strong>: Force a reload of component
+ classes. This is
+ often
+ necessary
+ after fixing a class that previously failed to compile due to errors.
+ </p>
- <h3>System Properties</h3>
- <dl>
- <t:loop source="systemProperties" value="propertyName">
- <dt>${propertyName}</dt>
- <dd>
- <t:if test="! complexProperty">
- ${propertyValue}
- <p:else>
- <ul>
- <li t:type="loop" source="complexPropertyValue" value="var:path">
- ${var:path}
- </li>
- </ul>
- </p:else>
- </t:if>
- </dd>
- </t:loop>
- </dl>
- </t:if>
-</div>
-</body>
+ <t:exceptiondisplay exception="rootException"/>
+
+ <h3>Request</h3>
+ <t:renderobject object="request"/>
+
+ <t:if test="hasSession">
+ <h2>Session</h2>
+ <dl>
+ <t:loop source="session.attributeNames" value="attributeName">
+ <dt>${attributeName}</dt>
+ <dd>
+ <t:renderobject object="attributeValue"/>
+ </dd>
+ </t:loop>
+ </dl>
+ </t:if>
+
+ <h3>System Properties</h3>
+ <dl>
+ <t:loop source="systemProperties" value="propertyName">
+ <dt>${propertyName}</dt>
+ <dd>
+ <t:if test="! complexProperty">
+ ${propertyValue}
+ <p:else>
+ <ul>
+ <li t:type="loop" source="complexPropertyValue" value="var:path">
+ ${var:path}
+ </li>
+ </ul>
+ </p:else>
+ </t:if>
+ </dd>
+ </t:loop>
+ </dl>
+ </t:if>
+ </div>
+ </body>
</html>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/7419eed3/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
index 65651ff..5e7c7a2 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
@@ -19,8 +19,10 @@
${page.selector.toShortString()}
</p:selectorCell>
<p:empty>
- <p><em>There are no pages in the page cache. This can only occur immediately after reloading all
- component classes or clearing the cache.</em></p>
+ <p>
+ <em>There are no pages in the page cache. This can only occur immediately after clearing the cache.
+ </em>
+ </p>
</p:empty>
</t:grid>
@@ -30,8 +32,7 @@
<div class="btn-group">
<t:actionlink t:id="forceLoad" zone="pages" class="btn btn-default">Load all pages</t:actionlink>
<t:if test="! productionMode">
- <t:actionlink t:id="clearCache" zone="pages" class="btn btn-default">Clear the cache</t:actionlink>
- <t:actionlink t:id="reloadClasses" zone="pages" class="btn btn-default">Reload component classes
+ <t:actionlink t:id="clearCaches" zone="pages" class="btn btn-default">Clear Caches
</t:actionlink>
</t:if>
<t:actionlink t:id="runGC" zone="pages" class="btn btn-default">Run the GC</t:actionlink>
@@ -59,7 +60,8 @@
<div class="panel panel-default">
<div class="panel-heading">
- <h3 class="panel-title">Key</h3></div>
+ <h3 class="panel-title">Key</h3>
+ </div>
<div class="panel-body">
<dl class="dl-horizontal">