Modified: websites/production/tapestry/content/tapestry-ioc-configuration.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-configuration.html 
(original)
+++ websites/production/tapestry/content/tapestry-ioc-configuration.html Wed 
Sep 20 12:29:16 2017
@@ -27,6 +27,14 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <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>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,50 +75,134 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><strong>Tapestry IOC 
Configuration</strong> is the configuration of both the IOC services provided 
by Tapestry and those you write yourself. Both are configured in the same way: 
using Java, not XML.</p><parameter 
ac:name="style">float:right</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label = "configuration" and space 
= currentSpace()</parameter></rich-text-body><p>One of the key concepts in 
Tapestry IoC is <em>distributed configuration</em>. The <em>distributed</em> 
part refers to the fact that <em>any module</em> may configure a service. 
Distributed configuration is the key feature of Tapestry IoC that supports 
extensibility and modularity.</p><p>Modules configure a service by 
 <em>contributing</em> to service configurations. This may seem esoteric but is 
really pretty simple. We'll explain with an example.</p><p>Let's say you've 
written a bunch of different services, each of which does something specific 
for a particular type of file (identified by the file's extension), and each 
implements the same interface, which we'll call FileServicer. And now let's say 
you need a central service that selects the one of your FileServicer 
implementations based on a given file extension. You start by providing a <a  
href="defining-tapestry-ioc-services.html">service builder 
method</a>:</p><parameter ac:name="">java</parameter><plain-text-body>  public 
static FileServiceDispatcher 
buildFileServicerDispatcher(Map&lt;String,FileServicer&gt; contributions)
+                <div id="ConfluenceContent"><p><strong>Tapestry IOC 
Configuration</strong> is the configuration of both the IOC services provided 
by Tapestry and those you write yourself. Both are configured in the same way: 
using Java, not XML.</p><div class="aui-label" style="float:right" 
title="Related Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  
href="application-module-class-cheat-sheet.html">Application Module Class Cheat 
Sheet</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service 
Configurations</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="symbols.html">Symbols</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="tapestry-ioc-configuration.html">Tapestry 
IoC Configuration</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="response-compression.html">Response 
Compression</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="configuration.html">Configuration</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<p>One of the key concepts in Tapestry IoC is <em>distributed 
configuration</em>. The <em>distributed</em> part refers to the fact that 
<em>any module</em> may configure a service. Distributed configuration is the 
key feature of Tapestry IoC that supports extensibility and 
modularity.</p><p>Modules configure a service by <em>contributing</em> to 
service configurations. This may seem esoteric but is really pretty simple. 
We'll explain with an example.</p><p>Let's say you've written a bunch of 
different services, each of which does something specific for a particular type 
of file (identified by the file's extension), and each implements the same 
interface, which we'll call FileServicer. And now let's say you need a central 
service that selects the one of your FileServicer implementations based on a 
given file extension. You start by providing a <a  
href="defining-tapestry-ioc-services.html">service builder method</a>:</p><div 
class="code panel pdl" style="border-width: 1px;"><div clas
 s="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  public static FileServiceDispatcher 
buildFileServicerDispatcher(Map&lt;String,FileServicer&gt; contributions)
   {
     return new FileServiceDispatcherImpl(contributions);
-  } </plain-text-body><p>In order to provide a value for the contribution 
parameter, Tapestry will <em>collect</em> contributions from service 
contribution methods. It will ensure that the keys and values match the generic 
types shown (String for the key, FileServicer for the value). The map will be 
assembled and passed into the service builder method, and from there, into the 
FileServiceDispatcherImpl constructor.</p><p>So where do the values come from? 
Your service contributor methods, methods whose names start with 
"contribute":</p><parameter ac:name="">java</parameter><plain-text-body>  
public static void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
+  } </pre>
+</div></div><p>In order to provide a value for the contribution parameter, 
Tapestry will <em>collect</em> contributions from service contribution methods. 
It will ensure that the keys and values match the generic types shown (String 
for the key, FileServicer for the value). The map will be assembled and passed 
into the service builder method, and from there, into the 
FileServiceDispatcherImpl constructor.</p><p>So where do the values come from? 
Your service contributor methods, methods whose names start with 
"contribute":</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 void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
   {
     configuration.add("txt", new TextFileServicer());
     configuration.add("pdf", new PDFFileServicer());
-  }  </plain-text-body><p>Or, instead of instantiating those services 
ourselves, we could <a  href="injection-in-detail.html">inject</a> 
them:</p><parameter ac:name="">java</parameter><plain-text-body>  public static 
void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration,
+  }  </pre>
+</div></div><p>Or, instead of instantiating those services ourselves, we could 
<a  href="injection-in-detail.html">inject</a> them:</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 void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration,
   
     @InjectService("TextFileServicer") FileServicer textFileServicer,
     @InjectService("PDFFileServicer") FileServicer pdfFileServicer)
   {
     configuration.add("txt", textFileServicer);
     configuration.add("pdf", pdfFileServicer);
-  }  </plain-text-body><p>The <strong>extensibility</strong> comes from the 
fact that multiple modules may all contribute to the same service 
configuration:</p><parameter ac:name="">java</parameter><plain-text-body>  
public static void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
+  }  </pre>
+</div></div><p>The <strong>extensibility</strong> comes from the fact that 
multiple modules may all contribute to the same service configuration:</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 void 
contributeFileServicerDispatcher(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
   {
     configuration.add("doc", new WordFileServicer());
     configuration.add("ppt", new PowerPointFileServicer());
-  }  </plain-text-body><p>Now the FileServicerDispatcher builder method gets a 
Map with at least four entries in it.</p><p>Because Tapestry IoC is highly 
dynamic (it scans the visible JAR manifest files to identify module classes), 
the FileServicerDispatcher service may be in one module, and the other 
contributing modules (such as the one that contributes the Office file 
services) may be written at a much later date. With no change to the 
FileServicerDispatcher service or its module class, the new services "plug 
into" the overall solution, simply by having their JAR's on the runtime 
classpath.</p><h1 
id="TapestryIoCConfiguration-Namingconventionsvs.Annotations">Naming 
conventions vs. Annotations</h1><p>
+  }  </pre>
+</div></div><p>Now the FileServicerDispatcher builder method gets a Map with 
at least four entries in it.</p><p>Because Tapestry IoC is highly dynamic (it 
scans the visible JAR manifest files to identify module classes), the 
FileServicerDispatcher service may be in one module, and the other contributing 
modules (such as the one that contributes the Office file services) may be 
written at a much later date. With no change to the FileServicerDispatcher 
service or its module class, the new services "plug into" the overall solution, 
simply by having their JAR's on the runtime classpath.</p><h1 
id="TapestryIoCConfiguration-Namingconventionsvs.Annotations">Naming 
conventions vs. Annotations</h1><p>
 
 </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 class="error"><span class="error">Unknown macro: {div}</span> 
