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;
+}