Author: hlship
Date: Fri Feb 19 18:53:55 2010
New Revision: 911922

URL: http://svn.apache.org/viewvc?rev=911922&view=rev
Log:
Re-implement CachedWorker using TransformMethod APIs

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java
   (with props)
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java
   (with props)
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java
   (with props)
Removed:
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/CachedWorkerTest.java
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java?rev=911922&r1=911921&r2=911922&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java
 Fri Feb 19 18:53:55 2010
@@ -1,10 +1,10 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2010 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
+// 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,
@@ -14,15 +14,25 @@
 
 package org.apache.tapestry5.internal.transform;
 
+import java.lang.reflect.Modifier;
+import java.util.List;
+
 import org.apache.tapestry5.Binding;
 import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.annotations.Cached;
-import org.apache.tapestry5.ioc.util.BodyBuilder;
+import org.apache.tapestry5.internal.TapestryInternalUtils;
 import org.apache.tapestry5.model.MutableComponentModel;
-import org.apache.tapestry5.services.*;
-
-import static java.lang.reflect.Modifier.PRIVATE;
-import java.util.List;
+import org.apache.tapestry5.runtime.PageLifecycleAdapter;
+import org.apache.tapestry5.services.BindingSource;
+import org.apache.tapestry5.services.ClassTransformation;
+import org.apache.tapestry5.services.ComponentClassTransformWorker;
+import org.apache.tapestry5.services.ComponentMethodAdvice;
+import org.apache.tapestry5.services.ComponentMethodInvocation;
+import org.apache.tapestry5.services.FieldAccess;
+import org.apache.tapestry5.services.TransformField;
+import org.apache.tapestry5.services.TransformMethod;
+import org.apache.tapestry5.services.TransformMethodSignature;
 
 /**
  * Caches method return values for methods annotated with {...@link Cached}.
@@ -31,6 +41,83 @@
 {
     private final BindingSource bindingSource;
 
+    /**
+     * Manages a cache value as the result of invoking a no-arguments method.
+     */
+    public interface MethodResultCache
+    {
+        /** Returns true if the cache contains a cached value. May also check 
to see if the cached value is valid. */
+        boolean isCached();
+
+        /** Stores a new cached value for later reference. */
+        void set(Object cachedValue);
+
+        /** Returns the previously cached value, if any. */
+        Object get();
+
+        /** Resets the cache, discarding the cached value. */
+        void reset();
+    }
+
+    /**
+     * Handles the watching of a binding (usually a property or property 
expression), invalidating the
+     * cache early if the watched binding's value changes.
+     */
+    private class SimpleMethodResultCache implements MethodResultCache
+    {
+        private boolean cached;
+        private Object cachedValue;
+
+        public void set(Object cachedValue)
+        {
+            cached = true;
+            this.cachedValue = cachedValue;
+        }
+
+        public void reset()
+        {
+            cached = false;
+            cachedValue = null;
+        }
+
+        public boolean isCached()
+        {
+            return cached;
+        }
+
+        public Object get()
+        {
+            return cachedValue;
+        }
+    }
+
+    private class WatchedBindingMethodResultCache extends 
SimpleMethodResultCache
+    {
+        private final Binding binding;
+
+        private Object cachedBindingValue;
+
+        public WatchedBindingMethodResultCache(Binding binding)
+        {
+            this.binding = binding;
+        }
+
+        @Override
+        public boolean isCached()
+        {
+            Object currentBindingValue = binding.get();
+
+            if (!TapestryInternalUtils.isEqual(cachedBindingValue, 
currentBindingValue))
+            {
+                reset();
+
+                cachedBindingValue = currentBindingValue;
+            }
+
+            return super.isCached();
+        }
+    }
+
     public CachedWorker(BindingSource bindingSource)
     {
         this.bindingSource = bindingSource;
@@ -38,103 +125,108 @@
 
     public void transform(ClassTransformation transformation, 
MutableComponentModel model)
     {
-        List<TransformMethodSignature> methods = 
transformation.findMethodsWithAnnotation(Cached.class);
-        if (methods.isEmpty())
-            return;
+        List<TransformMethod> methods = 
transformation.matchMethodsWithAnnotation(Cached.class);
 
-        for (TransformMethodSignature method : methods)
+        for (TransformMethod method : methods)
         {
-            if (method.getReturnType().equals("void"))
-                throw new 
IllegalArgumentException(TransformMessages.cachedMethodMustHaveReturnValue(method));
+            validateMethod(method);
 
-            if (method.getParameterTypes().length != 0)
-                throw new 
IllegalArgumentException(TransformMessages.cachedMethodsHaveNoParameters(method));
+            adviseMethod(transformation, method);
+        }
+    }
 
-            String propertyName = method.getMethodName();
+    private void adviseMethod(ClassTransformation transformation, 
TransformMethod method)
+    {
+        FieldAccess resultCacheAccess = 
createMethodResultCacheField(transformation, method);
 
-            // add a property to store whether or not the method has been 
called
-            String fieldName = transformation.addField(PRIVATE, 
method.getReturnType(), propertyName);
-            String calledField = transformation.addField(PRIVATE, "boolean", 
fieldName + "$called");
+        Cached annotation = method.getAnnotation(Cached.class);
 
-            Cached once = transformation.getMethodAnnotation(method, 
Cached.class);
-            String bindingField = null;
-            String bindingValueField = null;
-            boolean watching = once.watch().length() > 0;
+        ComponentMethodAdvice advice = createAdvice(resultCacheAccess, 
annotation.watch());
 
-            if (watching)
+        method.addAdvice(advice);
+    }
+
+    private FieldAccess createMethodResultCacheField(ClassTransformation 
transformation, TransformMethod method)
+    {
+        TransformField resultCacheField = 
transformation.createField(Modifier.PRIVATE, MethodResultCache.class
+                .getName(), "cache$" + method.getName());
+
+        return resultCacheField.getAccess();
+    }
+
+    private ComponentMethodAdvice createAdvice(final FieldAccess 
resultCacheAccess, final String watch)
+    {
+        ComponentMethodAdvice advice = new ComponentMethodAdvice()
+        {
+            public void advise(ComponentMethodInvocation invocation)
             {
-                // add fields to store the binding and the value
-                bindingField = transformation.addField(PRIVATE, 
Binding.class.getCanonicalName(),
-                                                       fieldName + "$binding");
-                bindingValueField = transformation.addField(PRIVATE, 
"java.lang.Object", fieldName + "$bindingValue");
-
-                String bindingSourceField = 
transformation.addInjectedField(BindingSource.class,
-                                                                            
fieldName + "$bindingsource",
-                                                                            
bindingSource);
-
-                String body = String.format("%s = %s.newBinding(\"Watch 
expression\", %s, \"%s\", \"%s\");",
-                                            bindingField,
-                                            bindingSourceField,
-                                            
transformation.getResourcesFieldName(),
-                                            BindingConstants.PROP,
-                                            once.watch());
+                MethodResultCache cache = getOrCreateCache(invocation);
 
-                
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
 body);
+                if (cache.isCached())
+                {
+                    invocation.overrideResult(cache.get());
+                    return;
+                }
+
+                invocation.proceed();
+
+                invocation.rethrow();
+
+                cache.set(invocation.getResult());
             }
 
-            BodyBuilder b = new BodyBuilder();
+            private MethodResultCache 
getOrCreateCache(ComponentMethodInvocation invocation)
+            {
+                MethodResultCache cache = (MethodResultCache) 
resultCacheAccess.read(invocation.getInstance());
 
-            // on cleanup, reset the field values
-            b.begin();
+                if (cache == null)
+                    cache = createAndStoreCache(invocation);
 
-            if (!TransformUtils.isPrimitive(method.getReturnType()))
-                b.addln("%s = null;", fieldName);
-            b.addln("%s = false;", calledField);
-
-            if (watching)
-                b.addln("%s = null;", bindingValueField);
-
-            b.end();
-
-            // TAPESTRY-2338: Cleanup at page detach, not render cleanup.  In 
an Ajax request, the rendering
-            // objects may reference properties of components that don't 
render and so won't execute the
-            // PostCleanupRender phase.
-
-            
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
 b.toString());
-
-            // prefix the existing method to cache the result
-            b.clear();
-            b.begin();
-
-            // if it has been called and watch is set and the old value is the 
same as the new value then return
-            // get the old value and cache it
-            /* NOTE: evaluates the binding twice when checking the new value.
-                * this is probably not a problem because in most cases 
properties
-                * that are being watched are not expensive operations. plus, we
-                * never guaranteed that it would be called exactly once when
-                * watching.
-                */
-            if (watching)
+                return cache;
+            }
+
+            private MethodResultCache 
createAndStoreCache(ComponentMethodInvocation invocation)
             {
-                b.addln("if (%s && %s == %s.get()) return %s;",
-                        calledField, bindingValueField, bindingField, 
fieldName);
-                b.addln("%s = %s.get();", bindingValueField, bindingField);
+                final MethodResultCache cache = 
createMethodResultCache(invocation.getComponentResources());
+
+                
invocation.getComponentResources().addPageLifecycleListener(new 
PageLifecycleAdapter()
+                {
+                    @Override
+                    public void containingPageDidDetach()
+                    {
+                        cache.reset();
+                    }
+                });
+
+                resultCacheAccess.write(invocation.getInstance(), cache);
+
+                return cache;
             }
-            else
+
+            private SimpleMethodResultCache 
createMethodResultCache(ComponentResources resources)
             {
-                b.addln("if (%s) return %s;", calledField, fieldName);
+                if (watch.equals(""))
+                    return new SimpleMethodResultCache();
+
+                Binding binding = bindingSource.newBinding("@Cached watch", 
resources, BindingConstants.PROP, watch);
+
+                return new WatchedBindingMethodResultCache(binding);
             }
+        };
 