-<p>&#160;</p></div>If you prefer annotations over naming conventions you can 
use the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Contribute.html";>Contribute</a>
 annotation. As of version 5.2 this annotation that may be placed on a 
contributor method of a module instead of starting the methods name with 
"contribute". The value of the annotation is the type of the service to 
contribute into.<p>The primary reasons to use @Contribute and marker 
annotations is twofold:</p><ul><li>There is no longer a linkage between the 
contribution method name and the service id, which is much more refactoring 
safe: if you change the service interface name, or the ID of the service, your 
method will still be invoked when using @Contribute.</li></ul><ul><li>It makes 
it much easier for an <a  href="tapestry-ioc-configuration.html">override</a> 
of the service to get the configuration intended for the original 
service.</li></ul><p>The followin
 g example is an annotation-based alternative for the contribution method 
above.</p><parameter 
ac:name="">java</parameter><plain-text-body>@Contribute(FileServiceDispatcher.class)
+<p>&#160;</p></div>If you prefer annotations over naming conventions you can 
use the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Contribute.html";>Contribute</a>
 annotation. As of version 5.2 this annotation that may be placed on a 
contributor method of a module instead of starting the methods name with 
"contribute". The value of the annotation is the type of the service to 
contribute into.<p>The primary reasons to use @Contribute and marker 
annotations is twofold:</p><ul><li>There is no longer a linkage between the 
contribution method name and the service id, which is much more refactoring 
safe: if you change the service interface name, or the ID of the service, your 
method will still be invoked when using @Contribute.</li></ul><ul><li>It makes 
it much easier for an <a  href="tapestry-ioc-configuration.html">override</a> 
of the service to get the configuration intended for the original 
service.</li></ul><p>The followin
 g example is an annotation-based alternative for the contribution method 
