tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r961168 [4/5] - in /websites/production/tapestry/content: ./ cache/
Date Sat, 08 Aug 2015 17:20:05 GMT
Modified: websites/production/tapestry/content/tapestry-ioc-decorators.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-decorators.html (original)
+++ websites/production/tapestry/content/tapestry-ioc-decorators.html Sat Aug  8 17:20:04 2015
@@ -31,8 +31,6 @@
   <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
   <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
   <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
   <script type="text/javascript">
   SyntaxHighlighter.defaults['toolbar'] = false;
   SyntaxHighlighter.all();
@@ -62,43 +60,13 @@
 <div class="clearer"></div>
 
   <div id="breadcrumbs">
-        <a href="index.html">Apache Tapestry</a>&nbsp;&gt;&nbsp;<a href="documentation.html">Documentation</a>&nbsp;&gt;&nbsp;<a href="user-guide.html">User Guide</a>&nbsp;&gt;&nbsp;<a href="ioc.html">IoC</a>&nbsp;&gt;&nbsp;<a href="tapestry-ioc-decorators.html">Tapestry IoC Decorators</a>
+        <a href="index.html">Apache Tapestry</a>&nbsp;&gt;&nbsp;<a href="documentation.html">Documentation</a>&nbsp;&gt;&nbsp;<a href="user-guide.html">User Guide</a>&nbsp;&gt;&nbsp;<a href="ioc.html">IOC</a>&nbsp;&gt;&nbsp;<a href="tapestry-ioc-decorators.html">Tapestry IoC Decorators</a>
     <a class="edit" title="Edit this page (requires approval -- just ask on the mailing list)" href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=23338481">edit</a>
   </div>
 
 <div id="content">
-<div id="ConfluenceContent">
-
-<h1 id="TapestryIoCDecorators-TapestryIoCDecorators">Tapestry IoC Decorators</h1>
-
-<div class="confluence-information-macro confluence-information-macro-information"><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
-<p>Starting with Tapestry 5.1, Service Decoration is augmented with <a shape="rect" href="service-advisors.html">Service Advice</a>. Advisors are  similar but more general, as they work on any service interface, which doesn't have to be known at build time. Decoration is used when the type of the service being decorated <em>is</em> known at build time, and involves supplying a new implementation of the service interface.</p></div></div>
-
-<p><em>Decoration</em> 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.</p>
-
-<p>Instead, a new object is placed <em>around</em> the existing object. The rest of the world sees this new object, termed an <strong>interceptor</strong>. The interceptor implements the same interface as the underlying object being decorated.</p>
-
-<p>A common example for this is the Java I/O library. The abstract InputStream base class has a very simple API for reading bytes from a stream (and a few other things). Subclasses of InputStream provide a wide array of other options such as buffering, encryption or decryption, as well as control over the source of data read by the stream. All of these <em>concerns</em> are encapsulated in different implementations of InputStream, and all can be connected together in a kind of pipeline, using the common InputStream API.</p>
-
-<p>Tapestry IoC uses a similar approach, where one or more interceptor objects, all implementing the service interface, are strung together. The service's proxy (responsible for just-in-time instantiation of the service implementation) is at one end of this pipeline, the core service implementation is at the other.</p>
-
-<p>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: <em>delegation</em>. An interceptor can even catch exceptions thrown by the underlying implementation and react to them. A sufficiently clever interceptor could retry a method if an exception is thrown, or could "soften" a checked exception by wrapping it in a RuntimeException.</p>
-
-<p>Decorators often are used in the context of <em>cross-cutting concerns</em>, such as logging or transaction management. This approach is a kind of <em>aspect oriented design</em>.</p>
-
-<p>One such cross cutting concern is lazy initialization of services. In Apache 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.</p>
-
-<p>Whereas the popular AspectJ framework changes the compiled bytecode of 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.</p>
-
-<p>It is also common to have <em>multiple</em> 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.</p>
-
-<p>Decorations are driven by service decoration methods. Often, a reusable service exists to do the grunt work of creating and instantiating a new class.</p>
-
-<h1 id="TapestryIoCDecorators-ServiceDecorationMethods">Service Decoration Methods</h1>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-package org.example.myapp.services;
+<div id="ConfluenceContent"><div class="confluence-information-macro confluence-information-macro-information"><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Starting with Tapestry 5.1, Service Decoration is augmented with <a shape="rect" href="service-advisors.html">Service Advice</a>. Advisors are similar but more general, as they work on any service interface, which doesn't have to be known at build time. Decoration is used when the type of the service being decorated <em>is</em> known at build time, and involves supplying a new implementation of the service interface.</p></div></div><p><em>Decoration</em> 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.</p><p>Instead, a new object is placed <em>around</em> the existing object. The rest of the world sees this new object, terme
 d an <strong>interceptor</strong>. The interceptor implements the same interface as the underlying object being decorated.</p><p>A common example for this is the Java I/O library. The abstract InputStream base class has a very simple API for reading bytes from a stream (and a few other things). Subclasses of InputStream provide a wide array of other options such as buffering, encryption or decryption, as well as control over the source of data read by the stream. All of these <em>concerns</em> are encapsulated in different implementations of InputStream, and all can be connected together in a kind of pipeline, using the common InputStream API.</p><p>Tapestry IoC uses a similar approach, where one or more interceptor objects, all implementing the service interface, are strung together. The service's proxy (responsible for just-in-time instantiation of the service implementation) is at one end of this pipeline, the core service implementation is at the other.</p><p>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: <em>delegation</em>. An interceptor can even catch exceptions thrown by the underlying implementation and react to them. A sufficiently clever interceptor could retry a method if an exception is thrown, or could "soften" a checked exception by wrapping it in a RuntimeException.</p><p>Decorators often are used in the context of <em>cross-cutting concerns</em>, such as logging or transaction management. This approach is a kind of <em>aspect oriented design</em>.</p><p>One such cross cutting concern is lazy initialization of services. In Apache 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.</p><p>Whereas the popular AspectJ fra
 mework changes the compiled bytecode of 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.</p><p>It is also common to have <em>multiple</em> 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.</p><p>Decorations are driven by service decoration methods. Often, a reusable service exists to do the grunt work of creating and instantiating a new class.</p><h1 id="TapestryIoCDecorators-ServiceDecorationMethods">Service Decoration Methods</h1><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">package org.example.myapp.services;
 
 import org.apache.tapestry5.ioc.services.LoggingDecorator;
 import org.slf4j.Logger;
