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 2008/01/29 01:11:03 UTC

svn commit: r616118 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ tapestry-core/src/main/java/org/apache/tapestry/runtime/ tapestry...

Author: hlship
Date: Mon Jan 28 16:11:01 2008
New Revision: 616118

URL: http://svn.apache.org/viewvc?rev=616118&view=rev
Log:
TAPESTRY-2097: Render exceptions should identify the components that are actively rendering

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueException.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/RenderErrorDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/RenderErrorDemo.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/runtime/RenderQueue.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RenderQueueImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueException.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueException.java?rev=616118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueException.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueException.java Mon Jan 28 16:11:01 2008
@@ -0,0 +1,34 @@
+// Copyright 2008 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.tapestry.internal.services;
+
+import org.apache.tapestry.ioc.internal.util.TapestryException;
+
+public class RenderQueueException extends TapestryException
+{
+    private final Object[] _activeComponentIds;
+
+    public RenderQueueException(String message, Object[] activeComponentIds, Throwable cause)
+    {
+        super(message, cause);
+
+        _activeComponentIds = activeComponentIds;
+    }
+
+    public Object[] getActiveComponentIds()
+    {
+        return _activeComponentIds;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueImpl.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RenderQueueImpl.java Mon Jan 28 16:11:01 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -15,6 +15,7 @@
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.ioc.internal.util.Defense;
 import org.apache.tapestry.ioc.util.Stack;
 import org.apache.tapestry.runtime.RenderCommand;
 import org.apache.tapestry.runtime.RenderQueue;
@@ -26,6 +27,8 @@
 
     private final Stack<RenderCommand> _queue = new Stack<RenderCommand>(INITIAL_QUEUE_DEPTH);
 
+    private final Stack<String> _nestedIds = new Stack<String>(INITIAL_QUEUE_DEPTH);
+
     private final Logger _logger;
 
     public RenderQueueImpl(Logger logger)
@@ -63,9 +66,23 @@
             // This will likely leave the page in a dirty state, and it will not go back into the
             // page pool.
 
-            _logger.error(ServicesMessages.renderQueueError(command, ex), ex);
+            String message = ServicesMessages.renderQueueError(command, ex);
+
+            _logger.error(message, ex);
 
-            throw ex;
+            throw new RenderQueueException(message, _nestedIds.getSnapshot(), ex);
         }
+    }
+
+    public void startComponent(String componentId)
+    {
+        Defense.notBlank(componentId, "componentId");
+
+        _nestedIds.push(componentId);
+    }
+
+    public void endComponent()
+    {
+        _nestedIds.pop();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Mon Jan 28 16:11:01 2008
@@ -52,6 +52,17 @@
  */
 public class ComponentPageElementImpl extends BaseLocatable implements ComponentPageElement, PageLifecycleListener
 {
+    /**
+     * @see #render(org.apache.tapestry.MarkupWriter, org.apache.tapestry.runtime.RenderQueue)
+     */
+    private static final RenderCommand POP_COMPONENT_ID = new RenderCommand()
+    {
+        public void render(MarkupWriter writer, RenderQueue queue)
+        {
+            queue.endComponent();
+        }
+    };
+
     private static final ComponentCallback CONTAINING_PAGE_DID_ATTACH = new ComponentCallback()
     {
         public void run(Component component)
@@ -892,6 +903,7 @@
         return String.format("%s[%s]", phaseName, _completeId);
     }
 
+
     /**
      * Pushes the SetupRender phase state onto the queue.
      */
@@ -903,6 +915,10 @@
         // Once we start rendering, the page is considered dirty, until we cleanup post render.
 
         _page.incrementDirtyCount();
+
+        queue.startComponent(_completeId);
+
+        queue.push(POP_COMPONENT_ID);
 
         queue.push(_setupRender);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/runtime/RenderQueue.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/runtime/RenderQueue.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/runtime/RenderQueue.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/runtime/RenderQueue.java Mon Jan 28 16:11:01 2008
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2008 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.
@@ -15,8 +15,8 @@
 package org.apache.tapestry.runtime;
 
 /**
- * A stateful object that manages the process of rendering a page. Rending a page in Tapestry is
- * based on a command queue.
+ * A stateful object that manages the process of rendering a page. Rending a page in Tapestry is based on a command
+ * queue.
  */
 public interface RenderQueue
 {
@@ -24,4 +24,18 @@
      * Adds the new command to the front of the queue.
      */
     void push(RenderCommand command);
+
+    /**
+     * Indicates that a component is starting its render. A stack of active component ids is used for exception
+     * reporting.
+     *
+     * @param componentId of component that is rendering
+     */
+    void startComponent(String componentId);
+
+    /**
+     * Corresponds to {@link #startComponent(String)}, used to denote when the most recently started component finishes
+     * rendering.
+     */
+    void endComponent();
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/RenderErrorDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/RenderErrorDemo.tml?rev=616118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/RenderErrorDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/RenderErrorDemo.tml Mon Jan 28 16:11:01 2008
@@ -0,0 +1,9 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+    <h1>Render Error Demo</h1>
+
+    <p>This page will not completely render, it gets an exception.</p>
+
+    <t:Echo value="value"/>
+
+</html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Mon Jan 28 16:11:01 2008
@@ -1522,4 +1522,21 @@
 
         assertSourcePresent("<ul><li>1</li><li>3</li><li>5</li><li>7</li><li>9</li></ul>");
     }
+
+    /**
+     * TAPESTRY-2097
+     */
+    @Test
+    public void render_queue_exception()
+    {
+        start("Render Error Demo");
+
+        assertTextPresent("An unexpected application exception has occurred");
+
+        for (String s : new String[]{"RenderErrorDemo", "RenderErrorDemo:border", "RenderErrorDemo:echo"})
+        {
+            assertSourcePresent(String.format("<li>%s</li>", s));
+        }
+
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/RenderErrorDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/RenderErrorDemo.java?rev=616118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/RenderErrorDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/RenderErrorDemo.java Mon Jan 28 16:11:01 2008
@@ -0,0 +1,24 @@
+// Copyright 2008 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.tapestry.integration.app1.pages;
+
+public class RenderErrorDemo
+{
+    public Object getValue()
+    {
+        throw new RuntimeException("Exception thrown from getValue().");
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java Mon Jan 28 16:11:01 2008
@@ -61,6 +61,8 @@
     private static final List<Item> ITEMS = CollectionFactory.newList(
             new Item("actionpage", "Action Page", "tests fixture for ActionLink component"),
 
+            new Item("RenderErrorDemo", "Render Error Demo", "reporting of errors while rendering"),
+
             new Item("nested/AssetDemo", "AssetDemo", "declaring an image using Assets"),
 
             new Item("blockdemo", "BlockDemo", "use of blocks to control rendering"),

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RenderQueueImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RenderQueueImplTest.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RenderQueueImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RenderQueueImplTest.java Mon Jan 28 16:11:01 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -84,6 +84,11 @@
 
         RenderQueueImpl queue = new RenderQueueImpl(logger);
 
+        queue.startComponent("foo");
+        queue.startComponent("bar");
+        queue.endComponent();
+        queue.startComponent("baz");
+
         queue.push(rc);
 
         try
@@ -91,9 +96,11 @@
             queue.run(writer);
             unreachable();
         }
-        catch (RuntimeException ex)
+        catch (RenderQueueException ex)
         {
-            assertSame(ex, t);
+            assertSame(ex.getCause(), t);
+
+            assertArraysEqual(ex.getActiveComponentIds(), new String[]{"foo", "baz"});
         }
 
         verify();

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java Mon Jan 28 16:11:01 2008
@@ -17,11 +17,9 @@
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 
 /**
- * A simple, streamlined implementation of {@link java.util.Stack}. The implementation is
- * <em>not</em> threadsafe.
+ * A simple, streamlined implementation of {@link java.util.Stack}. The implementation is <em>not</em> threadsafe.
  *
- * @param <E>
- * the type of elements stored in the map
+ * @param <E> the type of elements stored in the map
  * @see CollectionFactory#newStack()
  */
 public class Stack<E>
@@ -43,8 +41,8 @@
     }
 
     /**
-     * @param initialSize the initial size of the internal array (which will be expanded as necessary). For
-     *                    best efficiency, set this to the maximum depth of the stack.
+     * @param initialSize the initial size of the internal array (which will be expanded as necessary). For best
+     *                    efficiency, set this to the maximum depth of the stack.
      */
     public Stack(int initialSize)
     {
@@ -147,5 +145,21 @@
         builder.append("]");
 
         return builder.toString();
+    }
+
+    /**
+     * Returns a snapshot of the current state of the stack as an array of objects. The first object is the deepest in
+     * the stack, the last object is the most shallowest (most recently pushed onto the stack).  The returned array may
+     * be manipulated (it is a copy).
+     *
+     * @return the stack as an object array
+     */
+    public Object[] getSnapshot()
+    {
+        Object[] result = new Object[_index + 1];
+
+        System.arraycopy(_items, 0, result, 0, _index + 1);
+
+        return result;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java?rev=616118&r1=616117&r2=616118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java Mon Jan 28 16:11:01 2008
@@ -59,19 +59,26 @@
 
         assertTrue(stack.isEmpty());
 
-        stack.push("fred");
-        assertEquals(stack.peek(), "fred");
+        final String fred = "fred";
+        final String barney = "barney";
+
+        stack.push(fred);
+        assertEquals(stack.peek(), fred);
         assertFalse(stack.isEmpty());
 
-        stack.push("barney");
-        assertEquals(stack.peek(), "barney");
+        stack.push(barney);
+        assertEquals(stack.peek(), barney);
 
         assertEquals(stack.toString(), "Stack[barney, fred]");
 
-        assertEquals(stack.pop(), "barney");
-        assertEquals(stack.peek(), "fred");
+        Object[] snapshot = stack.getSnapshot();
+
+        assertArraysEqual(snapshot, new Object[]{fred, barney});
+
+        assertEquals(stack.pop(), barney);
+        assertEquals(stack.peek(), fred);
 
-        assertEquals(stack.pop(), "fred");
+        assertEquals(stack.pop(), fred);
         assertTrue(stack.isEmpty());
     }