above.</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;">@Contribute(FileServiceDispatcher.class)
 public static void 
arbitraryMethodName(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
 {
     configuration.add("doc", new WordFileServicer());
     configuration.add("ppt", new PowerPointFileServicer());
 }  
-</plain-text-body><p>If you have several implementations of a service 
interface, you have to disambiguate the services. For this purpose the marker 
annotations should be placed on the contributor method.</p><parameter 
ac:name="">java</parameter><plain-text-body>@Contribute(FileServiceDispatcher.class)
+</pre>
+</div></div><p>If you have several implementations of a service interface, you 
have to disambiguate the services. For this purpose the marker annotations 
should be placed on the contributor 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;">@Contribute(FileServiceDispatcher.class)
 @Red @Blue
 public static void 
arbitraryMethodName(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
 {
     configuration.add("doc", new WordFileServicer());
     configuration.add("ppt", new PowerPointFileServicer());
 }
-</plain-text-body><p>In this example, the method will only be invoked when 
constructing a service configuration where the service itself has both the Red 
and Blue marker annotations. Tapestry knows which annotations are marker 
annotations, and which marker annotations apply to the service, via the @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Marker.html";>Marker</a>
 annotation on the service implementation.</p><p>If the special @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Local.html";>Local</a>
 annotation is present, then the contribution is made only to the configuration 
of a service being constructed in the same module.</p><p>Note that it 
<em>is</em> possible for the same contribution method to be invoked to 
contribute to the configuration of multiple different services.</p><parameter 
ac:name="">java</parameter><plain-text-body>  @Contribute(FileServiceDisp
 atcher.class)
+</pre>
+</div></div><p>In this example, the method will only be invoked when 
constructing a service configuration where the service itself has both the Red 
and Blue marker annotations. Tapestry knows which annotations are marker 
annotations, and which marker annotations apply to the service, via the @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Marker.html";>Marker</a>
 annotation on the service implementation.</p><p>If the special @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Local.html";>Local</a>
 annotation is present, then the contribution is made only to the configuration 
of a service being constructed in the same module.</p><p>Note that it 
<em>is</em> possible for the same contribution method to be invoked to 
contribute to the configuration of multiple different services.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelConten
 t pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">  @Contribute(FileServiceDispatcher.class)
   @Local
   public static void 
arbitraryMethodName(MappedConfiguration&lt;String,FileServicer&gt; 
configuration)
   {
     configuration.add("doc", new WordFileServicer());
     configuration.add("ppt", new PowerPointFileServicer());
   }  
-</plain-text-body><h1 
id="TapestryIoCConfiguration-ConfigurationTypes">Configuration 
Types</h1><p>There are three different styles of configurations (with matching 
contributions):</p><ul><li><strong>Unordered Collection</strong> &#8211; 
Contributions are simply added in and order is not 
important.</li><li><strong>Ordered List</strong> &#8211; Contributions are 
provided as an ordered list. Contributions must establish the order by giving 
each contributed object a unique id, by establishing forward and backward 
dependencies between the values.</li><li><strong>Map</strong> &#8211; 
Contributions provide unique keys and corresponding values.</li></ul><h2 
id="TapestryIoCConfiguration-UnorderedCollection">Unordered Collection</h2><p>A 
service builder method can collect an unordered list of values by defining a 
parameter of type java.util.Collection. Further, you should parameterize the 
type of collection. Tapestry will identify the parameterized type and ensure 
that all contributions match
 .</p><p>One thing to remember is that the order in which contributions occur 
is unspecified. There will be a possibly large number of modules, each having 
zero or more methods that contribute into the service. The order in which these 
methods are invoked is unknown.</p><p>For example, here's a kind of Startup 
service that needs some Runnable objects. It doesn't care what order the 
Runnable objects are executed in.</p><parameter 
ac:name="">java</parameter><plain-text-body>  public static Runnable 
buildStartup(final Collection&lt;Runnable&gt; configuration)
+</pre>
+</div></div><h1 id="TapestryIoCConfiguration-ConfigurationTypes">Configuration 
Types</h1><p>There are three different styles of configurations (with matching 
contributions):</p><ul><li><strong>Unordered Collection</strong> &#8211; 
Contributions are simply added in and order is not 
important.</li><li><strong>Ordered List</strong> &#8211; Contributions are 
provided as an ordered list. Contributions must establish the order by giving 
each contributed object a unique id, by establishing forward and backward 
dependencies between the values.</li><li><strong>Map</strong> &#8211; 
Contributions provide unique keys and corresponding values.</li></ul><h2 
id="TapestryIoCConfiguration-UnorderedCollection">Unordered Collection</h2><p>A 
service builder method can collect an unordered list of values by defining a 
parameter of type java.util.Collection. Further, you should parameterize the 
type of collection. Tapestry will identify the parameterized type and ensure 
that all contributions match.</p><
 p>One thing to remember is that the order in which contributions occur is 
unspecified. There will be a possibly large number of modules, each having zero 
or more methods that contribute into the service. The order in which these 
methods are invoked is unknown.</p><p>For example, here's a kind of Startup 
service that needs some Runnable objects. It doesn't care what order the 
Runnable objects are executed in.</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 Runnable buildStartup(final 
Collection&lt;Runnable&gt; configuration)
   {
     return new Runnable()
     {
@@ -120,11 +212,15 @@ public static void arbitraryMethodName(M
           contribution.run();
       }
     };
-  }  </plain-text-body><p>Here we don't even need a separate class for the 
implementation, we use an inner class for the implementation. The point is, the 
configuration is provided to the builder method, which passes it along to the 
implementation of the service.</p><p>On the contribution side, a service 
contribution method sees a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Configuration.html";>Configuration</a>
 object:</p><parameter ac:name="">java</parameter><plain-text-body>  public 
static void contributeStartup(Configuration&lt;Runnable&gt; configuration)
+  }  </pre>
+</div></div><p>Here we don't even need a separate class for the 
implementation, we use an inner class for the implementation. The point is, the 
configuration is provided to the builder method, which passes it along to the 
implementation of the service.</p><p>On the contribution side, a service 
contribution method sees a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Configuration.html";>Configuration</a>
 object:</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 void 
contributeStartup(Configuration&lt;Runnable&gt; configuration)
   {
     configuration.add(new JMSStartup());
     configuration.add(new FileSystemStartup());
-  }    </plain-text-body><p>The Configuration interface defines just a single 
method: <code>add()</code>. This is very intentional: the only thing you can do 
is add new items. If we passed in a Collection, you might be tempted to check 
it for values, or remove them ... but that flies in the face of the fact that 
the order of execution of these service contribution methods is entirely 
unknown.</p><p>For readability, we've parameterized the configuration parameter 
of the method, constraining it to instances of java.lang.Runnable, so as to 
match the corresponding parameter. This is optional, but often very helpful. In 
any case, attempting to contribute an object that doesn't extend or implement 
the type (Runnable) will result in a runtime warning (and the value will be 
ignored).</p><p>Tapestry supports only this simple form of parameterized types. 
Java generics supports a wider form, "wildcards", that Tapestry doesn't 
understand.</p><p><parameter ac:name="">Ordered_List</parameter></p>
 <h2 id="TapestryIoCConfiguration-OrderedList">Ordered List</h2><p>Ordered 
lists are much more common. With an ordered list, the contributions are sorted 
into a proper order before being provided to the service builder 
method.</p><p>Again, the order in which service contribution methods are 
invoked is unknown. Therefore, the order in which objects are added to the 
configuration is not known. Instead, we enforce an order on the items 
<em>after</em> all the contributions have been added. As with <a  
href="tapestry-ioc-decorators.html">service decorators</a>, we set the order by 
giving each contributed object a unique id, and identifying (by id) which items 
must preceded it in the list, and which must follow.</p><p>So, if we changed 
our Startup service to require a specific order for startup:</p><parameter 
ac:name="">java</parameter><plain-text-body>  public static Runnable 
buildStartup(final List&lt;Runnable&gt; configuration)
+  }    </pre>
+</div></div><p>The Configuration interface defines just a single method: 
<code>add()</code>. This is very intentional: the only thing you can do is add 
new items. If we passed in a Collection, you might be tempted to check it for 
values, or remove them ... but that flies in the face of the fact that the 
order of execution of these service contribution methods is entirely 
unknown.</p><p>For readability, we've parameterized the configuration parameter 
of the method, constraining it to instances of java.lang.Runnable, so as to 
match the corresponding parameter. This is optional, but often very helpful. In 
any case, attempting to contribute an object that doesn't extend or implement 
the type (Runnable) will result in a runtime warning (and the value will be 
ignored).</p><p>Tapestry supports only this simple form of parameterized types. 
Java generics supports a wider form, "wildcards", that Tapestry doesn't 
understand.</p><p><span class="confluence-anchor-link" 
id="TapestryIoCConfigurati
 on-Ordered_List"></span></p><h2 