@@ -118,35 +86,13 @@ public class MyAppModule
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
 }</pre>
-</div></div>
-
-<p>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.</p>
-
-<p>We are using the parameterized types here (the &lt;T&gt;), to reinforce the fact that the delegate object passed in (which will be the core service implementation, or some other interceptor) must implement the service interface, and that the decorator method must return an instance of the service interface.</p>
-
-<p>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 (after type erasure, the <code>T delegate</code> parameter becomes <code>Object delegate</code>).</p>
-
-<p>In the above example, the decorator method receives 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.</p>
-
-<p>The "heavy lifting" is provided by the factory, which will create a new interceptor that logs method entry before delegating to the core service implementation. The interceptor will also log method parameters, return values, and even log exceptions.</p>
-
-<p>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.</p>
-
-<p>Alternately, when targetting services whose type is known at compile time, you may provide a parameter whose type matches the service interface. For example, decorateIndexer() will always be applied to the Indexer service, whose type (Indexer) is known. We could therefore rewrite decorateIndexer() as:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  public static Indexer decorateIndexer(Indexer delegate, Logger logger, LoggingDecorator decorator)
+</div></div><p>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.</p><p>We are using the parameterized types here (the &lt;T&gt;), to reinforce the fact that the delegate object passed in (which will be the core service implementation, or some other interceptor) must implement the service interface, and that the decorator method must return an instance of the service interface.</p><p>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 (after type erasure, the <code>T delegate</code> parameter be
 comes <code>Object delegate</code>).</p><p>In the above example, the decorator method receives 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.</p><p>The "heavy lifting" is provided by the factory, which will create a new interceptor that logs method entry before delegating to the core service implementation. The interceptor will also log method parameters, return values, and even log exceptions.</p><p>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.</p><p>Alternately, when targetting services whose type is known at compile time, you may provide a parameter whose type matches the service interface. For example, decorateIndexer() will always be applied to the Indexer service, whose type (Indexer) is known. We could therefore rewrite decorateIndexer() as:</p><div 
 class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  public static Indexer decorateIndexer(Indexer delegate, Logger logger, LoggingDecorator decorator)
   {
     return decorator.build(Indexer.class, delegate, "Indexer", logger);
   }</pre>
-</div></div>
-
-<p>Of course, nothing stops you from combining building with decorating inside the service builder method:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-package org.example.myapp.services;
+</div></div><p>Of course, nothing stops you from combining building with decorating inside the service builder method:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">package org.example.myapp.services;
 
 import org.apache.tapestry5.ioc.services.LoggingDecorator;
 import org.slf4j.Logger;
@@ -158,54 +104,16 @@ public class MyAppModule
     return decorator.build(Indexer.class, logger, new IndexerImpl());
   }
 }</pre>
