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 2009/01/26 19:36:48 UTC

svn commit: r737776 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ tapestry-core/src/main/java/org/apache/tapestry5/services/ tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/ tap...

Author: hlship
Date: Mon Jan 26 18:36:47 2009
New Revision: 737776

URL: http://svn.apache.org/viewvc?rev=737776&view=rev
Log:
TAP5-465: Add a LazyAdvisor service that can allow method invocations on services to be lazily evaluated

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReceiver.java
      - copied, changed from r737609, tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReciever.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/NotLazy.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/OneShotObjectCreator.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LazyAdvisor.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyService.java
Removed:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReciever.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSource.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/HibernateTransactionAdvisor.java
    tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionAdvisorImpl.java
    tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionDecoratorImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceAdvisor.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceAdvisorImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/AspectInterceptorBuilder.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSource.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSource.java Mon Jan 26 18:36:47 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 2009 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.tapestry5.internal.services;
 
 import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.annotations.NotLazy;
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.services.InvalidationEventHub;
 
@@ -41,5 +42,6 @@
      *
      * @since 5.1.0.0
      */
-    InvalidationEventHub getInvalidatonEventHub();
+    @NotLazy
+    InvalidationEventHub getInvalidationEventHub();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java Mon Jan 26 18:36:47 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -111,7 +111,7 @@
         return messagesSource.getMessages(bundle, locale);
     }
 
-    public InvalidationEventHub getInvalidatonEventHub()
+    public InvalidationEventHub getInvalidationEventHub()
     {
         return messagesSource;
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Mon Jan 26 18:36:47 2009
@@ -2103,7 +2103,7 @@
     public static InvalidationEventHub buildComponentMessagesInvalidationEventHub(
             ComponentMessagesSource messagesSource)
     {
-        return messagesSource.getInvalidatonEventHub();
+        return messagesSource.getInvalidationEventHub();
     }
 
     @Scope(ScopeConstants.PERTHREAD)
@@ -2193,4 +2193,15 @@
                                                                    "sun.reflect."
                           ));
     }
+
+    /**
+     * Advises the {@link org.apache.tapestry5.internal.services.ComponentMessagesSource} service so that the creation
+     * of {@link org.apache.tapestry5.ioc.Messages} instances can be deferred.
+     */
+    @Match("ComponentMessagesSource")
+    public static void adviseLazy(LazyAdvisor advisor, MethodAdviceReceiver receiver)
+    {
+        advisor.addLazyMethodInvocationAdvice(receiver);
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/HibernateTransactionAdvisor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/HibernateTransactionAdvisor.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/HibernateTransactionAdvisor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/HibernateTransactionAdvisor.java Mon Jan 26 18:36:47 2009
@@ -14,7 +14,7 @@
 
 package org.apache.tapestry5.hibernate;
 
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 
 /**
  * A replacement for {@link org.apache.tapestry5.hibernate.HibernateTransactionDecorator}.
@@ -29,5 +29,5 @@
      *
      * @param receiver advice receiver
      */
-    void advise(MethodAdviceReciever receiver);
+    void addTransactionCommitAdvice(MethodAdviceReceiver receiver);
 }

Modified: tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionAdvisorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionAdvisorImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionAdvisorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionAdvisorImpl.java Mon Jan 26 18:36:47 2009
@@ -19,7 +19,7 @@
 import org.apache.tapestry5.hibernate.annotations.CommitAfter;
 import org.apache.tapestry5.ioc.Invocation;
 import org.apache.tapestry5.ioc.MethodAdvice;
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 
 import java.lang.reflect.Method;
 
@@ -57,7 +57,7 @@
         this.manager = manager;
     }
 
