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 2006/07/09 02:34:07 UTC

svn commit: r420233 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/internal/ioc/ site/ site/apt/ioc/

Author: hlship
Date: Sat Jul  8 17:34:07 2006
New Revision: 420233

URL: http://svn.apache.org/viewvc?rev=420233&view=rev
Log:
Start documentating IoC decorators and interceptors.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/decorator.apt
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/index.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java?rev=420233&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java Sat Jul  8 17:34:07 2006
@@ -0,0 +1,35 @@
+// Copyright 2006 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.tapestry.internal.ioc;
+
+/**
+ * Like {@link org.apache.tapestry.internal.ioc.SingletonServiceLifecycle}, but does not generate a
+ * proxy. This is used for a few internal services inside the tapestry.ioc module and is needed for
+ * bootstrapping purposes (creating proxies requires the ClassFactory service, so we need a way to
+ * expose ClassFactory without generating a proxy for it).
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class PrimitiveServiceLifecycle extends SingletonServiceLifecycle
+{
+
+    /** Returns false. */
+    @Override
+    public boolean getCreateProxy()
+    {
+        return false;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/decorator.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/decorator.apt?rev=420233&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/decorator.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/decorator.apt Sat Jul  8 17:34:07 2006
@@ -0,0 +1,111 @@
+ ----
+ Tapestry IoC Decorators
+ ----
+ 
+Tapestry IoC Decorators
+
+  <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.
+  
+  Instead, a new object is placed <around> the existing object.  The rest of the world
+  sees this new object, termed an <<interceptor>>.  The interceptor implements the
+  same service interface as the underlying service.
+  
+  For each method in the service interface, the interceptor object can perform
+  some operations before and after re-invoking the same method on the
+  core service implementation.  This is another design pattern: <delegation>.  An interceptor
+  can even catch exceptions thrown by the underlying implementation and react to them.
+  
+  Decorators often are used in the context of <cross-cutting concerns>, such as logging or
+  transaction management. This approach is a kind of <aspect oriented design>.
+  
+  One such cross cutting concern is lazy initialization of services.  In HiveMind, services
+  are created only as needed, when a method of a service interface is first invoked.
+  This concern is supplied by the Tapestry IoC framework itself, but similar
+  concerns are easily implemented as decorations.
+  
+  Whereas the popular AspectJ framework changes your classes (it calls the process "weaving"),
+  with Tapestry IoC, the approach is to wrap your existing classes in new objects. These
+  wrapper objects are often dynamically created at runtime.
+  
+  It is also common to have <multiple> decorations on a single service. In this case,
+  a whole stack of interceptor objects will be created, each delegating to the next.
+  Tapestry IoC provides control over the order in which such decorations occur.
+  
+  Decorations are driven by service decoration methods. Often, a reusable service
+  exists to do the grunt work of creating and instantiating a new class.
+  
+Service Decoration Methods
+
++---------------------+
+package org.example.myapp.services;
+
+import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.services.LoggingInterceptorFactory;
+
+@Id("myapp")
+public class MyAppModule
+{
+  public Indexer buildIndexer()
+  {
+    return new IndexerImpl();
+  }
+  
+  public Object decorateIndexer(Object service, Class serviceInterface, Log serviceLog,
+    @InjectService("tapestry.ioc.LoggingInterceptorFactory")
+    LoggingInterceptorFactory factory)
+  {
+    return factory.createLoggingInterceptor(serviceInterface, serviceLog, service);
+  } 
+}
++---------------------+
+
+   The method decorateIndexer() is a service decorator method because it starts with the
+   word "decorate".  In this simple case, only the myapp.Indexer service will be decorated,
+   even if there are other services in this module or others ... this is because
+   of the name match ("decorateIndexer" and "buildIndexer"), but we'll shortly see how
+   annotations can be used to target many services for decoration.
+   
+   The values that may be provided to a decorator method are exactly the same as for a builder
+   method, with one addition:  The underlying service will be passed in
+   as a parameter of type java.lang.Object.  A decorator method must have one
+   parameter of type java.lang.Object for this purpose.
+   
+   In the above example, the decorator method recieves the core service implementation,
+   the service interface for the Indexer service, the Log for the Indexer service,
+   and an interceptor factory that generates logging interceptors.
+   
+   The "heavy lifting" is provided by the factory, which will create a new interceptor
+   that logs methods entry before delegating to the core service implementation. The interceptor
+   will also log method parameters, return values, and even log exceptions.
+   
+   The return value of the method is the new interceptor. You may return null if your
+   decorator method decides not to decorate the supplied service.
+   
+   Of course, nothing stops you from combining building with decorating inside
+   the service builder method:
+   
+   
++---------------------+
+package org.example.myapp.services;
+
+import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.services.LoggingInterceptorFactory;
+
+@Id("myapp")
+public class MyAppModule
+{
+  public Indexer buildIndexer(Class serviceInterface, Log serviceLog,
+    @InjectService("tapestry.ioc.LoggingInterceptorFactory")
+    LoggingInterceptorFactory factory)
+  {
+    return factory.createLoggingInterceptor(serviceInterface, serviceLog,  new IndexerImpl());
+  } 
+}
++---------------------+   
+
+  But as we'll see, its possible to have a single decorator method work on many different
+  services by using annotations.
+  
+  
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/index.apt?rev=420233&r1=420232&r2=420233&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/index.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/index.apt Sat Jul  8 17:34:07 2006
@@ -132,10 +132,11 @@
   The <<registry>> is the outside world's view of the modules and services. From the registry, it is possible to obtain
   a service, via its qualified id or by its service interface. 
     
-  Services may be <<intercepted>>.  Interceptors are new classes that implement the service interface, and wrap around the service implementation.
-  A service may have multiple interceptors, forming a chain of delegation.  
-  
-  Interceptors are defined by additional methods on the module builder. <TBD>.
+    
+  Services may be <<decorated>> by <<service decorator methods>>.  These methods create
+  <<interceptor>> objects that wrap around core service implementations, adding behavior such
+  as logging, security access, or transaction management.  Interceptors implement the same
+  service interface as the service.
   Control is given over the order in which interceptors are applied to a service.
   
   A service may have a <<configuration>>. The configuration is either a map, a collection, or an ordered list. The configuration is contructed

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt?rev=420233&r1=420232&r2=420233&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt Sat Jul  8 17:34:07 2006
@@ -50,6 +50,8 @@
 +-----------------------------------------------------------------------------------+
 package org.example.myapp.services;
 
+import org.apache.tapestry.ioc.annotations.Id;
+
 @Id("myapp")
 public class MyAppModule
 {

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt?rev=420233&r1=420232&r2=420233&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt Sat Jul  8 17:34:07 2006
@@ -18,6 +18,8 @@
 +-----------------------------------------------------------------------------------+
 package org.example.myapp.services;
 
+import org.apache.tapestry.ioc.annotations.Id;
+
 @Id("myapp")
 public class MyAppModule
 {

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml?rev=420233&r1=420232&r2=420233&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml Sat Jul  8 17:34:07 2006
@@ -54,6 +54,7 @@
             <item name="Introduction" href="ioc/index.html"/>
             <item name="Modules" href="ioc/module.html"/>
             <item name="Services" href="ioc/service.html"/>
+            <item name="Decorators" href="ioc/decorator.html"/>
         </menu>
                 
         ${reports}