-</div></div>
-
-<p>But as we'll see next, it's possible to have a single decorator method work on many different services by using annotations.</p>
-
-<h1 id="TapestryIoCDecorators-TargetingMultipleServices">Targeting Multiple Services</h1>
-
-<p>By using the @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Match.html">Match</a> annotation, you may identify which services are to be decorated.</p>
-
-<p>The value specified in the Match annotation is one or more patterns. These patterns are used to match services. Patterns take two forms: glob patterns and regular expressions.</p>
-
-<p>In a glob pattern, a "*" at the start or end of a string will match zero or more characters. Regular expressions provide a lot more matching power, but require a more involved syntax.</p>
-
-<p>In either case, the matching is case insensitive.</p>
-
-<p>For example, to target all the services in your module:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Match("*")
+</div></div><p>But as we'll see next, it's possible to have a single decorator method work on many different services by using annotations.</p><h1 id="TapestryIoCDecorators-TargetingMultipleServices">Targeting Multiple Services</h1><p>By using the @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Match.html">Match</a> annotation, you may identify which services are to be decorated.</p><p>The value specified in the Match annotation is one or more patterns. These patterns are used to match services. Patterns take two forms: glob patterns and regular expressions.</p><p>In a glob pattern, a "*" at the start or end of a string will match zero or more characters. Regular expressions provide a lot more matching power, but require a more involved syntax.</p><p>In either case, the matching is case insensitive.</p><p>For example, to target all the services in your module:</p><div class="code panel pdl" style="border-wi
 dth: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Match("*")
   public static &lt;T&gt; T decorateLogging(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
     LoggingDecorator decorator)
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }   </pre>
-</div></div>
-
-<p>You can use multiple patterns with @Match, in which case, the decorator will be applied to a service that matches <em>any</em> of the patterns. For instance, if you only wanted logging for your data access and business logic services, you might end up with <code>@Match("Data*", "*Logic")</code> (based, of course, on how you name your services).</p>
-
-<p>As the preceding example showed, a simple "glob" matching is supported, where a asterisk ('*') may be used at the start or end of the match string to match any number of characters. As elsewhere, matching is case insensitive.</p>
-
-<p>Thus, <code>@Match("*")</code> is dangerous, because it will match every service in every module.</p>
-
-<p><em>Note: It is not possible to decorate the services of the TapestryIOCModule.</em></p>
-
-<p><em>Note: Another idea will be other ways of matching services: base on inheritance of the service interface and/or based on the presence of particular class annotations on the service interface. None of this has been implemented yet, and can readily be accomplished inside the decorator method (which will return null if it decides the service doesn't need decoration).</em></p>
-
-<h1 id="TapestryIoCDecorators-OrderingofDecorators">Ordering of Decorators</h1>
-
-<p>In cases where multiple decorators will apply to a single service, you can control the order in which decorators are applied using an additional annotation: @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Order.html">Order</a>.</p>
-
-<p>This annotation allows any number of <a shape="rect" href="ordering-by-constraints.html">ordering constraints</a> to be specified for the decorator, to order it relative to any other decorators.</p>
-
-<p>For example, you almost always want logging decorators to come first, so:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Match("*")
+</div></div><p>You can use multiple patterns with @Match, in which case, the decorator will be applied to a service that matches <em>any</em> of the patterns. For instance, if you only wanted logging for your data access and business logic services, you might end up with <code>@Match("Data*", "*Logic")</code> (based, of course, on how you name your services).</p><p>As the preceding example showed, a simple "glob" matching is supported, where a asterisk ('*') may be used at the start or end of the match string to match any number of characters. As elsewhere, matching is case insensitive.</p><p>Thus, <code>@Match("*")</code> is dangerous, because it will match every service in every module.</p><p><em>Note: It is not possible to decorate the services of the TapestryIOCModule.</em></p><p><em>Note: Another idea will be other ways of matching services: base on inheritance of the service interface and/or based on the presence of particular class annotations on the service interface. None o
 f this has been implemented yet, and can readily be accomplished inside the decorator method (which will return null if it decides the service doesn't need decoration).</em></p><h1 id="TapestryIoCDecorators-OrderingofDecorators">Ordering of Decorators</h1><p>In cases where multiple decorators will apply to a single service, you can control the order in which decorators are applied using an additional annotation: @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Order.html">Order</a>.</p><p>This annotation allows any number of <a shape="rect" href="ordering-by-constraints.html">ordering constraints</a> to be specified for the decorator, to order it relative to any other decorators.</p><p>For example, you almost always want logging decorators to come first, so:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Match("*")
   @Order("before:*")
   public static &lt;T&gt; T decorateLogging(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -213,28 +121,13 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }   </pre>
-</div></div>
-
-<p>"before:*" indicates that this decorator should come before any decorator in <em>any</em> module.</p>
-
-<p><strong>Note:</strong> the ordering of decorators is in terms of the <em>effect</em> desired. Internally, the decorators are invoked last to first (since each once receives the "next" interceptor as its delegate). So the core service implementation is created (via a service builder method) and that is passed to the last decorator method. The interceptor created there is passed to the the next-to-last decorator method, and so forth.</p>
-
-<p>It should now be evident that the delegate passed into a decorator method is sometimes the core service implementation, and some times an interceptor object created by some other decorator method.</p>
+</div></div><p>"before:*" indicates that this decorator should come before any decorator in <em>any</em> module.</p><p><strong>Note:</strong> the ordering of decorators is in terms of the <em>effect</em> desired. Internally, the decorators are invoked last to first (since each once receives the "next" interceptor as its delegate). So the core service implementation is created (via a service builder method) and that is passed to the last decorator method. The interceptor created there is passed to the the next-to-last decorator method, and so forth.</p><p>It should now be evident that the delegate passed into a decorator method is sometimes the core service implementation, and some times an interceptor object created by some other decorator method.</p><h1 id="TapestryIoCDecorators-Annotationdrivendecorators">Annotation driven decorators</h1><p>
 
-<h1 id="TapestryIoCDecorators-Annotationdrivendecorators">Annotation driven decorators</h1>
-
-
-
-<div class="confluence-information-macro confluence-information-macro-information"><p class="title">Added in 5.2</p><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
+</p><div class="confluence-information-macro confluence-information-macro-information"><p class="title">Added in 5.2</p><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
 </div></div>
 <div style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;">
-</div>
-
-<p>Starting from version 5.2, Tapestry supports annotation-driven decorator methods. If the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Decorate.html">@Decorate</a> annotation is present, the decorator method can be arbitrary named, as shown in the following example.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Decorate
+<p>&#160;</p></div>Starting from version 5.2, Tapestry supports annotation-driven decorator methods. If the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Decorate.html">@Decorate</a> annotation is present, the decorator method can be arbitrary named, as shown in the following example.<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Decorate
   @Match("*DAO")
   public static &lt;T&gt; T byServiceId(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -243,15 +136,8 @@ public class MyAppModule
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
 </pre>
-</div></div>
-
-<p>The decorator above is applied to any service whose id matches the "*DAO" pattern.</p>
-
-<p>Alternatively, marker annotations can be placed on the decorate method to match a specific service.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Decorate
+</div></div><p>The decorator above is applied to any service whose id matches the "*DAO" pattern.</p><p>Alternatively, marker annotations can be placed on the decorate method to match a specific service.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Decorate
   @Blue
   public static &lt;T&gt; T byMarkerAnnotation(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -260,15 +146,8 @@ public class MyAppModule
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
 </pre>
-</div></div>
-
-<p>The decorator above is applied to any service that is marked by the @Blue annotation.</p>
-
-<p>By default, <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Decorate.html">@Decorate</a> annotation applies the decorator to any service matched by the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Match.html">@Match</a> or marker annotations. You can limit the matching to a single service interface, as shown in the following example.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Decorate(serviceInterface=MyService.class)
+</div></div><p>The decorator above is applied to any service that is marked by the @Blue annotation.</p><p>By default, <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Decorate.html">@Decorate</a> annotation applies the decorator to any service matched by the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Match.html">@Match</a> or marker annotations. You can limit the matching to a single service interface, as shown in the following example.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Decorate(serviceInterface=MyService.class)
   @Match("*DAO")
   public static &lt;T&gt; T byServiceId(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -276,13 +155,8 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }</pre>
-</div></div>
-
-<p>In the example above, the decorator is applied to any implementation of MyService interfaces whose id matches the "*DAO" pattern.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Decorate(serviceInterface=MyService.class)
+</div></div><p>In the example above, the decorator is applied to any implementation of MyService interfaces whose id matches the "*DAO" pattern.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">  @Decorate(serviceInterface=MyService.class)
   @Blue
   public static &lt;T&gt; T byMarkerAnnotation(Class&lt;T&gt; serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -291,35 +165,8 @@ public class MyAppModule
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
 </pre>
-</div></div>
-
-<p>The decorator above is applied to any implementation of the MyService interface that is marked by the @Blue annotation.</p>
-
-<h1 id="TapestryIoCDecorators-CreatingyourownDecorators">Creating your own Decorators</h1>
-
-<p>Decorators are a limited form of Aspect Oriented Programming, so we have borrowed some of that terminology here.</p>
-
-<p>A decorator exists to create an <em>interceptor</em>. The interceptor wraps around the service (because these interceptors can get chained, we talk about the "delegate" and not the "service").</p>
-
-<p>Each method of the interceptor will take <em>advice</em>. Advice is provided by a <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/MethodAdvice.html">MethodAdvice</a> instance. The sole method, <code>advise()</code>, receives an <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Invocation.html">Invocation</a>. MethodAdvice gives you a chance to see what the method invocation <em>is</em>; you can query the name of the method, and the types and values of the parameters.</p>
-
-<p>The MethodAdvice can override the parameters if necessary, then invoke <code>proceed()</code>. This call invokes the corresponding method on the original object, the delegate.</p>
-
-<p>If the method call throws a runtime exception, that exception is not caught. Your method advice can put a try ... catch block around the call to proceed() if interested in catching runtime exceptions.</p>
-
-<p>Checked exceptions are not thrown (since they are not part of the proceed() method's signature). Instead the invocation's <code>isFail()</code> method will return true. You can then retrieve the exception or override it.</p>
-
-<p>In the normal success case, you can ask for the return value and even override it before returning from the advise() method.</p>
-
-<p>In other words, you have total control. Your MethodAdvice can query or change parameters, decide whether it proceed into the original code, it can intercept exceptions that are thrown and replace them, and can query or even replace the return value.</p>
-
-<p>The <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/AspectDecorator.html">AspectDecorator</a> service is how you put your MethodAdvice into action.</p>
-
-<p>By way of an example, we'll show an implementation of the LoggingDecorator service:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-public class LoggingDecoratorImpl implements LoggingDecorator
+</div></div><p>The decorator above is applied to any implementation of the MyService interface that is marked by the @Blue annotation.</p><h1 id="TapestryIoCDecorators-CreatingyourownDecorators">Creating your own Decorators</h1><p>Decorators are a limited form of Aspect Oriented Programming, so we have borrowed some of that terminology here.</p><p>A decorator exists to create an <em>interceptor</em>. The interceptor wraps around the service (because these interceptors can get chained, we talk about the "delegate" and not the "service").</p><p>Each method of the interceptor will take <em>advice</em>. Advice is provided by a <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/MethodAdvice.html">MethodAdvice</a> instance. The sole method, <code>advise()</code>, receives an <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Invocation.html">Invocation</a>. MethodAdvic
 e gives you a chance to see what the method invocation <em>is</em>; you can query the name of the method, and the types and values of the parameters.</p><p>The MethodAdvice can override the parameters if necessary, then invoke <code>proceed()</code>. This call invokes the corresponding method on the original object, the delegate.</p><p>If the method call throws a runtime exception, that exception is not caught. Your method advice can put a try ... catch block around the call to proceed() if interested in catching runtime exceptions.</p><p>Checked exceptions are not thrown (since they are not part of the proceed() method's signature). Instead the invocation's <code>isFail()</code> method will return true. You can then retrieve the exception or override it.</p><p>In the normal success case, you can ask for the return value and even override it before returning from the advise() method.</p><p>In other words, you have total control. Your MethodAdvice can query or change parameters, deci
 de whether it proceed into the original code, it can intercept exceptions that are thrown and replace them, and can query or even replace the return value.</p><p>The <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/AspectDecorator.html">AspectDecorator</a> service is how you put your MethodAdvice into action.</p><p>By way of an example, we'll show an implementation of the LoggingDecorator service:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class LoggingDecoratorImpl implements LoggingDecorator
 {
     private final AspectDecorator aspectDecorator;
 
@@ -374,18 +221,7 @@ public class LoggingDecoratorImpl implem
                                                     serviceInterface.getName()));
     }
 }</pre>
-</div></div>
-
-<p><em>The actual code has been refactored slightly since this documentation was written.</em></p>
-
-<p>Most of the logging logic occurs inside the ServiceLogger object, the MethodAdvice exists to call the right methods at the right time. A Logger doesn't <em>change</em> parameter values (or thrown exceptions, or the result), it just captures and logs the data.</p>
-
-<p>Notice that for runtime exceptions, we catch the exception, log it, and rethrow it.</p>
-
-<p>For checked exceptions, we use isFail() and getThrown().</p>
-
-<p>The AspectDecorator service can also be used in more complicated ways: it is possible to only advise some of the methods and not others, or use different advice for different methods. Check the JavaDoc for more details.</p>
-</div>
+</div></div><p><em>The actual code has been refactored slightly since this documentation was written.</em></p><p>Most of the logging logic occurs inside the ServiceLogger object, the MethodAdvice exists to call the right methods at the right time. A Logger doesn't <em>change</em> parameter values (or thrown exceptions, or the result), it just captures and logs the data.</p><p>Notice that for runtime exceptions, we catch the exception, log it, and rethrow it.</p><p>For checked exceptions, we use isFail() and getThrown().</p><p>The AspectDecorator service can also be used in more complicated ways: it is possible to only advise some of the methods and not others, or use different advice for different methods. Check the JavaDoc for more details.</p><p>&#160;</p><p></p></div>
 </div>
 
 <div class="clearer"></div>

Modified: websites/production/tapestry/content/tapestry-ioc-modules.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-modules.html (original)
+++ websites/production/tapestry/content/tapestry-ioc-modules.html Sat Aug  8 17:20:04 2015
@@ -31,8 +31,6 @@
   <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
   <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
   <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
   <script type="text/javascript">
   SyntaxHighlighter.defaults['toolbar'] = false;
   SyntaxHighlighter.all();
@@ -62,35 +60,13 @@
 <div class="clearer"></div>
 
   <div id="breadcrumbs">
-        <a href="index.html">Apache Tapestry</a>&nbsp;&gt;&nbsp;<a href="documentation.html">Documentation</a>&nbsp;&gt;&nbsp;<a href="user-guide.html">User Guide</a>&nbsp;&gt;&nbsp;<a href="ioc.html">IoC</a>&nbsp;&gt;&nbsp;<a href="tapestry-ioc-modules.html">Tapestry IoC Modules</a>
+        <a href="index.html">Apache Tapestry</a>&nbsp;&gt;&nbsp;<a href="documentation.html">Documentation</a>&nbsp;&gt;&nbsp;<a href="user-guide.html">User Guide</a>&nbsp;&gt;&nbsp;<a href="ioc.html">IOC</a>&nbsp;&gt;&nbsp;<a href="tapestry-ioc-modules.html">Tapestry IoC Modules</a>
     <a class="edit" title="Edit this page (requires approval -- just ask on the mailing list)" href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=23338484">edit</a>
   </div>
 
 <div id="content">
-<div id="ConfluenceContent">
-
-<h1 id="TapestryIoCModules-TapestryIoCModules">Tapestry IoC Modules</h1>
-
-<p>You inform Tapestry about your services and contributions by providing a module class.</p>
-
-<p>The module class is a plain Java class. A system of annotations and naming conventions allow Tapestry to determine what services are provided by the module.</p>
-
-<p>A module class exists for the following reasons:</p>
-
-<ul><li>To <em>bind</em> service interfaces to service implementations</li><li>To contribute configuration data <em>into</em> services</li><li>To <em>decorate</em> services by providing <em>interceptors</em> around them</li><li>To provide explicit code for building a service</li><li>To set a default <em>marker</em> for all services defined in the module</li></ul>
-
-
-<p>All public methods of a module class must be meaningful to Tapestry (be one of the categories above). Any extra public methods result in startup exceptions (because the method may contain a typo).</p>
-
-<h1 id="TapestryIoCModules-ServiceBuilderMethods">Service Builder Methods</h1>
-
-<p>Service builder methods were the original way to define a service and provide the logic to construct it; although this is now more commonly (and succinctly) accomplished using the bind() method, there are still many cases where service builder methods are useful.</p>
-
-<p>Service builder methods are public methods. They are often static. Here's a trivial example:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-package org.example.myapp.services;
+<div id="ConfluenceContent"><p>You inform Tapestry about your services and contributions by providing a <strong>module</strong> class.</p><p>The module class is a plain Java class that you create to inform Tapestry about your services and contributions.</p><p>A system of annotations and naming conventions allow Tapestry to determine what services are provided by the module.</p><p>A module class exists for the following reasons:</p><ul><li>To <em>bind</em> service interfaces to service implementations</li><li>To contribute configuration data <em>into</em> services</li><li>To <em>decorate</em> services by providing <em>interceptors</em> around them</li><li>To provide explicit code for building a service</li><li>To set a default <em>marker</em> for all services defined in the module</li></ul><p>All public methods of a module class must be meaningful to Tapestry (be one of the categories above). Any extra public methods result in startup exceptions (because the method may contain a typo
 ).</p><h1 id="TapestryIoCModules-ServiceBuilderMethods">Service Builder Methods</h1><p>Service builder methods were the original way to define a service and provide the logic to construct it; although this is now more commonly (and succinctly) accomplished using the bind() method, there are still many cases where service builder methods are useful.</p><p>Service builder methods are public methods. They are often static. Here's a trivial example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">package org.example.myapp.services;
 
 public class MyAppModule
 {
@@ -99,31 +75,8 @@ public class MyAppModule
     return new IndexerImpl();
   }
 }</pre>
-</div></div>
-
-<p>Any public method (static or instance) whose name starts with "build" is a service builder method, implicitly defining a service within the module.</p>
-
-<p>Here we're defining a service around the Indexer service interface (presumably also in the org.example.myapp.services package).</p>
-
-<p>Every service has a unique id, used to identify it throughout the Registry of services (the Registry is the combined sum of all services from all modules). If you don't provide an explicit service id, as in this example, the service id is drawn from the return type; this service has an id of "Indexer".</p>
-
-<p>You can give a service an explicit id by adding it to the method name: buildIndexer(). This is useful when you do not want the service id to match the service interface name (for example, when you have different services that implement the same interface), or when you need to avoid name collisions on the method name (Java allows only a single method with a given name and set of parameters, even if the return types are different, so if you have two different service builder methods that take the same parameters, you should give them explicit service ids in the method name).</p>
-
-<p>Tapestry IoC is <a shape="rect" href="case-insensitivity.html">case insensitive</a>; later we can refer to this service as "indexer" or "INDEXER" or any variation thereof, and connect to this service.</p>
-
-<p>Service ids must be unique; if another module contributes a service with the id "Indexer" (or any case variation thereof) a runtime exception will occur when the Registry is created.</p>
-
-<p>We could extend this example by adding additional service builder methods, or by showing how to inject dependencies. See <a shape="rect" href="defining-tapestry-ioc-services.html">the service documentation</a> for more details.</p>
-
-<h1 id="TapestryIoCModules-AutobuildingServices">Autobuilding Services</h1>
-
-<p>Main article: <a shape="rect" href="defining-tapestry-ioc-services.html">Defining Tapestry IOC Services</a></p>
-
-<p>An alternate, and usually preferred, way to define a service is via a module's bind() method. The previous example can be rewritten as:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-package org.example.myapp.services;
+</div></div><p>Any public method (static or instance) whose name starts with "build" is a service builder method, implicitly defining a service within the module.</p><p>Here we're defining a service around the Indexer service interface (presumably also in the org.example.myapp.services package).</p><p>Every service has a unique id, used to identify it throughout the Registry of services (the Registry is the combined sum of all services from all modules). If you don't provide an explicit service id, as in this example, the service id is drawn from the return type; this service has an id of "Indexer".</p><p>You can give a service an explicit id by adding it to the method name: buildIndexer(). This is useful when you do not want the service id to match the service interface name (for example, when you have different services that implement the same interface), or when you need to avoid name collisions on the method name (Java allows only a single method with a given name and set of par
 ameters, even if the return types are different, so if you have two different service builder methods that take the same parameters, you should give them explicit service ids in the method name).</p><p>Tapestry IoC is <a shape="rect" href="case-insensitivity.html">case insensitive</a>; later we can refer to this service as "indexer" or "INDEXER" or any variation thereof, and connect to this service.</p><p>Service ids must be unique; if another module contributes a service with the id "Indexer" (or any case variation thereof) a runtime exception will occur when the Registry is created.</p><p>We could extend this example by adding additional service builder methods, or by showing how to inject dependencies. See <a shape="rect" href="defining-tapestry-ioc-services.html">the service documentation</a> for more details.</p><h1 id="TapestryIoCModules-AutobuildingServices">Autobuilding Services</h1><p>Main article: <a shape="rect" href="defining-tapestry-ioc-services.html">Defining Tapestry
  IOC Services</a></p><p>An alternate, and usually preferred, way to define a service is via a module's bind() method. The previous example can be rewritten as:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">package org.example.myapp.services;
 
 import org.apache.tapestry5.ioc.ServiceBinder;
 
@@ -134,27 +87,8 @@ public class MyAppModule
      binder.bind(Indexer.class, IndexerImpl.class);
   }
 }</pre>
-</div></div>
-
-<p>For more details, see see <a shape="rect" href="defining-tapestry-ioc-services.html">Defining Tapestry IOC Services</a>. In most cases, autobuilding is the <em>preferred</em> approach.</p>
-
-<p>Generally speaking, you should always bind and autobuild your services. The only exceptions are when:</p>
-
-<ul><li>You wish to do more than just instantiate a class; for example, to register the class as an event listener with some other service.</li><li>There is <em>no implementation class</em>; in some cases, you can create your implementation on the fly using JDK dynamic proxies or bytecode generation.</li></ul>
-
-
-<p>The bind() method must be static; an exception is thrown if the bind() method exists but is an instance method.</p>
-
-<h1 id="TapestryIoCModules-Cacheing_ServicesCachingServices"><span class="confluence-anchor-link" id="TapestryIoCModules-Cacheing_Services"></span>Caching Services</h1>
-
-<p>You will occasionally find yourself in the position of injecting the same services into your service builder or service decorator methods repeatedly (this occurs much less often since the introduction of service autobuilding). This can result in quite a bit of redundant typing. Less code is better code, so as an alternative, you may define a <em>constructor</em> for your module that accepts annotated parameters (as with <a shape="rect" href="defining-tapestry-ioc-services.html">service builder injection</a>).</p>
-
-<p>This gives you a chance to store common services in instance variables for later use inside service builder methods.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-
-public class MyModule
+</div></div><p>For more details, see see <a shape="rect" href="defining-tapestry-ioc-services.html">Defining Tapestry IOC Services</a>. In most cases, autobuilding is the <em>preferred</em> approach.</p><p>Generally speaking, you should always bind and autobuild your services. The only exceptions are when:</p><ul><li>You wish to do more than just instantiate a class; for example, to register the class as an event listener with some other service.</li><li>There is <em>no implementation class</em>; in some cases, you can create your implementation on the fly using JDK dynamic proxies or bytecode generation.</li></ul><p>The bind() method must be static; an exception is thrown if the bind() method exists but is an instance method.</p><h1 id="TapestryIoCModules-Cacheing_ServicesCachingServices"><span class="confluence-anchor-link" id="TapestryIoCModules-Cacheing_Services"></span>Caching Services</h1><p>You will occasionally find yourself in the position of injecting the same services int
 o your service builder or service decorator methods repeatedly (this occurs much less often since the introduction of service autobuilding). This can result in quite a bit of redundant typing. Less code is better code, so as an alternative, you may define a <em>constructor</em> for your module that accepts annotated parameters (as with <a shape="rect" href="defining-tapestry-ioc-services.html">service builder injection</a>).</p><p>This gives you a chance to store common services in instance variables for later use inside service builder methods.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyModule
 {   
   private final JobScheduler scheduler;
   private final FileSystem fileSystem;
@@ -174,55 +108,13 @@ public class MyModule
     return indexer;
   }
 }</pre>