id="TapestryIoCConfiguration-OrderedList">Ordered List</h2><p>Ordered lists are 
much more common. With an ordered list, the contributions are sorted into a 
proper order before being provided to the service builder method.</p><p>Again, 
the order in which service contribution methods are invoked is unknown. 
Therefore, the order in which objects are added to the configuration is not 
known. Instead, we enforce an order on the items <em>after</em> all the 
contributions have been added. As with <a  
href="tapestry-ioc-decorators.html">service decorators</a>, we set the order by 
giving each contributed object a unique id, and identifying (by id) which items 
must preceded it in the list, and which must follow.</p><p>So, if we changed 
our Startup service to require a specific order for startup:</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 Runnable buildStartup(final 
List&lt;Runnable&gt; configuration)
   {
     return new Runnable()
     {
@@ -134,17 +230,20 @@ public static void arbitraryMethodName(M
           contribution.run();
       }
     };
-  }  </plain-text-body><p>Notice that the service builder method is shielded 
from the details of how the items are ordered. It doesn't have to know about 
IDs and pre- and post-requisites. By using a parameter type of List, we've 
triggered Tapestry to collect all the ordering information.</p><p>For our 
service contribution methods, we must provide a parameter of type <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html";>OrderedConfiguration</a>:</p><parameter
 ac:name="">java</parameter><plain-text-body>  public static void 
