You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by bu...@apache.org on 2015/07/26 23:19:57 UTC

svn commit: r959684 [5/5] - in /websites/production/tapestry/content: ./ cache/

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 Sun Jul 26 21:19:56 2015
@@ -62,52 +62,90 @@
 <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-configuration.html">Tapestry IoC Configuration</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-configuration.html">Tapestry IoC Configuration</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=23338480">edit</a>
   </div>
 
 <div id="content">
-<div id="ConfluenceContent">
+<div id="ConfluenceContent"><p><strong>Configuration of Tapestry IOC services</strong> &#8211; both those provided by Tapestry and those you write yourself &#8211; is done using Java, not XML.</p><div class="aui-label" style="float:right" title="Related Articles">
 
-<h1 id="TapestryIoCConfiguration-TapestryIoCConfiguration">Tapestry IoC Configuration</h1>
 
-<div class="navmenu" style="float:right; background:#eee; margin:3px; padding:3px">
-<div class="error"><span class="error">Error formatting macro: contentbylabel: com.atlassian.confluence.api.service.exceptions.BadRequestException: Could not parse cql : null</span> </div></div>
 
-<p>Tapestry services &#8211; both those provided by Tapestry and those you write yourself &#8211; are configured using Java, not XML.</p>
 
-<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 seems esoteric, but is quite handy, and is best explained by 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 shape="rect" href="defining-tapestry-ioc-services.html">service builder method</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 FileServiceDispatcher buildFileServicerDispatcher(Map&lt;String,FileServicer&gt; contributions)
+
+<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 shape="rect" 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 shape="rect" 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 shape="rect" 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 shape="rect" 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 shape="rect" 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 shape="rect" 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 seems esoteric, but is quite handy, and is best explained by 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 shape="rect" href="defining-tapestry-ioc-services.html">service builder method</a>:</p><div class="code panel pdl" style="border-width: 1p
 x;"><div class="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);
   } </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)
+</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());
   }  </pre>
-</div></div>
-
-<p>Or, instead of instantiating those services ourselves, we could <a shape="rect" 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,
+</div></div><p>Or, instead of instantiating those services ourselves, we could <a shape="rect" 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)
@@ -115,60 +153,27 @@
     configuration.add("txt", textFileServicer);
     configuration.add("pdf", pdfFileServicer);
   }  </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)
+</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());
   }  </pre>
-</div></div>
+</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>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>
-
-
-
-<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>If you prefer annotations over naming conventions you can use the @<a shape="rect" 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>
-
-<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 shape="rect" href="tapestry-ioc-configuration.html">override</a> of the service to get the configuration intended for the original service.</li></ul>
-
-
-<p>The following 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)
+<p>&#160;</p></div>If you prefer annotations over naming conventions you can use the @<a shape="rect" 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 shape="rect" href="tapestry-ioc-configuration.html">override</a> of the service to get the configuration intended for the original service.<
 /li></ul><p>The following 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());
 }  
 </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)
+</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)
 {
@@ -176,17 +181,8 @@ public static void arbitraryMethodName(M
     configuration.add("ppt", new PowerPointFileServicer());
 }
 </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 shape="rect" 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 shape="rect" 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 panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  @Contribute(FileServiceDispatcher.class)
+</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 shape="rect" 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 shape="rect" 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 panelContent 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)
   {
@@ -194,26 +190,8 @@ public static void arbitraryMethodName(M
     configuration.add("ppt", new PowerPointFileServicer());
   }  
 </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)
+</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()
     {
@@ -224,39 +202,14 @@ public static void arbitraryMethodName(M
       }
     };
   }  </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 shape="rect" 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)
+</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 shape="rect" 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());
   }    </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="TapestryIoCConfiguration-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 shape="rect" 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)
+</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 shape="rect" 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()
     {
@@ -267,77 +220,24 @@ public static void arbitraryMethodName(M
       }
     };
   }  </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 shape="rect" 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)
+</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 shape="rect" 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");
   }    </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 shape="rect" 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 nulls). Again, they are allowed as placeholders, for the actual contributed objects to organize themselves around.</p>
-
-
+</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 shape="rect" 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 incl
 ude any nulls). Again, they are allowed as placeholders, for the actual contributed objects to organize themselves around.
 
-<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">
+</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 style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;">
-
 <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 shape="rect" 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 shape="rect" 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 class, 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 shape="rect" 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>
+</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 shape="rect" 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 shape="rect" 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 class, 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 shape="rect" 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>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>
-
-
-
-<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">
+</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>
 <div style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;">
