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 00:40:15 UTC

svn commit: r737609 [2/2] - in /tapestry/tapestry5/trunk: tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/ tapestry-hibernate-core/src/main/java/org/apache/tapestry5/hibernate/annotations/ tapestry-hibernate-core/src/main/java/org/...

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java Sun Jan 25 23:40:14 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 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.
@@ -67,6 +67,11 @@
                 getBuilder().adviseAllMethods(advice);
             }
 
+            public Class getInterface()
+            {
+                return serviceInterface;
+            }
+
             public T build()
             {
                 return builder == null ? delegate : builder.build();

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java Sun Jan 25 23:40:14 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 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.
@@ -104,6 +104,11 @@
             adviseMethod(m, advice);
     }
 
+    public Class getInterface()
+    {
+        return serviceInterface;
+    }
+
     public T build()
     {
         lock.lock();

Added: 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=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingAdvisorImpl.java Sun Jan 25 23:40:14 2009
@@ -0,0 +1,38 @@
+// 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.MethodAdvice;
+import org.apache.tapestry5.ioc.MethodAdviceReciever;
+import org.apache.tapestry5.ioc.services.ExceptionTracker;
+import org.apache.tapestry5.ioc.services.LoggingAdvisor;
+import org.slf4j.Logger;
+
+public class LoggingAdvisorImpl implements LoggingAdvisor
+{
+    private final ExceptionTracker exceptionTracker;
+
+    public LoggingAdvisorImpl(ExceptionTracker exceptionTracker)
+    {
+        this.exceptionTracker = exceptionTracker;
+    }
+
+    public <T> void advise(Logger logger, MethodAdviceReciever reciever)
+    {
+        MethodAdvice advice = new LoggingAdvice(logger, exceptionTracker);
+
+        reciever.adviseAllMethods(advice);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImpl.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImpl.java Sun Jan 25 23:40:14 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.
@@ -14,9 +14,9 @@
 
 package org.apache.tapestry5.ioc.internal.services;
 
-import org.apache.tapestry5.ioc.MethodAdvice;
 import org.apache.tapestry5.ioc.services.AspectDecorator;
-import org.apache.tapestry5.ioc.services.ExceptionTracker;
+import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder;
+import org.apache.tapestry5.ioc.services.LoggingAdvisor;
 import org.apache.tapestry5.ioc.services.LoggingDecorator;
 import org.slf4j.Logger;
 
@@ -24,21 +24,25 @@
 {
     private final AspectDecorator aspectDecorator;
 
-    private final ExceptionTracker exceptionTracker;
+    private final LoggingAdvisor advisor;
 
-    public LoggingDecoratorImpl(AspectDecorator aspectDecorator, ExceptionTracker exceptionTracker)
+    public LoggingDecoratorImpl(AspectDecorator aspectDecorator, LoggingAdvisor advisor)
     {
         this.aspectDecorator = aspectDecorator;
-        this.exceptionTracker = exceptionTracker;
+        this.advisor = advisor;
     }
 
     public <T> T build(Class<T> serviceInterface, T delegate, String serviceId, final Logger logger)
     {
-        MethodAdvice advice = new LoggingAdvice(logger, exceptionTracker);
+        AspectInterceptorBuilder<T> builder = aspectDecorator.createBuilder(serviceInterface, delegate,
+                                                                            String.format(
+                                                                                    "<Logging interceptor for %s(%s)>",
+                                                                                    serviceId,
+                                                                                    serviceInterface.getName()));
+        advisor.advise(logger, builder);
 
-        return aspectDecorator.build(serviceInterface, delegate, advice,
-                                     String.format("<Logging interceptor for %s(%s)>", serviceId,
-                                                   serviceInterface.getName()));
+        return builder.build();
     }
 
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java Sun Jan 25 23:40:14 2009
@@ -19,8 +19,7 @@
 import org.apache.tapestry5.ioc.annotations.InjectResource;
 import org.apache.tapestry5.ioc.annotations.InjectService;
 import org.apache.tapestry5.ioc.annotations.PostInjection;
-import org.apache.tapestry5.ioc.def.ServiceDef;
-import org.apache.tapestry5.ioc.def.ServiceDef2;
+import org.apache.tapestry5.ioc.def.*;
 import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
 import org.apache.tapestry5.ioc.services.ClassFabUtils;
@@ -40,7 +39,7 @@
  * Utilities used within various internal implemenations of Tapestry IOC and the rest of the tapestry-core framework.
  */
 
-@SuppressWarnings({"JavaDoc", "unchecked"})
+@SuppressWarnings({ "JavaDoc", "unchecked" })
 public class InternalUtils
 {
     /**
@@ -789,4 +788,48 @@
             }
         };
     }
+
+    public static ModuleDef2 toModuleDef2(final ModuleDef md)
+    {
+        if (md instanceof ModuleDef2)
+            return (ModuleDef2) md;
+
+        return new ModuleDef2()
+        {
+            public Set<AdvisorDef> getAdvisorDefs()
+            {
+                return Collections.emptySet();
+            }
+
+            public Class getBuilderClass()
+            {
+                return md.getBuilderClass();
+            }
+
+            public Set<ContributionDef> getContributionDefs()
+            {
+                return md.getContributionDefs();
+            }
+
+            public Set<DecoratorDef> getDecoratorDefs()
+            {
+                return md.getDecoratorDefs();
+            }
+
+            public String getLoggerName()
+            {
+                return md.getLoggerName();
+            }
+
+            public ServiceDef getServiceDef(String serviceId)
+            {
+                return md.getServiceDef(serviceId);
+            }
+
+            public Set<String> getServiceIds()
+            {
+                return md.getServiceIds();
+            }
+        };
+    }
 }

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=737609&r1=737608&r2=737609&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 Sun Jan 25 23:40:14 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 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.
@@ -14,30 +14,15 @@
 
 package org.apache.tapestry5.ioc.services;
 
-import org.apache.tapestry5.ioc.MethodAdvice;
-
-import java.lang.reflect.Method;
+import org.apache.tapestry5.ioc.MethodAdviceReciever;
 
 /**
  * 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>
+public interface AspectInterceptorBuilder<T> extends MethodAdviceReciever
 {
-    /**
-     * Adds advice for a specific method of the aspect interceptor being constructed.
-     *
-     * @param method method (of the interface for which an interceptor is being constructed) to be advised. Multiple
-     *               advice is allowed for a single method; the advice will be executed in the order it is added.
-     * @param advice the advice for this particular method.   Advice must be threadsafe.
-     */
-    void adviseMethod(Method method, MethodAdvice advice);
-
-    /**
-     * Advises <em>all</em> methods of the interface with the given advice.
-     */
-    void adviseAllMethods(MethodAdvice advice);
 
     /**
      * Builds and returns the interceptor.  Any methods that have not been advised will become "pass thrus".

Added: 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=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingAdvisor.java Sun Jan 25 23:40:14 2009
@@ -0,0 +1,36 @@
+// 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.MethodAdviceReciever;
+import org.slf4j.Logger;
+
+/**
+ * A service used in conjuction with a service advisor method to add logging advice to a service.
+ *
+ * @since 5.1.0.0
+ */
+public interface LoggingAdvisor
+{
+    /**
+     * Adds logging advice to all methods of the object.
+     *
+     * @param logger               log used for debug level logging messages by the interceptor
+     * @param methodAdviceReciever
+     * @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);
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java Sun Jan 25 23:40:14 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 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.
@@ -20,6 +20,9 @@
  * Service that can create a logging interceptor that wraps around a service implementation (or interceptor). The
  * interceptor works with the service's log to log, at debug level, method entry (with arguments), method exit (with
  * return value, if any) as well as any thrown exceptions.
+ * <p/>
+ * This represents the Tapestry 5.0 decorator approach; for Tapestry 5.1 you may want to use the {@link
+ * org.apache.tapestry5.ioc.services.LoggingAdvisor} in conjunction with a service advisor method.
  */
 public interface LoggingDecorator
 {

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=737609&r1=737608&r2=737609&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 Sun Jan 25 23:40:14 2009
@@ -58,12 +58,13 @@
         binder.bind(AspectDecorator.class, AspectDecoratorImpl.class);
         binder.bind(ClasspathURLConverter.class, ClasspathURLConverterImpl.class);
         binder.bind(ServiceOverride.class, ServiceOverrideImpl.class);
+        binder.bind(LoggingAdvisor.class, LoggingAdvisorImpl.class);
     }
 
     /**
-     * Provides access to additional service lifecycles. One lifecycles is built in ("singleton") but additional ones
-     * are accessed via this service (and its mapped configuration). Only proxiable services (those with explicit
-     * service interfaces) can be managed in terms of a lifecycle.
+     * Provides access to additional service lifecycles. One lifecycle is built in ("singleton") but additional ones are
+     * accessed via this service (and its mapped configuration). Only proxiable services (those with explicit service
+     * interfaces) can be managed in terms of a lifecycle.
      */
     public static ServiceLifecycleSource build(final Map<String, ServiceLifecycle> configuration)
     {
@@ -343,7 +344,7 @@
         {
             public Object[] coerce(Object input)
             {
-                return new Object[] {input};
+                return new Object[] { input };
             }
         });
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties Sun Jan 25 23:40:14 2009
@@ -22,7 +22,6 @@
 instantiate-builder-error=Unable to instantiate class %s as a module: %s
 builder-method-error=Error invoking service builder method %s (for service '%s'): %s
 constructor-error=Error invoking constructor %s (for service '%s'): %s
-decorator-method-error=Error invoking service decorator method %s (for service '%s'): %s
 builder-method-returned-null=Builder method %s (for service '%s') returned null.
 no-service-matches-type=No service implements the interface %s.
 many-service-matches=Service interface %s is matched by %d services: %s.  \

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/advice.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/advice.apt?rev=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/advice.apt (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/advice.apt Sun Jan 25 23:40:14 2009
@@ -0,0 +1,125 @@
+  ---
+  Service Advisors
+  ---
+
+Service Advisors
+
+  Service advice represents a powerful meta-programming facility availble to services. In fact, it is a kind
+  of limited Aspect Oriented Programming.
+
+  Service advice allows you to intercept method invocations on your services; you have the abillity
+  to see what methods get invoked, what the parameters are. You can let the normal code do it work, and then
+  inspect or event adjust the return value, or any thrown exceptions.  And you can do this all in normal Java code.
+
+  A common example of method-level service advice is to log method entry and exit, complete with
+  parameter values, return values, and thrown exceptions. Other approaches include security checks, transaction
+  management, and other broadly spanning concerns.
+
+  Let's start with a (contrived) example. Let's say you have an existing set of services that have methods
+  that sometimes return null, and you want them to return an empty string instead because you are getting some NullPointerExceptions.
+
+  You could track down the implementation of each service and fix the logic that provides a return value ... or you could advise the methods:
+
+----
+  @Match("*")
+  public static void adviseNonNull(MethodAdviceReciever receiver)
+  {
+    MethodAdvice advice = new MethodAdvice()
+    {
+      void advise(Invocation invocation)
+      {
+        invocation.proceed();
+
+        if (invocation.getResultType().equals(String.class) && invocation.getResult().equals(null))
+          invocation.overrideResult("");
+      }
+    };
+
+    receiver.adviseAllMethods(advice);
+  };
+----
+
+  This is a method that is placed in a module class. Note the terminology: <advise> is the verb ("to advise a method")
+  and <advice> is the noun ("with this advice").
+
+  The {{{../../apidocs/org/apache/tapestry5/ioc/annotations/Match.html}@Match}}
+  annotation indicates that this advice applies to all services (both your own, and those defined by Tapestry).
+  You will want to narrow down which services are actually targetted in most cases.
+
+  The {{{../../apidocs/org/apache/tapestry5/ioc/MethodAdvice.html}MethodAdvice}} object is very simple; it recieves an
+  {{{../../apidocs/org/apache/tapestry5/ioc/Invocation.html}Invocation}} representing a method call. Invocation
+  has methods for inspecting the type and value of the parameters, and for overriding the values of the parameters.
+
+  The call to proceed() allows the invocation to continue; the original method is invoked.  You can then inspect
+  and override the result (the return value).
+
+  We can improve our method to only advise methods that return String:
+
+----
+  @Match("*")
+  public static void adviseNonNull(MethodAdviceReciever receiver)
+  {
+    MethodAdvice advice = new MethodAdvice()
+    {
+      void advise(Invocation invocation)
+      {
+        invocation.proceed();
+
+        if (invocation.getResult().equals(null))
+          invocation.overrideResult("");
+      }
+    };
+
+    for (Method m : receiver.getServiceInterface().getMethods())
+    {
+      if (m.getReturnType().equals(String.class))
+        reciever.adviseMethod(m, advice);
+    }
+  };
+----
+
+  The {{{injection.html}guide to injection}} describes what can be injected into a service advisor method.
+
+  Service advisor methods must return void and have a parameter of type MethodAdviceReciever.
+
+  A service will often be advised multiple times; any method may have any number of advice objects added to it.
+  Some methods may not get any advice. All of this is acceptible.
+
+Logging Advice
+
+  Logging advice is built into Tapestry.  You can apply logging advice to your services very easily:
+
+---
+  @Match("*")
+  public static void adviseLogging(LoggingAdvisor loggingAdvisor, Logger logger, MethodAdviceReciever reciever)
+  {
+    loggingAdvisor.advise(logger, reciever);
+  }
+---
+
+  {{{../../apidocs/org/apache/tapestry5/ioc/services/LoggingAdvisor.html}LoggingAdvisor}} is
+  a built-in Tapestry IoC service.  This demonstrates how services can be injected into
+  service advisor methods.   The Logger parameter is the logger for the service being advised.
+
+Matching And Orderering
+
+  Each service advice method gets a unique id, obtained by stripping the "advise" prefix from the method name.
+  Advice ids must be unique across all modules.
+
+  If the @Match annotation is omitted, the advice will match against a service with the same id.
+
+  In many cases, the order in which the advice is given is very important; for example, you may want
+  logging first, then transaction management, then security checks.  The
+  {{{../../apidocs/org/apache/tapestry5/ioc/annotations/Order.html}@Order}} annotation allows you
+  to explictly set the order.  
+
+Decorators and Advice
+
+  {{{decorator.html}Service decorators}} are another way to achieve the same thing; service advisors were
+  added in Tapestry 5.1.
+
+  It is not recommended that you mix advice and decoration.  If you do, decoration take precendence; all decorators
+  will be in effect before any advice (internally, they are two seperate steps, with advice being processed and the
+  result of that used by the decorators).
+
+

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt Sun Jan 25 23:40:14 2009
@@ -4,6 +4,9 @@
  
 Tapestry IoC Decorators
 
+  <<Decoration has been replaced, in Tapestry 5.1, with {{{advice.html}advice}},
+  which is a simpler mechanism for accomplishing the same thing.>>
+
   <Decoration> is the name of a popular design pattern.  Using decoration,
   an existing object's behavior can be extended without changing the implementation
   of the object.

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/site.xml?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/site.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/site.xml Sun Jan 25 23:40:14 2009
@@ -51,6 +51,7 @@
             <item name="Modules" href="module.html"/>
             <item name="Module Autoloading" href="autoload.html"/>
             <item name="Services" href="service.html"/>
+            <item name="Advisors" href="advice.html"/>
             <item name="Decorators" href="decorator.html"/>
             <item name="Configuration" href="configuration.html"/>
             <item name="Type Coercion" href="coerce.html"/>

Added: 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=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceDemoModule.java Sun Jan 25 23:40:14 2009
@@ -0,0 +1,67 @@
+// 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;
+
+import org.apache.tapestry5.ioc.annotations.Match;
+import org.apache.tapestry5.ioc.annotations.Order;
+import org.apache.tapestry5.ioc.services.LoggingAdvisor;
+import org.slf4j.Logger;
+
+import java.lang.reflect.Method;
+
+public class AdviceDemoModule
+{
+    public static Greeter buildGreeter()
+    {
+        return new Greeter()
+        {
+            public String getGreeting()
+            {
+                return "Advice is Easy!";
+            }
+        };
+    }
+
+    @Match("*")
+    public static void adviseLogging(MethodAdviceReciever reciever, LoggingAdvisor loggingAdvisor, Logger logger)
+    {
+        loggingAdvisor.advise(logger, reciever);
+    }
+
+    @Order("after:Logging")
+    public static void adviseGreeter(MethodAdviceReciever receiver)
+    {
+        MethodAdvice advice = new MethodAdvice()
+        {
+            public void advise(Invocation invocation)
+            {
+                invocation.proceed();
+
+                String result = (String) invocation.getResult();
+
+                if (result != null)
+                    invocation.overrideResult(result.toUpperCase());
+            }
+        };
+
+        for (Method m : receiver.getInterface().getMethods())
+        {
+            if (m.getReturnType().equals(String.class))
+            {
+                receiver.adviseMethod(m, advice);
+            }
+        }
+    }
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceMethodMissingAdvisorParameterModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceMethodMissingAdvisorParameterModule.java?rev=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceMethodMissingAdvisorParameterModule.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/AdviceMethodMissingAdvisorParameterModule.java Sun Jan 25 23:40:14 2009
@@ -0,0 +1,26 @@
+// 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;
+
+public class AdviceMethodMissingAdvisorParameterModule
+{
+    /**
+     * This is an error as advisor methods must take a parameter of type MethodAdvisor.
+     */
+    public static void adviseBar()
+    {
+
+    }
+}

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=737609&r1=737608&r2=737609&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 Sun Jan 25 23:40:14 2009
@@ -871,7 +871,7 @@
 
         URL url = fakejar.toURL();
 
-        URLClassLoader loader = new URLClassLoader(new URL[] {url}, Thread.currentThread().getContextClassLoader());
+        URLClassLoader loader = new URLClassLoader(new URL[] { url }, Thread.currentThread().getContextClassLoader());
 
         RegistryBuilder builder = new RegistryBuilder(loader);
 
@@ -1293,4 +1293,55 @@
 
         assertEquals(g.getGreeting(), "Override Greeting");
     }
+
+    /**
+     * TAP5-60
+     */
+    @Test
+    public void non_void_advisor_method_is_error()
+    {
+        try
+        {
+            buildRegistry(NonVoidAdvisorMethodModule.class);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertMessageContains(ex,
+                                  "Advise method org.apache.tapestry5.ioc.NonVoidAdvisorMethodModule.adviseFoo(MethodAdviceReciever)",
+                                  "does not return void.");
+        }
+    }
+
+    /**
+     * TAP5-60
+     */
+    @Test
+    public void advisor_methods_must_take_a_method_advisor_parameter()
+    {
+        try
+        {
+            buildRegistry(AdviceMethodMissingAdvisorParameterModule.class);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertMessageContains(ex,
+                                  "Advise method org.apache.tapestry5.ioc.AdviceMethodMissingAdvisorParameterModule.adviseBar()",
+                                  "must take a parameter of type org.apache.tapestry5.ioc.MethodAdviceReciever.");
+        }
+    }
+
+    /**
+     * TAP5-60
+     */
+    @Test
+    public void advise_services()
+    {
+        Registry r = buildRegistry(AdviceDemoModule.class);
+
+        Greeter g = r.getService(Greeter.class);
+
+        assertEquals(g.getGreeting(), "ADVICE IS EASY!");
+    }
 }

Added: 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=737609&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/NonVoidAdvisorMethodModule.java Sun Jan 25 23:40:14 2009
@@ -0,0 +1,23 @@
+// 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;
+
+public class NonVoidAdvisorMethodModule
+{
+    public static String adviseFoo(MethodAdviceReciever methodAdviceReciever)
+    {
+        return "Never Called";
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImplTest.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImplTest.java Sun Jan 25 23:40:14 2009
@@ -17,7 +17,7 @@
 import org.apache.tapestry5.ioc.ModuleBuilderSource;
 import org.apache.tapestry5.ioc.OperationTracker;
 import org.apache.tapestry5.ioc.ServiceResources;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.easymock.EasyMock;
 import org.slf4j.Logger;
 import org.testng.annotations.Test;
 
@@ -61,10 +61,12 @@
 
         train_isDebugEnabled(logger, true);
 
-        logger.debug(IOCMessages.invokingMethod(InternalUtils.asString(m, getClassFactory())));
+        logger.debug(EasyMock.contains(
+                "Invoking method org.apache.tapestry5.ioc.internal.ServiceDecoratorFixture.decoratorReturnsInterceptor(Class, Object)"));
 
         replay();
 
+
         // Check that the delegate gets passed in; check that the return value of the
         // decorator method is the return value of the ServiceDecorator.
 
@@ -121,20 +123,24 @@
 
         train_isDebugEnabled(logger, false);
 
-        logger.warn(IOCMessages.decoratorReturnedWrongType(
-                m,
-                SERVICE_ID,
-                fixture.interceptorToReturn,
-                FieService.class));
 
         replay();
 
         ServiceDecoratorImpl decorator = new ServiceDecoratorImpl(m, source, resources,
                                                                   getClassFactory());
 
-        Object interceptor = decorator.createInterceptor(fixture.expectedDelegate);
+        try
+        {
+            decorator.createInterceptor(fixture.expectedDelegate);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertMessageContains(ex,
+                                  "Decorator method org.apache.tapestry5.ioc.internal.ServiceDecoratorFixture.decoratorUntyped(Object)",
+                                  "(invoked for service 'ioc.Fie') returned FoeService, which is not assignable to the org.apache.tapestry5.ioc.internal.FieService service interface.");
 
-        assertNull(interceptor);
+        }
 
         verify();
     }
@@ -167,8 +173,9 @@
         }
         catch (RuntimeException ex)
         {
-            assertEquals(ex.getMessage(), IOCMessages.decoratorMethodError(m, SERVICE_ID, ex
-                    .getCause()));
+            assertMessageContains(ex,
+                                  "Exception invoking method org.apache.tapestry5.ioc.internal.ServiceDecoratorFixture.decoratorThrowsException(Object)",
+                                  "Ouch!");
 
             Throwable cause = ex.getCause();
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImplTest.java?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/LoggingDecoratorImplTest.java Sun Jan 25 23:40:14 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.
@@ -89,7 +89,7 @@
 
     private LoggingDecoratorImpl newLoggingDecorator()
     {
-        return new LoggingDecoratorImpl(aspectDecorator, new ExceptionTrackerImpl());
+        return new LoggingDecoratorImpl(aspectDecorator, new LoggingAdvisorImpl(new ExceptionTrackerImpl()));
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/resources/log4j.properties?rev=737609&r1=737608&r2=737609&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/resources/log4j.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/resources/log4j.properties Sun Jan 25 23:40:14 2009
@@ -26,5 +26,7 @@
 log4j.category.tapestry.ioc.ClassFactory=error
 
 log4j.category.org.apache.tapestry5.ioc.FredModule=debug
+log4j.category.org.apache.tapestry5.ioc.AdviceDemoModule.Greeter=debug
+