contributeStartup(OrderedConfiguration&lt;Runnable&gt; configuration)
+  }  </pre>
+</div></div><p>Notice that the service builder method is shielded from the 
details of how the items are ordered. It doesn't have to know about IDs and 
pre- and post-requisites. By using a parameter type of List, we've triggered 
Tapestry to collect all the ordering information.</p><p>For our service 
contribution methods, we must provide a parameter of type <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html";>OrderedConfiguration</a>:</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 void 
contributeStartup(OrderedConfiguration&lt;Runnable&gt; configuration)
   {
     configuration.add("JMS", new JMSStartup());
     configuration.add("FileSystem", new FileSystemStartup(), 
"after:CacheSetup");
-  }    </plain-text-body><p>Often, you don't care about ordering; the first 
form of the add method is used then. The ordering algorithm will find a spot 
for the object (here the JMSStartup instance) based on the constraints of other 
contributed objects.</p><p>For the "FileSystem" contribution, a constraint has 
been specified, indicating that FileSystem should be ordered after some other 
contribution named "CacheSetup". Any number of such <a  
href="ordering-by-constraints.html">ordering constraints</a> may be specified 
(the <code>add()</code> method accepts a variable number of 
arguments).</p><p>The object passed in may be null; this is valid, and is 
considered a "join point": points of reference in the list that don't actually 
have any meaning of their own, but can be used when ordering other elements. 
<em>TODO: Show example for chain of command, once that's put 
together.</em></p><p>Null values, once ordered, are edited out (the List passed 
to the service builder method does not inc
 lude any nulls). Again, they are allowed as placeholders, for the actual 
contributed objects to organize themselves around.
+  }    </pre>
+</div></div><p>Often, you don't care about ordering; the first form of the add 
method is used then. The ordering algorithm will find a spot for the object 
(here the JMSStartup instance) based on the constraints of other contributed 
objects.</p><p>For the "FileSystem" contribution, a constraint has been 
specified, indicating that FileSystem should be ordered after some other 
contribution named "CacheSetup". Any number of such <a  
href="ordering-by-constraints.html">ordering constraints</a> may be specified 
(the <code>add()</code> method accepts a variable number of 
arguments).</p><p>The object passed in may be null; this is valid, and is 
considered a "join point": points of reference in the list that don't actually 
have any meaning of their own, but can be used when ordering other elements. 
<em>TODO: Show example for chain of command, once that's put 
together.</em></p><p>Null values, once ordered, are edited out (the List passed 
to the service builder method does not include any null
 s). Again, they are allowed as placeholders, for the actual contributed 