-</div>
-
-<p>The OrderedConfiguration and MappedConfiguration interfaces now support overrides. An override is a replacement for a normally contributed object. An override <em>must</em> match a contributed object, and each contributed object may be overridden at most once.</p>
-
-<p>The new object replaces the original object; alternately, you may override the original object with null.</p>
-
-<p>This allows you to fine tune configuration values that are contributed from modules that you are using, rather than just those that you write yourself. It is powerful and a bit dangerous.</p>
-
-<p>In Tapestry 5.0, services that wanted to support this kind of override behavior had to implement it on an ad-hoc basis, such as ApplicationDefaults overriding FactoryDefaults. In many cases, that is still useful.</p>
-</div>
+<p>&#160;</p></div>The OrderedConfiguration and MappedConfiguration interfaces now support overrides. An override is a replacement for a normally contributed object. An override <em>must</em> match a contributed object, and each contributed object may be overridden at most once.<p>The new object replaces the original object; alternately, you may override the original object with null.</p><p>This allows you to fine tune configuration values that are contributed from modules that you are using, rather than just those that you write yourself. It is powerful and a bit dangerous.</p><p>In Tapestry 5.0, services that wanted to support this kind of override behavior had to implement it on an ad-hoc basis, such as ApplicationDefaults overriding FactoryDefaults. In many cases, that is still useful.</p></div>
 </div>
 
 <div class="clearer"></div>

Modified: websites/production/tapestry/content/unit-testing-pages-or-components.html
==============================================================================
--- websites/production/tapestry/content/unit-testing-pages-or-components.html (original)
+++ websites/production/tapestry/content/unit-testing-pages-or-components.html Sun Jul 26 21:19:56 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();
@@ -67,27 +65,38 @@
   </div>
 
 <div id="content">
-<div id="ConfluenceContent"><h1 id="Unittestingpagesorcomponents-Unittestingpagesorcomponents">Unit testing pages or components</h1>
+<div id="ConfluenceContent"><p>Tapestry provides support for easily <strong>unit testing your pages and components</strong>. Follow the simple steps below.</p><div class="aui-label" style="float:right" title="Related Articles">
 
-<div class="navmenu" style="float:right; background:#eee; margin:3px; padding:3px">
-<div class="error"><span class="error">Error formatting macro: contentbylabel: com.atlassian.confluence.api.service.exceptions.BadRequestException: Could not parse cql : null</span> </div></div> 
 
-<p>Tapestry provides support for easily unit testing your pages and components. Follow the simple steps below.</p>
 
-<h2 id="Unittestingpagesorcomponents-Settingupadrivingenvironment">Setting up a driving environment</h2>
 
-<p>In order to unit test a page, you'll need to create an instance of <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/test/PageTester.html">PageTester</a>. It acts as both the browser and the servlet container so that you can use it to drive your page.</p>
 
-<p>The PageTester falls into a middle ground between pure unit testing and <a shape="rect" href="integration-testing.html">full-scale integration testing</a>.</p>
 
-<p>As the PageTester is not a real servlet container, you need to tell it the same information as you would in web.xml:</p>
 
-<ol><li>Your application package.</li><li>Your filter name. This is used to load your Tapestry IoC module only. If you have none, you can pass an empty string or anything to it.</li><li>The folder acting as your context root. This is used to locate your templates (if they're put there).Here is an example (using TestNG, but you're free to use JUnit or anything else):</li></ol>
 
+<h3>Related Articles</h3>
 
-<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 MyTest extends Assert
+<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 shape="rect" href="integration-testing.html">Integration Testing</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 shape="rect" href="unit-testing-pages-or-components.html">Unit testing pages or components</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div><h2 id="Unittestingpagesorcomponents-Settingupadrivingenvironment">Setting up a driving environment</h2><p>In order to unit test a page, you'll need to create an instance of <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/test/PageTester.html">PageTester</a>. It acts as both the browser and the servlet container so that you can use it to drive your page.</p><p>The PageTester falls into a middle ground between pure unit testing and <a shape="rect" href="integration-testing.html">full-scale integration testing</a>.</p><p>As the PageTester is not a real servlet container, you need to tell it the same information as you would in web.xml:</p><ol><li>Your application package.</li><li>Your filter name. This is used to load your Tapestry IoC module only. If you have none, you can pass an empty string or anything to it.</li><li>The folder acting as your context root. This is used to locate your templates (if they're put there)
 .Here is an example (using TestNG, but you're free to use JUnit or anything else):</li></ol><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 MyTest extends Assert
 {
     @Test
     public void test1()
@@ -98,16 +107,8 @@ public class MyTest extends Assert
     }
 }
 </pre>