-            b.addln("%s = true;", calledField);
-            b.end();
-            transformation.prefixMethod(method, b.toString());
-
-            // cache the return value
-            b.clear();
-            b.begin();
-            b.addln("%s = $_;", fieldName);
-            b.end();
-            transformation.extendExistingMethod(method, b.toString());
-        }
+        return advice;
+    }
+
+    private void validateMethod(TransformMethod method)
+    {
+        TransformMethodSignature signature = method.getSignature();
+
+        if (signature.getReturnType().equals("void"))
+            throw new IllegalArgumentException(String.format(
+                    "Method %s may not be used with @Cached because it returns 
void.", method.getMethodIdentifier()));
+
+        if (signature.getParameterTypes().length != 0)
+            throw new IllegalArgumentException(String.format(
+                    "Method %s may not be used with @Cached because it has 
parameters.", method.getMethodIdentifier()));
     }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java?rev=911922&r1=911921&r2=911922&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/TransformMessages.java
 Fri Feb 19 18:53:55 2010
@@ -18,12 +18,12 @@
 
 import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.annotations.MixinClasses;
-import org.apache.tapestry5.internal.structure.InternalComponentResourcesImpl;
 import org.apache.tapestry5.ioc.Messages;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.internal.util.MessagesImpl;
 import org.apache.tapestry5.services.TransformField;
+import org.apache.tapestry5.services.TransformMethod;
 import org.apache.tapestry5.services.TransformMethodSignature;
 
 class TransformMessages
@@ -35,16 +35,6 @@
         return MESSAGES.format("field-injection-error", className, fieldName, 
cause);
     }
 
-    static String cachedMethodMustHaveReturnValue(TransformMethodSignature 
method)
-    {
-        return MESSAGES.format("cached-no-return-value", method);
-    }
-
-    static String cachedMethodsHaveNoParameters(TransformMethodSignature 
method)
-    {
-        return MESSAGES.format("cached-no-parameters", method);
-    }
-
     static String 
illegalNumberOfPageActivationContextHandlers(List<TransformField> fields)
     {
         List<String> names = CollectionFactory.newList();

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties?rev=911922&r1=911921&r2=911922&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/transform/TransformStrings.properties
 Fri Feb 19 18:53:55 2010
@@ -13,8 +13,6 @@
 # limitations under the License.
 
 field-injection-error=Error obtaining injected value for field %s.%s: %s
-cached-no-return-val...@cached may only be used with methods that return 
values: %s
-cached-no-paramete...@cached cannot be used with methods that accept 
parameters: %s
 illegal-number-of-page-activation-context-handlers=Illegal number of fields 
annotated with @PageActivationContext: %s. Only one field is allowed.
 bad-mixin-constraint-length=%d mixins defined via @MixinClasses on field '%s', 
but %d ordering constraints \
  specified (expected 0 or %1$d).

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml?rev=911922&r1=911921&r2=911922&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml Fri Feb 19 
18:53:55 2010
@@ -132,6 +132,16 @@
           <a href="PageResetFailure">PageReset Annotation Failure</a>
           -- error when @PageReset is on a method with parameters
         </li>
+        
+        <li>
+          <a href="VoidMethodWithCached">@Cached on void method</a>
+          -- error when @Cached is used on a method that returns void
+        </li>
+        
+        <li>
+          <a href="ParamsMethodWithCached">@Cached on method with 
parameters</a>
+          -- error when @cached is used on a method that has parameters
+        </li>
     </ul>
 
 </html>

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java?rev=911922&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java
 Fri Feb 19 18:53:55 2010
@@ -0,0 +1,70 @@
+// Copyright 2010 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.integration.TapestryCoreTestCase;
+import org.testng.annotations.Test;
+
+public class CacheTests extends TapestryCoreTestCase
+{
+    /**
+     * TAPESTRY-2338
+     */
+    @Test
+    public void cached_properties_cleared_at_end_of_request()
+    {
+        clickThru("Clean Cache Demo");
+
+        String time1_1 = getText("time1");
+        String time1_2 = getText("time1");
+
+        // Don't know what they are but they should be the same.
+
+        assertEquals(time1_2, time1_1);
+
+        click("link=update");
+
+        sleep(250);
+
+        String time2_1 = getText("time1");
+        String time2_2 = getText("time1");
+
+        // Check that @Cache is still working
+
+        assertEquals(time2_2, time2_1);
+
+        assertFalse(time2_1.equals(time1_1),
+                "After update the nanoseconds time did not change, meaning 
@Cache was broken.");
+    }
+
+    @Test
+    public void void_method_is_error_with_cached()
+    {
+        clickThru("@Cached on void method");
+
+        assertTextPresent("Method 
org.apache.tapestry5.integration.app1.pages.VoidMethodWithCached.invalidMethod()",
+                "may not be used with @Cached because it returns void.");
+    }
+
+    @Test
+    public void parameters_not_allowed_with_cached_method()
+    {
+        clickThru("@Cached on method with parameters");
+
+        assertTextPresent(
+                "Method 
org.apache.tapestry5.integration.app1.pages.ParamsMethodWithCached.invalidMethod(java.lang.String)",
+                "may not be used with @Cached because it has parameters.");
+    }
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CacheTests.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java?rev=911922&r1=911921&r2=911922&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
 Fri Feb 19 18:53:55 2010
@@ -813,35 +813,6 @@
         assertTextPresent("Class 
org.apache.tapestry5.integration.app1.pages.Datum contains field(s) (_value) 
that are not private. You should change these fields to private, and add 
accessor methods if needed.");
     }
 
-    /**
-     * TAPESTRY-2338
-     */
-    @Test
-    public void cached_properties_cleared_at_end_of_request()
-    {
-        clickThru("Clean Cache Demo");
-
-        String time1_1 = getText("time1");
-        String time1_2 = getText("time1");
-
-        // Don't know what they are but they should be the same.
-
-        assertEquals(time1_2, time1_1);
-
-        click("link=update");
-
-        sleep(250);
-
-        String time2_1 = getText("time1");
-        String time2_2 = getText("time1");
-
-        // Check that @Cache is still working
-
-        assertEquals(time2_2, time2_1);
-
-        assertFalse(time2_1.equals(time1_1),
-                "After update the nanoseconds time did not change, meaning 
@Cache was broken.");
-    }
 
     @Test
     public void method_advice()

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java?rev=911922&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java
 Fri Feb 19 18:53:55 2010
@@ -0,0 +1,26 @@
+// Copyright 2010 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.annotations.Cached;
+
+public class ParamsMethodWithCached
+{
+    @Cached
+    public int invalidMethod(String parameter)
+    {
+        return 0;
+    }
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ParamsMethodWithCached.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java?rev=911922&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java
 Fri Feb 19 18:53:55 2010
@@ -0,0 +1,25 @@
+// Copyright 2010 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.annotations.Cached;
+
+public class VoidMethodWithCached
+{
+    @Cached
+    public void invalidMethod()
+    {
+    }
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/VoidMethodWithCached.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to