tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject svn commit: r911922 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/transform/ main/resources/org/apache/tapestry5/internal/transform/ test/app1/ test/java/org/apache/tapestry5/integration/app1/ test/java/org/a...
Date Fri, 19 Feb 2010 18:53:56 GMT
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-value=@Cached may only be used with methods that return values: %s
-cached-no-parameters=@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



Mime
View raw message