-</div></div>
-<h2 id="Unittestingpagesorcomponents-Testingtherenderingofapage">Testing the rendering of a page</h2>
-
-<p>To test if a page renders properly (optionally with context), you can tell the PageTester to render it and then assert against the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/dom/Document.html">DOM Document</a> returned.</p>
-
-<p>Here is an example. Let's assuming the page being tested is named "MyPage" and it should return a page containing an HTML element whose id is "id1" and whose text content should be "hello":</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 MyTest extends Assert
+</div></div><h2 id="Unittestingpagesorcomponents-Testingtherenderingofapage">Testing the rendering of a page</h2><p>To test if a page renders properly (optionally with context), you can tell the PageTester to render it and then assert against the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/dom/Document.html">DOM Document</a> returned.</p><p>Here is an example. Let's assuming the page being tested is named "MyPage" and it should return a page containing an HTML element whose id is "id1" and whose text content should be "hello":</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 MyTest extends Assert
 {
     @Test
     public void test1()
@@ -120,13 +121,8 @@ public class MyTest extends Assert
     }
 }
 </pre>
-</div></div>
-
-<p>If the page requires a context, you can pass it this way:</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 MyTest extends Assert
+</div></div><p>If the page requires a context, you can pass it this way:</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 MyTest extends Assert
 {
     @Test
     public void test1()
@@ -140,15 +136,8 @@ public class MyTest extends Assert
     }
 }
 </pre>
-</div></div>
-
-<h2 id="Unittestingpagesorcomponents-Testinganactionlink">Testing an action link</h2>
-
-<p>After rendering a page, you may want to "click" on an action link and then assert against the resulting page. You can do it this way:</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 MyTest extends Assert
+</div></div><h2 id="Unittestingpagesorcomponents-Testinganactionlink">Testing an action link</h2><p>After rendering a page, you may want to "click" on an action link and then assert against the resulting page. You can do it this way:</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 MyTest extends Assert
 {
     @Test
     public void test1()
@@ -163,15 +152,8 @@ public class MyTest extends Assert
     }
 }
 </pre>
-</div></div>
-
-<h2 id="Unittestingpagesorcomponents-Testingaformsubmission">Testing a form submission</h2>
-
-<p>After rendering a page, you may want to fill out a form, submit it and then inspect the resulting page. You can do it this way:</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 MyTest extends Assert
+</div></div><h2 id="Unittestingpagesorcomponents-Testingaformsubmission">Testing a form submission</h2><p>After rendering a page, you may want to fill out a form, submit it and then inspect the resulting page. You can do it this way:</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 MyTest extends Assert
 {
     @Test
     public void test1()
@@ -189,17 +171,7 @@ public class MyTest extends Assert
     }
 }
 </pre>
-</div></div>
-
-<p>To submit a form by clicking a submit button, call the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/test/PageTester.html#clickSubmit(org.apache.tapestry5.dom.Element,%20java.util.Map)">clickSubmit()</a> method instead.</p>
-
-<h2 id="Unittestingpagesorcomponents-Unittestingacomponent">Unit testing a component</h2>
-
-<p>To unit test a component, just create a test page containing that component. Then unit test that page.</p>
-
-<h2 id="Unittestingpagesorcomponents-Third-partyTestingModules">Third-party Testing Modules</h2>
-
-<ul><li><a shape="rect" class="external-link" href="http://tapestrytestify.sourceforge.net/" >Tapestry-Testify</a> makes it easier to write page and component tests and run them efficiently.</li><li><a shape="rect" class="external-link" href="http://tapestryxpath.sourceforge.net/" >Tapestry-XPath</a> allows you to use XPath expressions to query the Tapestry DOM (useful for simplifying page and component tests).</li></ul></div>
+</div></div><p>To submit a form by clicking a submit button, call the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/test/PageTester.html#clickSubmit(org.apache.tapestry5.dom.Element,%20java.util.Map)">clickSubmit()</a> method instead.</p><h2 id="Unittestingpagesorcomponents-Unittestingacomponent">Unit testing a component</h2><p>To unit test a component, just create a test page containing that component. Then unit test that page.</p><h2 id="Unittestingpagesorcomponents-Third-partyTestingModules">Third-party Testing Modules</h2><ul><li><a shape="rect" class="external-link" href="http://tapestrytestify.sourceforge.net/" >Tapestry-Testify</a> makes it easier to write page and component tests and run them efficiently.</li><li><a shape="rect" class="external-link" href="http://tapestryxpath.sourceforge.net/" >Tapestry-XPath</a> allows you to use XPath expressions to query the Tapestry DOM (useful for simplifying page and compon
 ent tests).</li></ul></div>
 </div>
 
 <div class="clearer"></div>