objects to organize themselves around.
 
 </p><div class="confluence-information-macro 
confluence-information-macro-information"><p class="title">Added in 
5.3</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 class="error"><span class="error">Unknown macro: {div}</span> 
 <p>When using <code>add()</code> without any specific constraints, a default 
constraint is added: after the previously added element. These default 
constraints are only within a single contribution method, but makes it much 
easier to set the order of several related contributions. Note that the 
contributions will be ordered relative to each other and it's possible that 
contributions by some other module or method may be interspersed between 
them.</p>
-</div><h2 id="TapestryIoCConfiguration-MappedConfigurations">Mapped 
Configurations</h2><p>As discussed in the earlier examples, mapped 
configurations are also supported. The keys passed in must be unique. When 
conflicts occur, Tapestry will log warnings (identifying the source of the 
conflict, in terms of invoked methods), and ignore the conflicting 
value.</p><p>Neither the key nor the value may be null.</p><p>For mapped 
configurations where the key type is String, a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/util/CaseInsensitiveMap.html";>CaseInsensitiveMap</a>
 will be automatically used (and passed to the service builder method), to help 
ensure that <a  href="tapestry-ioc-configuration.html">case insensitivity</a> 
is automatic and pervasive.</p><h1 
id="TapestryIoCConfiguration-InjectingClasses">Injecting Classes</h1><p>All 
three configuration interfaces have a second method, 
<code>addInstance()</code>. This method takes a cla
 ss, not an instance. The class is instantiated and contributed. If the 
constructor for the class takes dependencies, those are injected as 
well.</p><h1 id="TapestryIoCConfiguration-InjectingResources">Injecting 
Resources</h1><p>In addition to injecting services into a contributor method 
(via the @InjectService and @Inject annotations), Tapestry will key off of the 
parameter type to allow other things to be injected.</p><ul><li><a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/ObjectLocator.html";>ObjectLocator</a>:
 access to other services visible to the contributing 
module</li><li>org.slf4j.Logger: the Logger for the service being contributed 
to</li></ul><p>No annotation is needed for these cases.</p><p><parameter 
ac:name="">overrides</parameter></p><h1 
id="TapestryIoCConfiguration-ConfigurationOverrides">Configuration 
Overrides</h1><p>
+</div><h2 id="TapestryIoCConfiguration-MappedConfigurations">Mapped 
Configurations</h2><p>As discussed in the earlier examples, mapped 
configurations are also supported. The keys passed in must be unique. When 
conflicts occur, Tapestry will log warnings (identifying the source of the 
conflict, in terms of invoked methods), and ignore the conflicting 
value.</p><p>Neither the key nor the value may be null.</p><p>For mapped 
configurations where the key type is String, a <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/util/CaseInsensitiveMap.html";>CaseInsensitiveMap</a>
 will be automatically used (and passed to the service builder method), to help 
ensure that <a  href="tapestry-ioc-configuration.html">case insensitivity</a> 
is automatic and pervasive.</p><h1 
id="TapestryIoCConfiguration-InjectingClasses">Injecting Classes</h1><p>All 
three configuration interfaces have a second method, 
<code>addInstance()</code>. This method takes a cla
 ss, not an instance. The class is instantiated and contributed. If the 
constructor for the class takes dependencies, those are injected as 
well.</p><h1 id="TapestryIoCConfiguration-InjectingResources">Injecting 
Resources</h1><p>In addition to injecting services into a contributor method 
(via the @InjectService and @Inject annotations), Tapestry will key off of the 
parameter type to allow other things to be injected.</p><ul><li><a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/ObjectLocator.html";>ObjectLocator</a>:
 access to other services visible to the contributing 
module</li><li>org.slf4j.Logger: the Logger for the service being contributed 
to</li></ul><p>No annotation is needed for these cases.</p><p><span 
class="confluence-anchor-link" 
id="TapestryIoCConfiguration-overrides"></span></p><h1 
id="TapestryIoCConfiguration-ConfigurationOverrides">Configuration 
Overrides</h1><p>
 
 </p><div class="confluence-information-macro 
