You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by bu...@apache.org on 2020/01/11 22:19:55 UTC

svn commit: r1055144 - in /websites/production/tapestry/content: cache/main.pageCache environmental-services.html javascript-modules.html tapestry-ioc-overview.html

Author: buildbot
Date: Sat Jan 11 22:19:55 2020
New Revision: 1055144

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/environmental-services.html
    websites/production/tapestry/content/javascript-modules.html
    websites/production/tapestry/content/tapestry-ioc-overview.html

Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/tapestry/content/environmental-services.html
==============================================================================
--- websites/production/tapestry/content/environmental-services.html (original)
+++ websites/production/tapestry/content/environmental-services.html Sat Jan 11 22:19:55 2020
@@ -77,10 +77,10 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><div class="navmenu" style="float:right; width:30%; background:#eee; margin:3px; padding:3px">
+                <div id="ConfluenceContent"><p><br clear="none"></p><div class="navmenu" style="float:right; width:30%; background:#eee; margin:3px; padding:3px">
 <p>Environmental services represent yet another, distinct form of injection.</p>
 
-<p>Unlike service injection (injection via a service implementation's constructor) or normal component injection (directly into component fields, via the @Inject annotation) where the injected value is always the same, with environmental services, the injected value is very late bound and dynamic.</p></div><strong>Environmental services</strong> provide a conduit of communication between two components (usually a component and the components it encloses). The first component pushes an object of a certain type into the <em>environment</em>, and then the second component can access that object merely by defining an annotated property of the same type.<p>An example of how this works is Tapestry's built-in <em>form support</em>. The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a> component creates an object of type <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/t
 apestry5/services/FormSupport.html">FormSupport</a> and pushes it into the environment. Then, the enclosed form components can use that FormSupport object to participate in both the rendering of the Form and the Form's eventual submission. This is how control names and client-side ids are determined, how fields register callbacks so that they can process their part of the submission, and how fields hook themselves to client-side validation.</p><h1 id="EnvironmentalServices-Usingthe@Environmentalannotation">Using the @Environmental annotation</h1><p>The @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Environmental.html">Environmental</a> annotation, when used in a component class, causes the associated field to be replaced at runtime with a read-only value obtained from an Environment service provided by an enclosing component.</p><p>A very common Environmental is <a  class="external-link" href="http://tapestry.apache.org/c
 urrent/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html">JavaScriptSupport</a>, used when generating <a  href="ajax-javascript.html">client-side JavaScript</a>.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<p>Unlike service injection (injection via a service implementation's constructor) or normal component injection (directly into component fields, via the @Inject annotation) where the injected value is always the same, with environmental services, the injected value is very late bound and dynamic.</p></div><strong>Environmental services</strong> provide a conduit of communication between two components (usually a component and the components it encloses). The first component pushes an object of a certain type into the <em>environment</em>, and then the second component can access that object merely by defining an annotated property of the same type.<p><br clear="none"></p><p>An example of how this works is Tapestry's built-in <em>form support</em>. The <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a> component creates an object of type <a  class="external-link" href="http://tapestry.apache.org/curr
 ent/apidocs/org/apache/tapestry5/services/FormSupport.html">FormSupport</a> and pushes it into the environment. Then, the enclosed form components can use that FormSupport object to participate in both the rendering of the Form and the Form's eventual submission. This is how control names and client-side ids are determined, how fields register callbacks so that they can process their part of the submission, and how fields hook themselves to client-side validation.</p><h1 id="EnvironmentalServices-Usingthe@Environmentalannotation">Using the @Environmental annotation</h1><p>The @<a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Environmental.html">Environmental</a> annotation, when used in a component class, causes the associated field to be replaced at runtime with a read-only value obtained from an Environment service provided by an enclosing component.</p><p>A very common Environmental is <a  class="external-link" href="http
 ://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html">JavaScriptSupport</a>, used when generating <a  href="ajax-javascript.html">client-side JavaScript</a>.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">  @Inject @Path("${tapestry.scriptaculous}/dragdrop.js")
   private Asset dragDropLibrary;
 

Modified: websites/production/tapestry/content/javascript-modules.html
==============================================================================
--- websites/production/tapestry/content/javascript-modules.html (original)
+++ websites/production/tapestry/content/javascript-modules.html Sat Jan 11 22:19:55 2020
@@ -85,29 +85,31 @@
 
 
 
+
+
 <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>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="typescript.html">TypeScript</a>
+                        <a  href="javascript-modules.html">JavaScript Modules</a>
                 
                         
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="coffeescript.html">CoffeeScript</a>
+                        <a  href="typescript.html">TypeScript</a>
                 
                         
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="client-side-javascript.html">Client-Side JavaScript</a>
@@ -116,16 +118,16 @@
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="javascript-modules.html">JavaScript Modules</a>
+                        <a  href="coffeescript.html">CoffeeScript</a>
                 
                         
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="javascript-faq.html">JavaScript FAQ</a>
@@ -134,7 +136,7 @@
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="ajax-and-zones.html">Ajax and Zones</a>
@@ -143,25 +145,25 @@
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="component-cheat-sheet.html">Component Cheat Sheet</a>
+                        <a  href="legacy-javascript.html">Legacy JavaScript</a>
                 
                         
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a  href="legacy-javascript.html">Legacy JavaScript</a>
+                        <a  href="component-cheat-sheet.html">Component Cheat Sheet</a>
                 
                         
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="assets.html">Assets</a>
@@ -173,7 +175,7 @@
 
 
 <h2 id="JavaScriptModules-TheNeedforModules">The Need for Modules</h2><p>As web applications have evolved, the use of JavaScript in the client has expanded almost exponentially. This has caused all kinds of growing pains, since the original design of the web browser, and the initial design of JavaScript, was never intended for this level of complexity. Unlike Java, JavaScript has no native concept of a "package" or "namespace" and has the undesirable tendency to make everything a global.</p><p>In the earliest days, client-side JavaScript was constructed as libraries that would define simple functions and variables:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: js; gutter: false; theme: Default" style="font-size:12px;">function onclickHelp(event) {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: js; gutter: false; theme: Default" data-theme="Default">function onclickHelp(event) {
   if (helpModal === undefined) {
     helpModal = ...
   }
@@ -181,7 +183,7 @@
 }
 $("#helpButton").click(onClickHelp);</pre>
 </div></div><p>What's not apparent here is that function <code>onclickHelp()</code> is actually attached to the global window object. Further, the variable <code>helpModal</code> is also not local, it too gets defined on the window object. If you start to mix and match JavaScript from multiple sources, perhaps various kinds of third-party UI widgets, you start to run the risk of name collisions.</p><p>One approach to solving these kinds of problems is a&#160;<em>hygienic&#160;function wrapper</em>. The concept here is to define a function and immediately execute it. The functions and variables defined inside the function are private to that function.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: js; gutter: false; theme: Default" style="font-size:12px;">(function() {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: js; gutter: false; theme: Default" data-theme="Default">(function() {
   var helpModal = null;
 
   function onClickHelp(event) { ... }
@@ -189,7 +191,7 @@ $("#helpButton").click(onClickHelp);</pr
   $("#helpButton").click(onClickHelp);
 })();</pre>
 </div></div><p>This is an improvement in so far as it assists with name collisions. The variables and functions can only be referenced by name from inside the wrapper.</p><p>However, if you are building a library of code to reuse across your application (or building a library to share between applications) then something is still missing: a way to expose just the function you want from inside you wrapper to the outside world.</p><p>The old-school route is to choose a hopefully unique prefix, building a cumbersome name (perhaps <code>myapp_onClickHelp</code>), and attach that to the global window object. But that just makes your code that much uglier, and leaves you open to problems if not all members of your development team understand the rules and prefixes.</p><p>Enter the <a  class="external-link" href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md" rel="nofollow">Asynchronous Module Definition</a>. The AMD is pragmatic way to avoid globals, and adds a number of bells and
  whistles that can themselves be quite important.</p><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>Tapestry uses the <a  class="external-link" href="http://requirejs.org/" rel="nofollow">RequireJS</a> library as the client-side implementation of AMD. It supplements this on the server-side with Tapestry services for even more flexibility.</p></div></div><p>Under AMD, JavaScript is broken up into&#160;<em>modules</em>.</p><ul><li>Modules have a unique name, such as <code>t5/core/dom</code> or <code>app/tree-viewer</code>.</li><li>A module has a constructor function that&#160;<em>exports</em> a value.</li><li>A module defines&#160;<em>dependencies</em> on any number of other modules.</li><li>The export of each dependency is provided as a parameter to the constructor function.</li></ul><p>Here's an example
  from Tapestry itself:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Module t5/core/confirm-click</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: js; gutter: false; theme: Default" style="font-size:12px;">(function() {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: js; gutter: false; theme: Default" data-theme="Default">(function() {
   define(["jquery", "./events", "./dom", "bootstrap/modal"], function($, events, dom) {
     var runDialog;
     runDialog = function(options) {
@@ -207,13 +209,13 @@ $("#helpButton").click(onClickHelp);</pr
   });
 }).call(this);</pre>
 </div></div><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>The <code><span>confirm-click </span></code>module is used to raise a modal confirmation dialog when certain buttons are clicked; it is loaded by the <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/mixins/Confirm.html">Confirm</a> mixin.</p></div></div><p>This module depends on several other modules:&#160;<code>jquery</code>, <code>t5/core/events</code>, <code>t5/core/dom</code>, and <code>bootstrap/modal</code>. These other modules will have been loaded, and their constructor functions executed, before the <code>confirm-click</code> constructor function is executed. The export of each module is provided as a parameter in the order in which the dependencies are defined.</p><div class="confluenc
 e-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>With AMD, the JavaScript libraries may be loaded in parallel by the browser (that's the <em>asynchronous</em> part of AMD); RequireJS manages the dependency graph and invokes each function just once, as soon as its dependencies are ready, as libraries are loaded. In some cases, a module may be loaded just for its side effects; such modules will be listed last in the dependency array, and will not have a corresponding parameter in the dependent module's constructor function. In <code>confirm-click</code>, the <code>bootstrap/modal</code> module is loaded for side-effects.</p></div></div><p><code>confirm-click</code> defines a local function, <code>runDialog</code>. It performs some side-effects, attaching event handlers to the body and the document. The module's export is a JavaScri
 pt object containing a function that allows other modules to raise the modal dialog.</p><p>If a module truly exports only a single function and is unlikely to change, then it is acceptable to just return the function itself, not an object containing the function. However, returning an object makes it easier to expand the responsibilities of <code>confirm-click</code> in the future; perhaps to add a <code>dismissDialog</code> function.</p><h2 id="JavaScriptModules-LocationofModules">Location of Modules</h2><p>Modules are stored as a special kind of Tapestry <a  href="assets.html">asset</a>. On the server, modules are stored on the class path under <code>META-INF/modules</code>. In a typical environment, that means the sources will be in <code>src/main/resources/META-INF/modules</code>.</p><p>Typically, your application will place it's modules directly in this folder. If you are writing a reusable library, you will put modules for that library into a subfolder to prevent naming confli
 cts. Tapestry's own modules are prefixed with <code>t5/core</code>.</p><p>If you are using the optional&#160;<code><a  href="coffeescript.html">tapestry-web-resources</a></code> module (that's a server-side module, not an AMD module), then you can write your modules as CoffeeScript files (or TypeScript, starting in Tapestry 5.5); Tapestry will take care of compiling them to JavaScript as necessary.</p><p>The service <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/ModuleManager.html">ModuleManager</a> is the central piece of server-side support for modules. It supports&#160;<em>overriding</em> of existing modules by contributing overriding <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/JavaScriptModuleConfiguration.html">module definitions</a>. This can be useful to <a  class="external-link" href="http://en.wikipedia.org/wiki/Monkey_patch" rel="nofollow">mo
 nkey patch</a> an existing module supplied with Tapestry, or as part of a third-party library.</p><h2 id="JavaScriptModules-LoadingModulesfromTapestryCode">Loading Modules from Tapestry Code</h2><p>Often, you will have a Tapestry page or component that defines client-side behavior; such a component will need to load a module.</p><p>The simplest approach is to use the <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/annotations/Import.html">Import</a> annotation:</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;">@Import(module = "t5/core/confirm-click")
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">@Import(module = "t5/core/confirm-click")
 public class Confirm
 {
   ...
 }</pre>
 </div></div><p>The <code>module</code> attribute may either a single module name, or a list of module names.</p><p>In many cases, you not only want to require the module, but invoke a function exported by the module. In that case you must use the <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html">JavaScriptSupport</a> environmental.</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;">  @Environmental
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">  @Environmental
   JavaScriptSupport javaScriptSupport;
 
   ...
@@ -223,8 +225,8 @@ public class Confirm
   ...
 
   javaScriptSupport.require("my-module").invoke("setup").with(clientId, actionUrl);</pre>
-</div></div><p>In the first example, <code>my-module</code> exports a single function of two parameters. In the second example, <code>my-module</code> exports an object and the <code>setup</code> key is the function that is invoked.</p><h2 id="JavaScriptModules-DevelopmentMode">Development Mode</h2><p>In development mode, Tapestry will write details into the client-side console.</p><p><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/41813130/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png?version=1&amp;modificationDate=1401727827000&amp;api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/41813130/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png?version=1&amp;modificationDate=1401727827000&amp;api=v2"></span></p><p>This lists module
 s&#160;<em>explicitly</em> loaded (for initialization), but does not include modules loaded only as dependencies. You can see more details about what was actually loaded using&#160;<em>view source</em>; RequireJS adds <code>&lt;script&gt;</code> tags to the document to load libraries and modules.</p><h2 id="JavaScriptModules-LibrariesversusModules">Libraries versus Modules</h2><p>Tapestry still supports JavaScript libraries. &#160;When the page is loading, all libraries are loaded before any modules.</p><p>Libraries are loaded sequentially, so if you can avoid using libraries, so much the better in terms of page load time.</p><p>Libraries work in both normal page rendering, and Ajax partial page updates. Even in partial page updates, the libraries will be loaded sequentially before modules are loaded or exported functions invoked.</p><h2 id="JavaScriptModules-AggregatingModules">Aggregating Modules</h2><p>An important part of performance for production applications is JavaScript agg
 regation.</p><p>In development mode, you want your modules and other assets to load individually. For both CSS and JavaScript, smaller files that align with corresponding server-side files makes it much easier to debug problems.</p><p>Unlike assets, modules can't be fingerprinted, so on each page load, the client browser must ask the server for the module's contents frequently (typically getting a 304 Not Modified response).</p><p><span>This is acceptable in development mode, but quite undesirable in production.</span></p><div class="confluence-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>By default, Tapestry sets a max age of 60 (seconds) on modules, so you won't see module requests on every page load. This is configurable and you may want a much higher value in production. If you are rapidly iterating on the source of a modul
 e, you may need to force the browser to reload after clearing local cache. Chrome has an option to disable the client-side cache when its developer tools are open.</p></div></div><p>With JavaScript aggregation, the module can be included in the single virtual JavaScript library that represents a <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/JavaScriptStack.html">JavaScript stack</a>. This significantly cuts down on both the number of requests from the client to the server, and the overall number of bytes transferred.</p><p>Adding a module to the stack is not the same as <code>require</code>-ing it. In fact, you must still use <code>JavaScriptSupport.require()</code> regardless.</p><p>What adding a module to a stack accomplishes is that the module's code is downloaded in the first, initial JavaScript download; the download of the stack's virtual library. When (and if) the module is required as a dependency, the code wi
 ll already be present in the browser and ready to execute.</p><p>Tapestry&#160;<strong>does not</strong> attempt to do dependency analysis; that is left as a manual exercise. Typically, if you aggregate a module, your should look at its dependencies, and aggregate those as well. Failure to do so will cause unwanted requests back to the Tapestry server for the dependency modules, even though the aggregated module's code is present.</p><p>Because Tapestry is open, it is possible to contribute modules even into the&#160;<strong>core</strong> JavaScript stack. &#160;This is done using your application's 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;">    @Contribute(JavaScriptStack.class)
+</div></div><p>In the first example, <code>my-module</code> exports a single function of two parameters. In the second example, <code>my-module</code> exports an object and the <code>setup</code> key is the function that is invoked.</p><h2 id="JavaScriptModules-DevelopmentMode">Development Mode</h2><p>In development mode, Tapestry will write details into the client-side console.</p><p><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="javascript-modules.data/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png" data-image-src="https://cwiki.apache.org/confluence/download/attachments/41813130/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png?version=1&amp;modificationDate=1401727827000&amp;api=v2"></span></p><p>This lists modules&#160;<em>explicitly</em> loaded (for initialization), but does not include modules loaded only as dependen
 cies. You can see more details about what was actually loaded using&#160;<em>view source</em>; RequireJS adds <code>&lt;script&gt;</code> tags to the document to load libraries and modules.</p><h2 id="JavaScriptModules-LibrariesversusModules">Libraries versus Modules</h2><p>Tapestry still supports JavaScript libraries. &#160;When the page is loading, all libraries are loaded before any modules.</p><p>Libraries are loaded sequentially, so if you can avoid using libraries, so much the better in terms of page load time.</p><p>Libraries work in both normal page rendering, and Ajax partial page updates. Even in partial page updates, the libraries will be loaded sequentially before modules are loaded or exported functions invoked.</p><h2 id="JavaScriptModules-AggregatingModules">Aggregating Modules</h2><p>An important part of performance for production applications is JavaScript aggregation.</p><p>In development mode, you want your modules and other assets to load individually. For both C
 SS and JavaScript, smaller files that align with corresponding server-side files makes it much easier to debug problems.</p><p>Unlike assets, modules can't be fingerprinted, so on each page load, the client browser must ask the server for the module's contents frequently (typically getting a 304 Not Modified response).</p><p><span>This is acceptable in development mode, but quite undesirable in production.</span></p><div class="confluence-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>By default, Tapestry sets a max age of 60 (seconds) on modules, so you won't see module requests on every page load. This is configurable and you may want a much higher value in production. If you are rapidly iterating on the source of a module, you may need to force the browser to reload after clearing local cache. Chrome has an option to disable t
 he client-side cache when its developer tools are open.</p></div></div><p>With JavaScript aggregation, the module can be included in the single virtual JavaScript library that represents a <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/JavaScriptStack.html">JavaScript stack</a>. This significantly cuts down on both the number of requests from the client to the server, and the overall number of bytes transferred.</p><p>Adding a module to the stack is not the same as <code>require</code>-ing it. In fact, you must still use <code>JavaScriptSupport.require()</code> regardless.</p><p>What adding a module to a stack accomplishes is that the module's code is downloaded in the first, initial JavaScript download; the download of the stack's virtual library. When (and if) the module is required as a dependency, the code will already be present in the browser and ready to execute.</p><p>Tapestry&#160;<strong>does not</strong> att
 empt to do dependency analysis; that is left as a manual exercise. Typically, if you aggregate a module, your should look at its dependencies, and aggregate those as well. Failure to do so will cause unwanted requests back to the Tapestry server for the dependency modules, even though the aggregated module's code is present.</p><p>Because Tapestry is open, it is possible to contribute modules even into the&#160;<strong>core</strong> JavaScript stack. &#160;This is done using your application's module:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">    @Contribute(JavaScriptStack.class)
     @Core
     public static void addAppModules(OrderedConfiguration&lt;StackExtension&gt; configuration) {
         configuration.add("tree-viewer", StackExtension.module("tree-viewer"));

Modified: websites/production/tapestry/content/tapestry-ioc-overview.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-overview.html (original)
+++ websites/production/tapestry/content/tapestry-ioc-overview.html Sat Jan 11 22:19:55 2020
@@ -75,7 +75,9 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Even today, with the overwhelming success of <a  class="external-link" href="http://www.springframework.org" rel="nofollow">Spring</a> and the rise of smaller, simpler approaches to building applications (in contrast to the heavyweight EJB 2.0 approach), many people still have trouble wrapping their heads around Inversion of Control.</p><p>Really understanding IoC is a new step for many developers. If you can remember back to when you made the transition from procedural programming (in C, or BASIC) to object oriented programming, you might remember the point where you "got it". The point where it made sense to have methods on objects, and data inside objects.</p><p>Inversion of Control builds upon those ideas. The goal is to make code more robust (that is, with fewer errors), more reusable and much easier to test.</p><p>Prior to IoC approaches, most developers were used to a more <em>monolithic</em> design, with a few core objects and a
  <code>main()</code> method somewhere that starts the ball rolling. <code>main()</code> instantiates the first couple of classes, and those classes end up instantiating and using all the other classes in the system.</p><p>That's an <em>unmanaged</em> system. Most desktop applications are unmanaged, so it's a very familiar pattern, and easy to get your head around.</p><p>By contrast, web applications are a <em>managed</em> environment. You don't write a main(), you don't control startup. You <em>configure</em> the Servlet API to tell it about your servlet classes to be instantiated, and their life cycle is totally controlled by the servlet container.</p><p>Inversion of Control is just a more general application of this approach. The container is ultimately responsible for instantiating and configuring the objects you tell it about, and running their entire life cycle of those objects.</p><p>Web applications are more complicated to write than monolithic applications, largely because o
 f <em>multithreading</em>. Your code will be servicing many different users simultaneously across many different threads. This tends to complicate the code you write, since some fundamental aspects of object oriented development get called into question: in particular, the use of <em>internal state</em> (values stored inside instance variables), since in a multithreaded environment, that's no longer the safe place it is in traditional development. Shared objects plus internal state plus multiple threads equals an broken, unpredictable application.</p><p>Frameworks such as Tapestry &#8211; both the IoC container, and the web framework itself &#8211; exist to help.</p><p>When thinking in terms of IoC, <strong>small is beautiful</strong>. What does that mean? It means small classes and small methods are easier to code than large ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods a thousand lines long, and no distinction between business logic 
 and view logic. Everything mixed together into an untestable jumble.</p><p>At the other extreme is IoC: small objects, each with a specific purpose, collaborating with other small objects.</p><p>Using unit tests, in collaboration with tools such as <a  class="external-link" href="http://easymock.org/" rel="nofollow">EasyMock</a>, you can have a code base that is easy to maintain, easy to extend, and easy to test. And by factoring out a lot of <em>plumbing</em> code, your code base will not only be easier to work with, it will be smaller.</p><h2 id="TapestryIoCOverview-LivingontheFrontier">Living on the Frontier</h2><p>Coding applications the traditional way is like being a homesteader on the American frontier in the 1800's. You're responsible for every aspect of your house: every board, every nail, every stick of furniture is something you personally created. There <em>is</em> a great comfort in total self reliance. Even if your house is small, the windows are a bit drafty or the fl
 oorboards creak a little, you know exactly <em>why</em> things are not-quite perfect.</p><p>Flash forward to modern cities or modern suburbia and it's a whole different story. Houses are built to specification from design plans, made from common materials, by many specializing tradespeople. Construction codes dictate how plumbing, wiring and framing should be performed. A home-owner may not even know how to drive a nail, but can still take comfort in draft-free windows, solid floors and working plumbing.</p><p>To extend the metaphor, a house in a town is not alone and self-reliant the way a frontier house is. The town house is situated on a street, in a neighborhood, within a town. The town provides services (utilities, police, fire control, streets and sewers) to houses in a uniform way. Each house just needs to connect up to those services.</p><h2 id="TapestryIoCOverview-TheWorldoftheContainer">The World of the Container</h2><p>So the IoC container is the "town" and in the world o
 f the IoC container, everything has a name, a place, and a relationship to everything else in the container. Tapestry calls this world "The Registry".</p><p><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23338486/ioc-overview.png?version=1&amp;modificationDate=1290980234000&amp;api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23338486/ioc-overview.png?version=1&amp;modificationDate=1290980234000&amp;api=v2"></span></p><p>Here we're seeing a few services from the built-in Tapestry IoC module, and a few of the services from the Tapestry web framework module. In fact, there are over 100 services, all interrelated, in the Registry ... and that's before you add your own to the mix. The IoC Registry treats all the services uniformly, regardless of whether they are part of Tapestry, or part of your application, or part o
 f an add-on library.</p><p>Tapestry IoC's job is to make all of these services available to each other, and to the outside world. The outside world could be a standalone application, or it could be an application built on top of the Tapestry web framework.</p><h2 id="TapestryIoCOverview-ServiceLifeCycle">Service Life Cycle</h2><p>Tapestry services are <em>lazy</em>, which means they are not fully instantiated until they are absolutely needed. Often, what looks like a service is really a proxy object ... the first time any method of the proxy is invoked, the actual service is instantiated and initialized (Tapestry uses the term <em>realized</em> for this process). Of course, this is all absolutely thread-safe.</p><p>Initially a service is <em>defined</em>, meaning some module has defined the service. Later, the service will be <em>virtual</em>, meaning a proxy has been created. This occurs most often because some other service <em>depends</em> on it, but hasn't gotten around to invok
 ing methods on it. Finally, a service that is ready to use is <em>realized</em>. What's nice is that your code neither knows nor cares about the life cycle of the service, because of the magic of the proxy.</p><p>In fact, when a Tapestry web application starts up, before it services its first request, only about 20% of the services have been realized; the remainder are defined or virtual.</p><h2 id="TapestryIoCOverview-Classvs.Service">Class vs. Service</h2><p>A Tapestry service is more than just a class. First of all, it is a combination of an <em>interface</em> that defines the operations of the service, and an <em>implementation class</em> that implements the interface.</p><p>Why this extra division? Having a service interface is what lets Tapestry create proxies and perform other operations. It's also a very good practice to code to an interface, rather than a specific implementation. You'll often be surprised at the kinds of things you can accomplish by substituting one impleme
 ntation for another.</p><p>Tapestry is also very aware that a service will have dependencies on other services. It may also have other needs ... for example, in Tapestry IoC, the container provides services with access to Loggers.</p><p>Tapestry IoC also has support for other configuration that may be provided to services when they are realized.</p><h2 id="TapestryIoCOverview-DependencyInjection">Dependency Injection</h2><p>Main Article: <a  href="injection.html">Injection</a></p><div class="aui-label" style="float:right" title="Related Articles">
+                <div id="ConfluenceContent"><p>Even today, with the overwhelming success of <a  class="external-link" href="http://www.springframework.org" rel="nofollow">Spring</a> and the rise of smaller, simpler approaches to building applications (in contrast to the heavyweight EJB 2.0 approach), many people still have trouble wrapping their heads around Inversion of Control.</p><p>Really understanding IoC is a new step for many developers. If you can remember back to when you made the transition from procedural programming (in C, or BASIC) to object oriented programming, you might remember the point where you "got it". The point where it made sense to have methods on objects, and data inside objects.</p><p>Inversion of Control builds upon those ideas. The goal is to make code more robust (that is, with fewer errors), more reusable and much easier to test.</p><p>Prior to IoC approaches, most developers were used to a more <em>monolithic</em> design, with a few core objects and a
  <code>main()</code> method somewhere that starts the ball rolling. <code>main()</code> instantiates the first couple of classes, and those classes end up instantiating and using all the other classes in the system.</p><p>That's an <em>unmanaged</em> system. Most desktop applications are unmanaged, so it's a very familiar pattern, and easy to get your head around.</p><p>By contrast, web applications are a <em>managed</em> environment. You don't write a main(), you don't control startup. You <em>configure</em> the Servlet API to tell it about your servlet classes to be instantiated, and their life cycle is totally controlled by the servlet container.</p><p>Inversion of Control is just a more general application of this approach. The container is ultimately responsible for instantiating and configuring the objects you tell it about, and running their entire life cycle of those objects.</p><p>Web applications are more complicated to write than monolithic applications, largely because o
 f <em>multithreading</em>. Your code will be servicing many different users simultaneously across many different threads. This tends to complicate the code you write, since some fundamental aspects of object oriented development get called into question: in particular, the use of <em>internal state</em> (values stored inside instance variables), since in a multithreaded environment, that's no longer the safe place it is in traditional development. Shared objects plus internal state plus multiple threads equals an broken, unpredictable application.</p><p>Frameworks such as Tapestry &#8211; both the IoC container, and the web framework itself &#8211; exist to help.</p><p>When thinking in terms of IoC, <strong>small is beautiful</strong>. What does that mean? It means small classes and small methods are easier to code than large ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods a thousand lines long, and no distinction between business logic 
 and view logic. Everything mixed together into an untestable jumble.</p><p>At the other extreme is IoC: small objects, each with a specific purpose, collaborating with other small objects.</p><p>Using unit tests, in collaboration with tools such as <a  class="external-link" href="http://easymock.org/" rel="nofollow">EasyMock</a>, you can have a code base that is easy to maintain, easy to extend, and easy to test. And by factoring out a lot of <em>plumbing</em> code, your code base will not only be easier to work with, it will be smaller.</p><h2 id="TapestryIoCOverview-LivingontheFrontier">Living on the Frontier</h2><p>Coding applications the traditional way is like being a homesteader on the American frontier in the 1800's. You're responsible for every aspect of your house: every board, every nail, every stick of furniture is something you personally created. There <em>is</em> a great comfort in total self reliance. Even if your house is small, the windows are a bit drafty or the fl
 oorboards creak a little, you know exactly <em>why</em> things are not-quite perfect.</p><p>Flash forward to modern cities or modern suburbia and it's a whole different story. Houses are built to specification from design plans, made from common materials, by many specializing tradespeople. Construction codes dictate how plumbing, wiring and framing should be performed. A home-owner may not even know how to drive a nail, but can still take comfort in draft-free windows, solid floors and working plumbing.</p><p>To extend the metaphor, a house in a town is not alone and self-reliant the way a frontier house is. The town house is situated on a street, in a neighborhood, within a town. The town provides services (utilities, police, fire control, streets and sewers) to houses in a uniform way. Each house just needs to connect up to those services.</p><h2 id="TapestryIoCOverview-TheWorldoftheContainer">The World of the Container</h2><p>So the IoC container is the "town" and in the world o
 f the IoC container, everything has a name, a place, and a relationship to everything else in the container. Tapestry calls this world "The Registry".</p><p><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="tapestry-ioc-overview.data/ioc-overview.png" data-image-src="https://cwiki.apache.org/confluence/download/attachments/23338486/ioc-overview.png?version=1&amp;modificationDate=1290980234000&amp;api=v2"></span></p><p>Here we're seeing a few services from the built-in Tapestry IoC module, and a few of the services from the Tapestry web framework module. In fact, there are over 100 services, all interrelated, in the Registry ... and that's before you add your own to the mix. The IoC Registry treats all the services uniformly, regardless of whether they are part of Tapestry, or part of your application, or part of an add-on library.</p><p>Tapestry IoC's job is to make all of these services available to each other, a
 nd to the outside world. The outside world could be a standalone application, or it could be an application built on top of the Tapestry web framework.</p><h2 id="TapestryIoCOverview-ServiceLifeCycle">Service Life Cycle</h2><p>Tapestry services are <em>lazy</em>, which means they are not fully instantiated until they are absolutely needed. Often, what looks like a service is really a proxy object ... the first time any method of the proxy is invoked, the actual service is instantiated and initialized (Tapestry uses the term <em>realized</em> for this process). Of course, this is all absolutely thread-safe.</p><p>Initially a service is <em>defined</em>, meaning some module has defined the service. Later, the service will be <em>virtual</em>, meaning a proxy has been created. This occurs most often because some other service <em>depends</em> on it, but hasn't gotten around to invoking methods on it. Finally, a service that is ready to use is <em>realized</em>. What's nice is that your
  code neither knows nor cares about the life cycle of the service, because of the magic of the proxy.</p><p>In fact, when a Tapestry web application starts up, before it services its first request, only about 20% of the services have been realized; the remainder are defined or virtual.</p><h2 id="TapestryIoCOverview-Classvs.Service">Class vs. Service</h2><p>A Tapestry service is more than just a class. First of all, it is a combination of an <em>interface</em> that defines the operations of the service, and an <em>implementation class</em> that implements the interface.</p><p>Why this extra division? Having a service interface is what lets Tapestry create proxies and perform other operations. It's also a very good practice to code to an interface, rather than a specific implementation. You'll often be surprised at the kinds of things you can accomplish by substituting one implementation for another.</p><p>Tapestry is also very aware that a service will have dependencies on other ser
 vices. It may also have other needs ... for example, in Tapestry IoC, the container provides services with access to Loggers.</p><p>Tapestry IoC also has support for other configuration that may be provided to services when they are realized.</p><h2 id="TapestryIoCOverview-DependencyInjection">Dependency Injection</h2><p>Main Article: <a  href="injection.html">Injection</a></p><div class="aui-label" style="float:right" title="Related Articles">
+
+
 
 
 
@@ -88,7 +90,16 @@
 
 <ul class="content-by-label"><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="environmental-services.html">Environmental Services</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="injection-in-detail.html">Injection in Detail</a>
@@ -97,7 +108,7 @@
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="injection-faq.html">Injection FAQ</a>
@@ -106,7 +117,7 @@
                     </div>
     </li><li>
         <div>
-                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>        </div>
+                <span class="icon aui-icon content-type-page" title="Page">Page:</span>        </div>
 
         <div class="details">
                         <a  href="injection.html">Injection</a>
@@ -118,7 +129,7 @@
 
 
 <p>Inversion of Control refers to the fact that the container, here Tapestry IoC's Registry, instantiates your classes. It decides on when the classes get instantiated.</p><p>Dependency Injection is a key part of <em>realization</em>: this is how a service is provided with the other services it needs to operate. For example, a Data Access Object service may be injected with a ConnectionPool service.</p><p>In Tapestry, injection occurs through constructors, through parameters to service builder methods, or through direct injection into fields. Tapestry prefers constructor injection, as this emphasizes that dependencies should be stored in <strong>final</strong> variables. This is the best approach towards ensuring thread safety.</p><p>In any case, injection "just happens". Tapestry finds the constructor of your class and analyzes the parameters to determine what to pass in. In some cases, it uses just the parameter type to find a match, in other cases, annotations on the parameters m
 ay also be used. It also scans through the fields of your service implementation class to identify which should have injected values written into them.</p><h2 id="TapestryIoCOverview-Whycan'tIjustusenew?">Why can't I just use <code>new</code>?</h2><p>That's a common question. All these concepts seem alien at first. What's wrong with <code>new</code>?</p><p>The problem with new is that it rigidly connects one implementation to another implementation. Let's follow a progression that reflects how a lot of projects get written. It will show that in the real world, <code>new</code> is not as simple as it first seems.</p><p>This example is built around some real-world work that involves a Java Messaging Service queue, part of an application performance monitoring subsystem for a large application. Code inside each server collects performance data of various types and sends it, via a shared JMS queue, to a central server for collection and reporting.</p><p>This code is for a metric that pe
 riodically counts the number of rows in a key database table. Other implementations of MetricProducer will be responsible for measuring CPU utilization, available disk space, number of requests per second, and so forth.</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 TableMetricProducer implements MetricProducer
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">public class TableMetricProducer implements MetricProducer
 {
   . . . 
 
@@ -131,7 +142,7 @@
 }
 </pre>
 </div></div><p>We've omitted some of the details (this code will need a database URL or a connection pool to operate), so as to focus on the one method and it's relationship to the QueueWriter class.</p><p>Obviously, this code has a problem ... we're creating a new QueueWriter for each metric we write into the queue, and the QueueWriter presumably is going to open the JMS queue fresh each time, an expensive operation. Thus:</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 TableMetricProducer implements MetricProducer
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">public class TableMetricProducer implements MetricProducer
 {
   . . . 
 
@@ -144,9 +155,9 @@
     queueWriter.sendMetric(metric);
   }</pre>
 </div></div><p>That's better. It's not perfect ... a proper system might know when the application was being shutdown and would shut down the JMS Connection inside the QueueWriter as well.</p><p>Here's a more immediate problem: JMS connections are really meant to be shared, and we'll have lots of little classes collecting different metrics. So we need to make the QueueWriter shareable:</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;">  private final QueueWriter queueWriter = QueueWriter.getInstance();</pre>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">  private final QueueWriter queueWriter = QueueWriter.getInstance();</pre>
 </div></div><p>... and inside class QueueWriter:</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 QueueWriter
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">public class QueueWriter
 {
   private static QueueWriter instance;
 
@@ -166,7 +177,7 @@
 }
 </pre>
 </div></div><p>Much better! Now all the metric producers running inside all the threads can share a single QueueWriter. Oh wait ...</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 synchronized static getInstance()
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">  public synchronized static getInstance()
   {
     if (instance == null)
     {
@@ -176,7 +187,7 @@
   }
 </pre>
 </div></div><p>Is that necessary? Yes. Will the code work without it? Yes &#8211; <strong>99.9% of the time</strong>. In fact, this is a very common error in systems that manually code a lot of these construction patterns: forgetting to properly synchronize access. These things often work in development and testing, but fail (with infuriating infrequency) in production, as it takes two or more threads running simultaneously to reveal the coding error.</p><p>Wow, we're a long way from a simple <code>new</code> already, and we're talking about just one service. But let's detour into <em>testing</em>.</p><p>How would you test TableMetricProducer? One way would be to let it run and try to find the message or messages it writes in the queue, but that seems fraught with difficulties. It's more of an integration test, and is certainly something that you'd want to execute at some stage of your development, but not as part of a quick-running unit test suite.</p><p>Instead, let's split QueueW
 riter in two: a QueueWriter interface, and a QueueWriterImpl implementation class. This will allow us to run TableMetricProducer against a <em>mock implementation</em> of QueueWriter, rather than the real thing. This is one of the immediate benefits of <em>coding to an interface</em> rather than <em>coding to an implementation</em>.</p><p>We'll need to change TableMetricProducer to take the QueueWriter as a constructor parameter.</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 TableMetricProducer implements MetricProducer
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">public class TableMetricProducer implements MetricProducer
 {
   private final QueueWriter queueWriter;
 
@@ -209,7 +220,7 @@
 }
 </pre>
 </div></div><p>This still isn't ideal, as we still have an explicit linkage between TableMetricProducer and QueueWriterImpl.</p><p>What we're seeing here is that there are multple <em>concerns</em> inside the little bit of code in this example. TableMetricProducer has an unwanted <em>construction concern</em> about which implementation of QueueWriter to instantiate (this shows up as two constructors, rather than just one). QueueWriterImpl has an additional <em>life cycle concern</em>, in terms of managing the singleton.</p><p>These extra concerns, combined with the use of static variables and methods, are a <em>bad design smell</em>. It's not yet very stinky, because this example is so small, but these problems tend to multiply as an application grows larger and more complex, especially as services start to truly collaborate in earnest.</p><p>For comparison, lets see what the Tapestry IoC implementation would look like:</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 MonitorModule
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java; gutter: false; theme: Default" data-theme="Default">public class MonitorModule
 {
   public static void bind(ServiceBinder binder)
   {
@@ -223,7 +234,7 @@
   }
 }
 </pre>
-</div></div><p>Again, we've omitted a few details related to the database the TableMetricProducer will point at (in fact, Tapestry IoC provides a lot of support for configuration of this type as well, which is yet another concern).</p><p>The MonitorModule class is a Tapestry IoC module: a class that defines and configures services.</p><p>The bind() method is the principle way that services are made known to the Registry: here we're binding a service interface to a service implementation. QueueWriter we've discussed already, and MetricScheduler is a service that is responsible for determining when MetricProducer instances run.</p><p>The contributeMetricScheduler() method allows the module to <em>contribute</em> into the MetricProducer service's <em>configuration</em>. More testability: the MetricProducer isn't tied to a pre-set list of producers, instead it will have a Collection&lt;MetricProducer&gt; injected into its constructor. Thus, when we're coding the MetricProducerImpl class
 , we can test it against mock implementations of MetricProducer.</p><p>The QueueWriter service is injected into the contributeMetricScheduler() method. Since there's only one QueueWriter service, Tapestry IoC is able to "find" the correct service based entirely on type. If, eventually, there's more than one QueueWriter service (perhaps pointing at different JMS queues), you would use an annotation on the parameter to help Tapestry connect the parameter to the appropriate service.</p><p>Presumably, there would be a couple of other parameters to the contributeMetricScheduler() method, to inject in a database URL or connection pool (that would, in turn, be passed to TableMetricProducer).</p><p>A new TableMetricProducer instance is created and contributed in. We could contribute as many producers as we like here. Other modules could also define a contributeMetricScheduler() method and contribute their own MetricProducer instances.</p><p>Meanwhile, the QueueWriterImpl class no longer nee
 ds the <code>instance</code> variable or getInstance() method, and the TableMetricProducer only needs a single constructor.</p><h2 id="TapestryIoCOverview-AdvantagesofIoC:Summary">Advantages of IoC: Summary</h2><p>It would be ludicrous for us to claim that applications built without an IoC container are doomed to failure. There is overwhelming evidence that applications have been built without containers and have been perfectly successful.</p><p>What we are saying is that IoC techniques and discipline will lead to applications that are:</p><ul><li><strong>More testable</strong> &#8211; smaller, simpler classes; coding to interfaces allows use of mock implementations</li><li><strong>More robust</strong> &#8211; smaller, simpler classes; use of final variables; thread safety baked in</li><li><strong>More scalable</strong> &#8211; thread safety baked in</li><li><strong>Easier to maintain</strong> &#8211; less code, simpler classes</li><li><strong>Easier to extend</strong> &#8211; new f
 eatures are often additions (new services, new contributions) rather than changes to existing classes</li></ul><p>What we're saying is that an IoC container allows you to work faster and smarter.</p><p>Many of these traits work together; for example, a more testable application is inherently more robust. Having a test suite makes it easier to maintain and extend your code, because its much easier to see if new features break existing ones. Simpler code plus tests also lowers the cost of entry for new developers coming on board, which allows for more developers to work efficiently on the same code base. The clean separation between interface and implementation also allows multiple developers to work on different aspects of the same code base with a lowered risk of interference and conflict.</p><p>By contrast, traditional applications, which we term <em>monolithic</em> applications, are often very difficult to test, because there are fewer classes, and each class has multiple concerns
 . A lack of tests makes it more difficult to add new features without breaking existing features. Further, the monolithic approach more often leads to implementations being linked to other implementations, yet another hurdle standing in the way of testing.</p><p>Let's end with a metaphor.</p><p>Over a decade ago, when Java first came on the scene, it was the first mainstream language to support garbage collection. This was very controversial: the garbage collector was seen as unnecessary, and a waste of resources. Among C and C++ developers, the attitude was "Why do I need a garbage collector? If I call malloc() I can call free()."</p><p>But now, most developers would never want to go back to a non-garbage collected environment. Having the GC around makes it much easier to code in a way we find natural: many small related objects working together. It turns out that knowing when to call free() is more difficult than it sounds. The Objective-C language tried to solve this with retain 
 counts on objects and that still lead to memory leaks when it was applied to object <em>graphs</em> rather than object <em>trees</em>.</p><p>Roll the clock forward a decade and the common consensus has shifted considerably. Objective-C 2.0 features true garbage collection and GC libraries are available for C and C++. All scripting languages, including Ruby and Python, feature garbage collection as well. A new language <em>without</em> garbage collection is now considered an anomaly.</p><p>The point is, the life cycle of objects turns out to be far more complicated than it looks at first glance. We've come to accept that our own applications lack the ability to police their objects as they are no longer needed (they literally lack the ability to determine <em>when</em> an object is no longer needed) and the garbage collector, a kind of higher authority, takes over that job very effectively. The end result? Less code and fewer bugs. And a careful study shows that the Java memory alloc
 ator and garbage collector (the two are quite intimately tied together) is actually <strong>more</strong> efficient than malloc() and free().</p><p>So we've come to accept that the <em>death concern</em> is better handled outside of our own code. The use of Inversion of Control is simply the flip side of that: the <em>life cycle and construction concerns</em> are also better handled by an outside authority as well: the IoC container. These concerns govern when a service is <em>realized</em> and how its dependencies and configuration are injected. As with the garbage collector, ceding these chores to the container results in less code and fewer bugs, and lets you concentrate on the things that should matter to you: your business logic, your application &#8211; and not a whole bunch of boilerplate plumbing!</p><p>&#160;</p><p></p></div>
+</div></div><p>Again, we've omitted a few details related to the database the TableMetricProducer will point at (in fact, Tapestry IoC provides a lot of support for configuration of this type as well, which is yet another concern).</p><p>The MonitorModule class is a Tapestry IoC module: a class that defines and configures services.</p><p>The bind() method is the principle way that services are made known to the Registry: here we're binding a service interface to a service implementation. QueueWriter we've discussed already, and MetricScheduler is a service that is responsible for determining when MetricProducer instances run.</p><p>The contributeMetricScheduler() method allows the module to <em>contribute</em> into the MetricProducer service's <em>configuration</em>. More testability: the MetricProducer isn't tied to a pre-set list of producers, instead it will have a Collection&lt;MetricProducer&gt; injected into its constructor. Thus, when we're coding the MetricProducerImpl class
 , we can test it against mock implementations of MetricProducer.</p><p>The QueueWriter service is injected into the contributeMetricScheduler() method. Since there's only one QueueWriter service, Tapestry IoC is able to "find" the correct service based entirely on type. If, eventually, there's more than one QueueWriter service (perhaps pointing at different JMS queues), you would use an annotation on the parameter to help Tapestry connect the parameter to the appropriate service.</p><p>Presumably, there would be a couple of other parameters to the contributeMetricScheduler() method, to inject in a database URL or connection pool (that would, in turn, be passed to TableMetricProducer).</p><p>A new TableMetricProducer instance is created and contributed in. We could contribute as many producers as we like here. Other modules could also define a contributeMetricScheduler() method and contribute their own MetricProducer instances.</p><p>Meanwhile, the QueueWriterImpl class no longer nee
 ds the <code>instance</code> variable or getInstance() method, and the TableMetricProducer only needs a single constructor.</p><h2 id="TapestryIoCOverview-AdvantagesofIoC:Summary">Advantages of IoC: Summary</h2><p>It would be ludicrous for us to claim that applications built without an IoC container are doomed to failure. There is overwhelming evidence that applications have been built without containers and have been perfectly successful.</p><p>What we are saying is that IoC techniques and discipline will lead to applications that are:</p><ul><li><strong>More testable</strong> &#8211; smaller, simpler classes; coding to interfaces allows use of mock implementations</li><li><strong>More robust</strong> &#8211; smaller, simpler classes; use of final variables; thread safety baked in</li><li><strong>More scalable</strong> &#8211; thread safety baked in</li><li><strong>Easier to maintain</strong> &#8211; less code, simpler classes</li><li><strong>Easier to extend</strong> &#8211; new f
 eatures are often additions (new services, new contributions) rather than changes to existing classes</li></ul><p>What we're saying is that an IoC container allows you to work faster and smarter.</p><p>Many of these traits work together; for example, a more testable application is inherently more robust. Having a test suite makes it easier to maintain and extend your code, because its much easier to see if new features break existing ones. Simpler code plus tests also lowers the cost of entry for new developers coming on board, which allows for more developers to work efficiently on the same code base. The clean separation between interface and implementation also allows multiple developers to work on different aspects of the same code base with a lowered risk of interference and conflict.</p><p>By contrast, traditional applications, which we term <em>monolithic</em> applications, are often very difficult to test, because there are fewer classes, and each class has multiple concerns
 . A lack of tests makes it more difficult to add new features without breaking existing features. Further, the monolithic approach more often leads to implementations being linked to other implementations, yet another hurdle standing in the way of testing.</p><p>Let's end with a metaphor.</p><p>Over a decade ago, when Java first came on the scene, it was the first mainstream language to support garbage collection. This was very controversial: the garbage collector was seen as unnecessary, and a waste of resources. Among C and C++ developers, the attitude was "Why do I need a garbage collector? If I call malloc() I can call free()."</p><p>But now, most developers would never want to go back to a non-garbage collected environment. Having the GC around makes it much easier to code in a way we find natural: many small related objects working together. It turns out that knowing when to call free() is more difficult than it sounds. The Objective-C language tried to solve this with retain 
 counts on objects and that still lead to memory leaks when it was applied to object <em>graphs</em> rather than object <em>trees</em>.</p><p>Roll the clock forward a decade and the common consensus has shifted considerably. Objective-C 2.0 features true garbage collection and GC libraries are available for C and C++. All scripting languages, including Ruby and Python, feature garbage collection as well. A new language <em>without</em> garbage collection is now considered an anomaly.</p><p>The point is, the life cycle of objects turns out to be far more complicated than it looks at first glance. We've come to accept that our own applications lack the ability to police their objects as they are no longer needed (they literally lack the ability to determine <em>when</em> an object is no longer needed) and the garbage collector, a kind of higher authority, takes over that job very effectively. The end result? Less code and fewer bugs. And a careful study shows that the Java memory alloc
 ator and garbage collector (the two are quite intimately tied together) is actually <strong>more</strong> efficient than malloc() and free().</p><p>So we've come to accept that the <em>death concern</em> is better handled outside of our own code. The use of Inversion of Control is simply the flip side of that: the <em>life cycle and construction concerns</em> are also better handled by an outside authority as well: the IoC container. These concerns govern when a service is <em>realized</em> and how its dependencies and configuration are injected. As with the garbage collector, ceding these chores to the container results in less code and fewer bugs, and lets you concentrate on the things that should matter to you: your business logic, your application &#8211; and not a whole bunch of boilerplate plumbing!</p><p><br clear="none"></p><p></p></div>
       </div>
 
       <div class="clearer"></div>