-    public void advise(MethodAdviceReciever receiver)
+    public void addTransactionCommitAdvice(MethodAdviceReceiver receiver)
     {
         for (Method m : receiver.getInterface().getMethods())
         {

Modified: tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionDecoratorImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionDecoratorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate-core/src/main/java/org/apache/tapestry5/internal/hibernate/HibernateTransactionDecoratorImpl.java Mon Jan 26 18:36:47 2009
@@ -44,7 +44,7 @@
 
         AspectInterceptorBuilder<T> builder = aspectDecorator.createBuilder(serviceInterface, delegate, description);
 
-        advisor.advise(builder);
+        advisor.addTransactionCommitAdvice(builder);
 
         return builder.build();
     }

Copied: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReceiver.java (from r737609, tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReciever.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReceiver.java?p2=tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReceiver.java&p1=tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReciever.java&r1=737609&r2=737776&rev=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReciever.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/MethodAdviceReceiver.java Mon Jan 26 18:36:47 2009
@@ -19,7 +19,7 @@
 /**
  * Interface used with service advisor methods to define advice.  Allows advice on specific methods, or on all methods.
  */
-public interface MethodAdviceReciever
+public interface MethodAdviceReceiver
 {
     /**
      * Adds advice for a specific method of the aspect interceptor being constructed.
@@ -38,6 +38,7 @@
     /**
      * Returns the interface for which methods may be advised.
      *
+     * @see org.apache.tapestry5.ioc.services.MethodIterator
      * @since 5.1.0.0
      */
     Class getInterface();

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceAdvisor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceAdvisor.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceAdvisor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceAdvisor.java Mon Jan 26 18:36:47 2009
@@ -16,7 +16,7 @@
 
 /**
  * Provided by a {@link org.apache.tapestry5.ioc.AdvisorDef} to perform the advice (by invoking methods on a {@link
- * org.apache.tapestry5.ioc.MethodAdviceReciever}).
+ * MethodAdviceReceiver}).
  *
  * @since 5.1.0.0
  */
@@ -25,7 +25,7 @@
     /**
      * Passed the reciever, allows the code (usually a method on a module class) to advice some or all methods.
      *
-     * @param methodAdviceReciever
+     * @param methodAdviceReceiver
      */
-    void advise(MethodAdviceReciever methodAdviceReciever);
+    void advise(MethodAdviceReceiver methodAdviceReceiver);
 }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/NotLazy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/NotLazy.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/NotLazy.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/NotLazy.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,30 @@
+// Copyright 2009 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.ioc.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * Marks a method as specifically not-lazy, even if other methods in the same interface are being {@linkplain
+ * org.apache.tapestry5.ioc.services.LazyAdvisor advised as lazy}.
+ *
+ * @since 5.1.0.0
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface NotLazy
+{
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java Mon Jan 26 18:36:47 2009
@@ -291,7 +291,7 @@
 
         for (Class pt : method.getParameterTypes())
         {
-            if (pt.equals(MethodAdviceReciever.class))
+            if (pt.equals(MethodAdviceReceiver.class))
             {
                 found = true;
 
@@ -302,7 +302,7 @@
         if (!found)
             throw new RuntimeException(String.format("Advise method %s must take a parameter of type %s.",
                                                      toString(method),
-                                                     MethodAdviceReciever.class.getName()));
+                                                     MethodAdviceReceiver.class.getName()));
 
 
         AdvisorDef def = new AdvisorDefImpl(method, extractPatterns(advisorId, method), extractConstraints(method),

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceAdvisorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceAdvisorImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceAdvisorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceAdvisorImpl.java Mon Jan 26 18:36:47 2009
@@ -14,7 +14,7 @@
 
 package org.apache.tapestry5.ioc.internal;
 
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 import org.apache.tapestry5.ioc.ModuleBuilderSource;
 import org.apache.tapestry5.ioc.ServiceAdvisor;
 import org.apache.tapestry5.ioc.ServiceResources;
@@ -38,11 +38,11 @@
      * Invokes the configured method, passing the builder. The method will always take, as a parameter, a
      * MethodAdvisor.
      */
-    public void advise(MethodAdviceReciever methodAdviceReciever)
+    public void advise(MethodAdviceReceiver methodAdviceReceiver)
     {
         Map<Class, Object> resources = CollectionFactory.newMap(this.resourcesDefaults);
 
-        resources.put(MethodAdviceReciever.class, methodAdviceReciever);
+        resources.put(MethodAdviceReceiver.class, methodAdviceReceiver);
 
         InjectionResources injectionResources = new MapInjectionResources(resources);
 

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImpl.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImpl.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,179 @@
+// Copyright 2009 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.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.Invocation;
+import org.apache.tapestry5.ioc.MethodAdvice;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
+import org.apache.tapestry5.ioc.ObjectCreator;
+import org.apache.tapestry5.ioc.annotations.NotLazy;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.services.*;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+public class LazyAdvisorImpl implements LazyAdvisor
+{
+    /**
+     * Map from an interface type to a corresponding "thunk" class that implements the interface.
+     */
+    private final Map<Class, Class> interfaceToThunkClass = CollectionFactory.newConcurrentMap();
+
+    private final ClassFactory classFactory;
+
+    private final MethodSignature toStringSignature = new MethodSignature(String.class, "toString", null, null);
+
+    private static final int PRIVATE_FINAL = Modifier.FINAL + Modifier.PRIVATE;
+
+    private static final String DESCRIPTION_FIELD = "_$description";
+    private static final String CREATOR_FIELD = "_$creator";
+    private static final String DELEGATE_METHOD = "_$delegate";
+
+    public LazyAdvisorImpl(@Builtin ClassFactory classFactory)
+    {
+        this.classFactory = classFactory;
+    }
+
+    public void addLazyMethodInvocationAdvice(MethodAdviceReceiver methodAdviceReceiver)
+    {
+        for (Method m : methodAdviceReceiver.getInterface().getMethods())
+        {
+            if (filter(m))
+                addAdvice(m, methodAdviceReceiver);
+        }
+    }
+
+    private void addAdvice(Method method, MethodAdviceReceiver receiver)
+    {
+        final Class thunkClass = getThunkClass(method.getReturnType());
+
+        final String description = String.format("<%s Thunk for %s>",
+                                                 method.getReturnType().getName(),
+                                                 InternalUtils.asString(method));
+
+        MethodAdvice advice = new MethodAdvice()
+        {
+            /**
+             * When the method is invoked, we don't immediately proceed. Intead, we return a thunk instance
+             * that defers its behavior to the lazyily invoked invocation.
+             */
+            public void advise(final Invocation invocation)
+            {
+                ObjectCreator deferred = new ObjectCreator()
+                {
+                    public Object createObject()
+                    {
+                        invocation.proceed();
+
+                        return invocation.getResult();
+                    }
+                };
+
+                ObjectCreator oneShot = new OneShotObjectCreator(deferred);
+
+                Object thunk = createThunk(thunkClass, description, oneShot);
+
+                invocation.overrideResult(thunk);
+            }
+        };
+
+        receiver.adviseMethod(method, advice);
+    }
+
+    private Object createThunk(Class thunkClass, String description, ObjectCreator creator)
+    {
+        Throwable failure = null;
+
+        try
+        {
+            return thunkClass.getConstructors()[0].newInstance(description, creator);
+        }
+        catch (InvocationTargetException ex)
+        {
+            failure = ex.getTargetException();
+        }
+        catch (Exception ex)
+        {
+            failure = ex;
+        }
+
+        throw new RuntimeException(String.format("Exception instantiating thunk class %s: %s",
+                                                 thunkClass.getName(),
+                                                 InternalUtils.toMessage(failure)),
+                                   failure);
+    }
+
+    private Class getThunkClass(Class type)
+    {
+        Class result = interfaceToThunkClass.get(type);
+
+        if (result == null)
+        {
+            result = constructThunkClass(type);
+            interfaceToThunkClass.put(type, result);
+        }
+
+        return result;
+    }
+
+    private Class constructThunkClass(Class interfaceType)
+    {
+        ClassFab classFab = classFactory.newClass(interfaceType);
+
+        classFab.addField(DESCRIPTION_FIELD, PRIVATE_FINAL, String.class);
+
+        classFab.addField(CREATOR_FIELD, PRIVATE_FINAL, ObjectCreator.class);
+
+        classFab.addConstructor(new Class[] { String.class, ObjectCreator.class }, null,
+                                String.format("{ %s = $1; %s = $2; }", DESCRIPTION_FIELD, CREATOR_FIELD));
+
+        MethodSignature sig = new MethodSignature(interfaceType, DELEGATE_METHOD, null, null);
+
+        classFab.addMethod(Modifier.PRIVATE, sig, String.format("return ($r) %s.createObject();", CREATOR_FIELD));
+
+        MethodIterator mi = new MethodIterator(interfaceType);
+
+        while (mi.hasNext())
+        {
+            sig = mi.next();
+
+            classFab.addMethod(Modifier.PUBLIC, sig,
+                               String.format("return ($r) %s().%s($$);", DELEGATE_METHOD, sig.getName()));
+        }
+
+        if (!mi.getToString())
+            classFab.addMethod(Modifier.PUBLIC, toStringSignature, String.format("return %s;", DESCRIPTION_FIELD));
+
+        return classFab.createClass();
+    }
+
+    private boolean filter(Method method)
+    {
+        if (method.getAnnotation(NotLazy.class) != null) return false;
+
+        if (!method.getReturnType().isInterface()) return false;
+
+        for (Class extype : method.getExceptionTypes())
+        {
+            if (!RuntimeException.class.isAssignableFrom(extype)) return false;
+        }
+
+        return true;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java Mon Jan 26 18:36:47 2009
@@ -15,7 +15,7 @@
 package org.apache.tapestry5.ioc.internal.services;
 
 import org.apache.tapestry5.ioc.MethodAdvice;
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 import org.apache.tapestry5.ioc.services.ExceptionTracker;
 import org.apache.tapestry5.ioc.services.LoggingAdvisor;
 import org.slf4j.Logger;
@@ -29,10 +29,10 @@
         this.exceptionTracker = exceptionTracker;
     }
 
-    public <T> void advise(Logger logger, MethodAdviceReciever reciever)
+    public <T> void advise(Logger logger, MethodAdviceReceiver receiver)
     {
         MethodAdvice advice = new LoggingAdvice(logger, exceptionTracker);
 
-        reciever.adviseAllMethods(advice);
+        receiver.adviseAllMethods(advice);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/OneShotObjectCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/OneShotObjectCreator.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/OneShotObjectCreator.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/OneShotObjectCreator.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,43 @@
+// Copyright 2009 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.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.ObjectCreator;
+
+public class OneShotObjectCreator implements ObjectCreator
+{
+    private boolean cached;
+
+    private Object cachedValue;
+
+    private ObjectCreator creator;
+
+    public OneShotObjectCreator(ObjectCreator creator)
+    {
+        this.creator = creator;
+    }
+
+    public synchronized Object createObject()
+    {
+        if (!cached)
+        {
+            cachedValue = creator.createObject();
+            cached = true;
+            creator = null;
+        }
+
+        return cachedValue;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/AspectInterceptorBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/AspectInterceptorBuilder.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/AspectInterceptorBuilder.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/AspectInterceptorBuilder.java Mon Jan 26 18:36:47 2009
@@ -14,14 +14,14 @@
 
 package org.apache.tapestry5.ioc.services;
 
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 
 /**
  * A builder may be obtained from the {@link org.apache.tapestry5.ioc.services.AspectDecorator} and allows more
  * controlled creation of the created interceptor; it allows different methods to be given different advice, and allows
  * methods to be omitted (in which case the method invocation passes through without advice).
  */
-public interface AspectInterceptorBuilder<T> extends MethodAdviceReciever
+public interface AspectInterceptorBuilder<T> extends MethodAdviceReceiver
 {
 
     /**

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LazyAdvisor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LazyAdvisor.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LazyAdvisor.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LazyAdvisor.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,39 @@
+// Copyright 2009 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.ioc.services;
+
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
+
+/**
+ * An advisor that identifies methods which can be evaluated lazily and advises them. A method can be evaluated lazily
+ * if it returns an interface type and if it throws no checked exceptions. Lazy evaluation should be handled carefully,
+ * as if any of the parameters to a method are mutable, or the internal state of the invoked service changes, the lazily
+ * evaluated results may not match the immediately evaluated result. This effect is greatly exaggerated if the lazy
+ * return object is evaluated in a different thread than when it was generated.
+ * <p/>
+ * Another consideration is that exceptions that would occur immediately in the non-lazy case are also deferred, often
+ * losing much context in the process.
+ * <p/>
+ * Use laziness with great care.
+ * <p/>
+ * Use the {@link org.apache.tapestry5.ioc.annotations.NotLazy} annotation on methods that should not be advised.
+ *
+ * @since 5.1.0.0
+ */
+public interface LazyAdvisor
+{
+    void addLazyMethodInvocationAdvice(MethodAdviceReceiver methodAdviceReceiver);
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java Mon Jan 26 18:36:47 2009
@@ -14,7 +14,7 @@
 
 package org.apache.tapestry5.ioc.services;
 
-import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 import org.slf4j.Logger;
 
 /**
@@ -28,9 +28,9 @@
      * Adds logging advice to all methods of the object.
      *
      * @param logger               log used for debug level logging messages by the interceptor
-     * @param methodAdviceReciever
+     * @param methodAdviceReceiver
      * @return a new object implementing the interface that can be used in place of the delegate, providing logging
      *         behavior around each method call on the service interface
      */
-    <T> void advise(Logger logger, MethodAdviceReciever methodAdviceReciever);
+    <T> void advise(Logger logger, MethodAdviceReceiver methodAdviceReceiver);
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TapestryIOCModule.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TapestryIOCModule.java Mon Jan 26 18:36:47 2009
@@ -59,6 +59,7 @@
         binder.bind(ClasspathURLConverter.class, ClasspathURLConverterImpl.class);
         binder.bind(ServiceOverride.class, ServiceOverrideImpl.class);
         binder.bind(LoggingAdvisor.class, LoggingAdvisorImpl.class);
+        binder.bind(LazyAdvisor.class, LazyAdvisorImpl.class);
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java Mon Jan 26 18:36:47 2009
@@ -35,13 +35,13 @@
     }
 
     @Match("*")
-    public static void adviseLogging(MethodAdviceReciever reciever, LoggingAdvisor loggingAdvisor, Logger logger)
+    public static void adviseLogging(MethodAdviceReceiver receiver, LoggingAdvisor loggingAdvisor, Logger logger)
     {
-        loggingAdvisor.advise(logger, reciever);
+        loggingAdvisor.advise(logger, receiver);
     }
 
     @Order("after:Logging")
-    public static void adviseGreeter(MethodAdviceReciever receiver)
+    public static void adviseGreeter(MethodAdviceReceiver receiver)
     {
         MethodAdvice advice = new MethodAdvice()
         {

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java Mon Jan 26 18:36:47 2009
@@ -1308,7 +1308,7 @@
         catch (RuntimeException ex)
         {
             assertMessageContains(ex,
-                                  "Advise method org.apache.tapestry5.ioc.NonVoidAdvisorMethodModule.adviseFoo(MethodAdviceReciever)",
+                                  "Advise method org.apache.tapestry5.ioc.NonVoidAdvisorMethodModule.adviseFoo(MethodAdviceReceiver)",
                                   "does not return void.");
         }
     }
@@ -1328,7 +1328,7 @@
         {
             assertMessageContains(ex,
                                   "Advise method org.apache.tapestry5.ioc.AdviceMethodMissingAdvisorParameterModule.adviseBar()",
-                                  "must take a parameter of type org.apache.tapestry5.ioc.MethodAdviceReciever.");
+                                  "must take a parameter of type org.apache.tapestry5.ioc.MethodAdviceReceiver.");
         }
     }
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java?rev=737776&r1=737775&r2=737776&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java Mon Jan 26 18:36:47 2009
@@ -16,7 +16,7 @@
 
 public class NonVoidAdvisorMethodModule
 {
-    public static String adviseFoo(MethodAdviceReciever methodAdviceReciever)
+    public static String adviseFoo(MethodAdviceReceiver methodAdviceReceiver)
     {
         return "Never Called";
     }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImplTest.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImplTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyAdvisorImplTest.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,176 @@
+// Copyright 2009 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.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.Greeter;
+import org.apache.tapestry5.ioc.internal.IOCInternalTestCase;
+import org.apache.tapestry5.ioc.services.AspectDecorator;
+import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder;
+import org.apache.tapestry5.ioc.services.LazyAdvisor;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class LazyAdvisorImplTest extends IOCInternalTestCase
+{
+    private AspectDecorator aspectDecorator;
+
+    private LazyAdvisor lazyAdvisor;
+
+    @BeforeClass
+    public void setup()
+    {
+        aspectDecorator = getService(AspectDecorator.class);
+        lazyAdvisor = getService(LazyAdvisor.class);
+    }
+
+    @Test
+    public void void_methods_are_not_lazy()
+    {
+        LazyService service = mockLazyService();
+
+        service.notLazyBecauseVoid();
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        advised.notLazyBecauseVoid();
+
+        verify();
+    }
+
+    private LazyService mockLazyService()
+    {
+        return newMock(LazyService.class);
+    }
+
+    @Test
+    public void non_interface_return_value()
+    {
+        LazyService service = mockLazyService();
+
+        expect(service.notLazyBecauseOfReturnValue()).andReturn("working hard!");
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        assertEquals(advised.notLazyBecauseOfReturnValue(), "working hard!");
+
+        verify();
+    }
+
+    @Test
+    public void lazy_method()
+    {
+        LazyService service = mockLazyService();
+        Greeter greeter = new Greeter()
+        {
+            public String getGreeting()
+            {
+                return "Hello!";
+            }
+        };
+
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        Greeter thunk = advised.createGreeter();
+
+        assertEquals(thunk.toString(),
+                     "<org.apache.tapestry5.ioc.Greeter Thunk for org.apache.tapestry5.ioc.internal.services.LazyService.createGreeter()>");
+
+        verify();
+
+        expect(service.createGreeter()).andReturn(greeter);
+
+        // Prove that the lazy method is only invoked once.
+
+        replay();
+
+        for (int i = 0; i < 2; i++)
+            assertEquals(thunk.getGreeting(), "Hello!");
+
+        verify();
+    }
+
+    @Test
+    public void checked_exception_prevents_lazy() throws Exception
+    {
+        LazyService service = mockLazyService();
+        Greeter greeter = newMock(Greeter.class);
+
+        expect(service.notLazyCreateGreeter()).andReturn(greeter);
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        Greeter actual = advised.notLazyCreateGreeter();
+
+        assertSame(actual, greeter);
+
+        verify();
+    }
+
+    @Test
+    public void notlazy_annotation()
+    {
+        LazyService service = mockLazyService();
+        Greeter greeter = newMock(Greeter.class);
+
+        expect(service.notLazyFromAnnotationGreeter()).andReturn(greeter);
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        Greeter actual = advised.notLazyFromAnnotationGreeter();
+
+        assertSame(actual, greeter);
+
+        verify();
+
+    }
+
+    @Test
+    public void thunk_class_is_cached()
+    {
+        LazyService service = mockLazyService();
+
+        replay();
+
+        LazyService advised = advise(service);
+
+        Greeter g1 = advised.createGreeter();
+        Greeter g2 = advised.safeCreateCreator();
+
+        assertSame(g2.getClass(), g1.getClass());
+
+        verify();
+    }
+
+    private LazyService advise(LazyService base)
+    {
+        AspectInterceptorBuilder<LazyService> builder = aspectDecorator.createBuilder(LazyService.class, base,
+                                                                                      "<LazyService Proxy>");
+
+        lazyAdvisor.addLazyMethodInvocationAdvice(builder);
+
+        return builder.build();
+    }
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyService.java?rev=737776&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyService.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LazyService.java Mon Jan 26 18:36:47 2009
@@ -0,0 +1,42 @@
+// Copyright 2009 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.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.Greeter;
+import org.apache.tapestry5.ioc.annotations.NotLazy;
+
+import java.sql.SQLException;
+
+/**
+ * Used to test {@link org.apache.tapestry5.ioc.services.LazyAdvisor}, as it has a mix of lazy and not lazy methods.
+ */
+public interface LazyService
+{
+    void notLazyBecauseVoid();
+
+    String notLazyBecauseOfReturnValue();
+
+    /**
+     * The only lazy method.
+     */
+    Greeter createGreeter() throws RuntimeException;
+
+    Greeter safeCreateCreator();
+
+    @NotLazy
+    Greeter notLazyFromAnnotationGreeter();
+
+    Greeter notLazyCreateGreeter() throws SQLException;
+}