confluence-information-macro-information"><p class="title">Added in 
5.1</p><span class="aui-icon aui-icon-small aui-iconfont-info 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body">
 </div></div>

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 Wed Sep 
20 12:29:16 2017
@@ -27,6 +27,14 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <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>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,7 +75,8 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><rich-text-body><p>Starting with 
Tapestry 5.1, Service Decoration is augmented with <a  
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></rich-text-body><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 InputStre
 am 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 dy
 namically 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><parameter 
ac:name="">java</parameter><plain-text-body>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  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, t
 ermed 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;
 
 import org.apache.tapestry5.ioc.services.LoggingDecorator;
 import org.slf4j.Logger;
@@ -86,10 +95,14 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
-}</plain-text-body><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> param
 eter 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><parameter ac:name="">java</parameter><plain-text-body>  public static 
Indexer decorateIndexer(Indexer delegate, Logger logger, LoggingDecorator 
decorator)
+}</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 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);
-  }</plain-text-body><p>Of course, nothing stops you from combining building 
with decorating inside the service builder method:</p><parameter 
ac:name="">java</parameter><plain-text-body>package org.example.myapp.services;
+  }</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;
 
 import org.apache.tapestry5.ioc.services.LoggingDecorator;
 import org.slf4j.Logger;
@@ -100,25 +113,31 @@ public class MyAppModule
   {
     return decorator.build(Indexer.class, logger, new IndexerImpl());
   }
-}</plain-text-body><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  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><parameter ac:name="">java</parameter><plain-text
 -body>  @Match("*")
+}</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  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("*")
   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);
-  }   </plain-text-body><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 inter
 face. 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  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  
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><parameter ac:name="">java</parameter><plain-text-body>  @Match("*")
+  }   </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 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  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  
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,
     LoggingDecorator decorator)
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
-  }   </plain-text-body><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>
+  }   </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><h1 
id="TapestryIoCDecorators-Annotationdrivendecorators">Annotation driven 
decorators</h1><p>
 
 </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 class="error"><span class="error">Unknown macro: {div}</span> 
-<p>&#160;</p></div>Starting from version 5.2, Tapestry supports 
annotation-driven decorator methods. If the <a  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.<plain-text-body>  @Decorate
+<p>&#160;</p></div>Starting from version 5.2, Tapestry supports 
annotation-driven decorator methods. If the <a  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,
@@ -126,7 +145,9 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
-</plain-text-body><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><plain-text-body> 
 @Decorate
+</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
   @Blue
   public static &lt;T&gt; T byMarkerAnnotation(Class&lt;T&gt; 
serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -134,14 +155,18 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
-</plain-text-body><p>The decorator above is applied to any service that is 
marked by the @Blue annotation.</p><p>By default, <a  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  
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><plain-text-body>  
@Decorate(serviceInterface=MyService.class)
+</pre>
+</div></div><p>The decorator above is applied to any service that is marked by 
the @Blue annotation.</p><p>By default, <a  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  
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,
     LoggingDecorator decorator)
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
-  }</plain-text-body><p>In the example above, the decorator is applied to any 
implementation of MyService interfaces whose id matches the "*DAO" 
pattern.</p><plain-text-body>  @Decorate(serviceInterface=MyService.class)
+  }</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)
   @Blue
   public static &lt;T&gt; T byMarkerAnnotation(Class&lt;T&gt; 
serviceInterface, T delegate,
     String serviceId, Logger logger,
@@ -149,7 +174,9 @@ public class MyAppModule
   {
     return decorator.build(serviceInterface, delegate, serviceId, logger);
   }
-</plain-text-body><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  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  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/Invocation.html";>Invocation</a>.
 MethodAdvice gives you a chan
 ce 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 
proc
 eed 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  
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><parameter ac:name="">java</parameter><plain-text-body>public class 
LoggingDecoratorImpl implements LoggingDecorator
+</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  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  
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 in
 to 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  
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;
 
@@ -203,7 +230,8 @@ public class MyAppModule
                                       String.format("&lt;Logging interceptor 
for %s(%s)&gt;", serviceId,
                                                     
serviceInterface.getName()));
     }
-}</plain-text-body><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>
+}</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><p>&#160;</p><p></p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to