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}