-</div></div>
-
-<p>Notice that we've switched from <em>static</em> methods to <em>instance</em> methods. Since the builder methods are not static, the MyModule class will be instantiated so that the methods may be invoked. The constructor receives two common dependencies, which are stored into instance fields that may later be used inside service builder methods such as buildIndexer().</p>
-
-<p>This approach is far from required; all the builder methods of your module can be static if you wish. It is used when you have many common dependencies and wish to avoid defining those dependencies as parameters to multiple methods.</p>
-
-<p>Tapestry IoC automatically resolves the parameter type (JobScheduler and FileSystem, in the example) to the corresponding services that implement that type. When there's more than one service that implements the service interface, you'll get an error (but additional annotations and configuration can be used to ensure the correct service injected).</p>
-
-<p>For modules, there are two additional parameter types that are used to refer to <em>resources</em> that can be provided to the module instance (rather than <em>services</em> which may be injected).</p>
-
-<ul><li><a shape="rect" class="external-link" href="http://www.slf4j.org/api/org/slf4j/Logger.html" >org.slf4j.Logger</a>: logger for the module (derived from the module's class name)</li><li><a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/ObjectLocator.html">ObjectLocator</a>: access to other services<br clear="none">
-Note that the fields are final: this is important. Tapestry IoC is thread-safe and you largely never have to think about concurrency issues. But in a busy application, different services may be built by different threads simultaneously. Each module class is a singleton, instantiated at most once, and making these fields final ensures that the values are available across multiple threads. Refer to Brian Goetz's <a shape="rect" class="external-link" href="http://www.javaconcurrencyinpractice.com/" >Java Concurrency in Practice</a> for a more complete explanation of the relationship between final fields, constructors, and threads ... or just trust us!</li></ul>
-
-
-<p>Care should be taken with this approach: in some circumstances, you may force a situation in which the module constructor is dependent on itself. For example, if you invoke a method on any injected services defined within the same module from the module class' constructor, then the service implementation will be needed. Creating service implementations requires the module builder instance ... that's a recursive reference.</p>
-
-<p>Tapestry detects these scenarios and throws a runtime exception to prevent an endless loop.</p>
-
-<h1 id="TapestryIoCModules-ModuleClassImplementationNotes">Module Class Implementation Notes</h1>
-
-<p>Module classes are designed to be very, very simple to implement.</p>
-
-<p>Again, keep the methods very simple. Use <a shape="rect" href="defining-tapestry-ioc-services.html">parameter injection</a> to gain access to the dependencies you need.</p>
-
-<p>Be careful about inheritance. Tapestry will see all <em>public</em> methods, even those inherited from base classes. Tapestry <em>only</em> sees public methods.</p>
-
-<p>By convention, module class names end in Module and are final classes.</p>
-
-<p>You don't <em>have</em> to define your methods as static. The use of static methods is only absolutely necessary in a few cases, where the constructor for a module is dependent on contributions from the same module (this creates a chicken-and-the-egg situation that is resolved through static methods).</p>
-
-<h1 id="TapestryIoCModules-DefaultMarker">Default Marker</h1>
-
-<p>Services are often referenced by a particular marker interface on the method or constructor parameter. Tapestry will use the intersection of services with that exact marker and assignable by type to find a unique service to inject.</p>
-
-<p>Often, all services in a module should share a marker, this can be specified with a @Marker annotation on the module class. For example, the TapestryIOCModule:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-@Marker(Builtin.class)
+</div></div><p>Notice that we've switched from <em>static</em> methods to <em>instance</em> methods. Since the builder methods are not static, the MyModule class will be instantiated so that the methods may be invoked. The constructor receives two common dependencies, which are stored into instance fields that may later be used inside service builder methods such as buildIndexer().</p><p>This approach is far from required; all the builder methods of your module can be static if you wish. It is used when you have many common dependencies and wish to avoid defining those dependencies as parameters to multiple methods.</p><p>Tapestry IoC automatically resolves the parameter type (JobScheduler and FileSystem, in the example) to the corresponding services that implement that type. When there's more than one service that implements the service interface, you'll get an error (but additional annotations and configuration can be used to ensure the correct service injected).</p><p>For modules
 , there are two additional parameter types that are used to refer to <em>resources</em> that can be provided to the module instance (rather than <em>services</em> which may be injected).</p><ul><li><a shape="rect" class="external-link" href="http://www.slf4j.org/api/org/slf4j/Logger.html" >org.slf4j.Logger</a>: logger for the module (derived from the module's class name)</li><li><a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/ObjectLocator.html">ObjectLocator</a>: access to other services<br clear="none"> Note that the fields are final: this is important. Tapestry IoC is thread-safe and you largely never have to think about concurrency issues. But in a busy application, different services may be built by different threads simultaneously. Each module class is a singleton, instantiated at most once, and making these fields final ensures that the values are available across multiple threads. Refer to Brian Goetz's <a shape
 ="rect" class="external-link" href="http://www.javaconcurrencyinpractice.com/" >Java Concurrency in Practice</a> for a more complete explanation of the relationship between final fields, constructors, and threads ... or just trust us!</li></ul><p>Care should be taken with this approach: in some circumstances, you may force a situation in which the module constructor is dependent on itself. For example, if you invoke a method on any injected services defined within the same module from the module class' constructor, then the service implementation will be needed. Creating service implementations requires the module builder instance ... that's a recursive reference.</p><p>Tapestry detects these scenarios and throws a runtime exception to prevent an endless loop.</p><h1 id="TapestryIoCModules-ModuleClassImplementationNotes">Module Class Implementation Notes</h1><p>Module classes are designed to be very, very simple to implement.</p><p>Again, keep the methods very simple. Use <a shape="
 rect" href="defining-tapestry-ioc-services.html">parameter injection</a> to gain access to the dependencies you need.</p><p>Be careful about inheritance. Tapestry will see all <em>public</em> methods, even those inherited from base classes. Tapestry <em>only</em> sees public methods.</p><p>By convention, module class names end in Module and are final classes.</p><p>You don't <em>have</em> to define your methods as static. The use of static methods is only absolutely necessary in a few cases, where the constructor for a module is dependent on contributions from the same module (this creates a chicken-and-the-egg situation that is resolved through static methods).</p><h1 id="TapestryIoCModules-DefaultMarker">Default Marker</h1><p>Services are often referenced by a particular marker interface on the method or constructor parameter. Tapestry will use the intersection of services with that exact marker and assignable by type to find a unique service to inject.</p><p>Often, all services i
 n a module should share a marker, this can be specified with a @Marker annotation on the module class. For example, the TapestryIOCModule:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Marker(Builtin.class)
 public final class TapestryIOCModule
 {
   . . .</pre>
-</div></div>
-
-<p>This references a particular annotation class, Builtin:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-@Target(
+</div></div><p>This references a particular annotation class, Builtin:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Target(
 { PARAMETER, FIELD })
 @Retention(RUNTIME)
 @Documented
@@ -230,21 +122,8 @@ public @interface Builtin
 {
 
 }</pre>
-</div></div>
-
-<p>The annotation can be applied to method and constructor parameters, for use within the IoC container. It can also be applied to fields, though this is specific to the Tapestry web framework.</p>
-
-<h1 id="TapestryIoCModules-FieldInjection">Field Injection</h1>
-
-<p>The @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Inject.html">Inject</a> and @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/InjectService.html">InjectService</a> annotations may be used on instance fields of a module class, as an alternative to passing dependencies of the module in via the constructor.</p>
-
-<p>Caution: injection via fields uses reflection to make the fields accessible. In addition, it may not be as thread-safe as using the constructor to assign to final fields.</p>
-
-<p>Using this style, the previous example of a module class may be rewritten:</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-public class MyModule
+</div></div><p>The annotation can be applied to method and constructor parameters, for use within the IoC container. It can also be applied to fields, though this is specific to the Tapestry web framework.</p><h1 id="TapestryIoCModules-FieldInjection">Field Injection</h1><p>The @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Inject.html">Inject</a> and @<a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/InjectService.html">InjectService</a> annotations may be used on instance fields of a module class, as an alternative to passing dependencies of the module in via the constructor.</p><p>Caution: injection via fields uses reflection to make the fields accessible. In addition, it may not be as thread-safe as using the constructor to assign to final fields.</p><p>Using this style, the previous example of a module class may be rewritten:</p><div cl
 ass="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class MyModule
 {
   @Inject
   private JobScheduler scheduler;
@@ -261,8 +140,7 @@ public class MyModule
     return indexer;
   }
 }</pre>
-</div></div>
-</div>
+</div></div><p>&#160;</p><p></p></div>
 </div>
 
 <div class="clearer"></div>



Mime
View raw message