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 2017/09/16 02:22:41 UTC

svn commit: r1018228 [22/41] - in /websites/production/tapestry/content: ./ cache/

Modified: websites/production/tapestry/content/ioc.html
==============================================================================
--- websites/production/tapestry/content/ioc.html (original)
+++ websites/production/tapestry/content/ioc.html Sat Sep 16 02:22:40 2017
@@ -36,13 +36,26 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div>
+
+</div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">IOC</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html">
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">IOC</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -54,31 +67,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Tapestry's <strong>Inversion of Control</strong> container is a built-in Tapestry module based on <a  class="external-link" href="http://www.martinfowler.com/articles/injection.html" rel="nofollow">inversion of control</a> (IoC), a design approach that allows a working system to be fabricated from many small, easily testable pieces.</p><div class="aui-label" style="float:right" title="Related Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="ioc.html">IOC</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="ioc-cookbook.html">IoC cookbook</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="tapestry-ioc-overview.html">Tapestry IoC Overview</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="tapestry-inversion-of-control-faq.html">Tapestry Inversion of Control FAQ</a> 
-  </div> </li></ul></div><p>An additional benefit of using IoC is that, by breaking a complex system into small pieces, it becomes easier to modify and extend the system, by overriding or replacing selected parts of the system.</p><p>The use of IoC in Tapestry represents an evolution from Tapestry 3 to Tapestry 4 to Tapestry 5. Tapestry 3 did not use IoC, though it included some weaker mechanisms, such as extensions, that served a similar purpose. To make large scale changes to the behavior of Tapestry 3 required subclassing key classes and overriding methods.</p><p>Tapestry 4 introduced the use of the <a  class="external-link" href="http://hivemind.apache.org/">Apache HiveMind</a> IoC container. In fact, the HiveMind project was created specifically for use as the IoC container for Tapestry 4. Tapestry 4 has met its goals for extensibility and configurability, largely because of HiveMind's flexibility.</p><p>Tapestry 5 extends on this, replacing HiveMind with a new container specif
 ically build for Tapestry 5, designed for greater ease of use, expressiveness and performance. HiveMind itself has been subsequently shelved; T5 IoC can be considered a streamlined and improved HiveMind. And T5 IoC can be used separately from the rest of Tapestry!</p><h2 id="IOC-WhyNotSpring?">Why Not Spring?</h2><p><a  class="external-link" href="http://www.springframework.org" rel="nofollow">Spring</a> is the most successful IoC container project. The Spring project combines a very good IoC container, integrated <a  class="external-link" href="http://www.eclipse.org/aspectj/" rel="nofollow">AspectJ</a> support, and a large number of libraries built on top of the container. Spring is an excellent <em>application</em> container, but lacks a number of features necessary for a <em>framework</em> container:</p><ul><li>Spring beans can be wired together by name (or id), but it is not possible to introduce additional naming abstractions. Tapestry 4's "infrastructure:" abstraction was the
  key to allowing easy spot overrides of internal Tapestry services without having to duplicate the large web of interrelated services (nearly 200 in Tapestry 4.0).</li><li>Although Spring allows beans to be intercepted, it does so in the form of a new bean, leaving the un-intercepted bean visible (and subject to misuse). Tapestry IoC "wraps" the service inside interceptors, preventing un-intercepted access to the core service implementation.</li><li>Spring's XML configuration files are quite verbose. This has improved with Spring 2.0, but still far more verbose that T5 IoC module classes.</li><li>Spring has a simple map/list/value configuration scheme, but it is not distributed; it is part of a single bean definition. Tapestry 5 IoC allows a service configuration to be assembled from multiple modules. This is very important for seamless extensibility of the framework, with zero configuration (just drop the module into the classpath and everything hooks together).</li></ul><h2 id="IO
 C-WhyNotHiveMind?">Why Not HiveMind?</h2><p>The difficulty of managing the release schedules of two complex frameworks proved to be an issue.</p><p>The use of HiveMind was also related to one of the common criticisms of Tapestry 4: startup time. The time it took to parse and organize all that XML showed up as several seconds of startup time. Creating a streamlined IoC container that is not driven by XML has alleviated those issues.</p><p>With the advent of new technologies (in particular, JDK 1.5 <a  class="external-link" href="http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html" rel="nofollow">Annotations</a> and runtime class generation via <a  class="external-link" href="http://www.jboss.org/products/javassist" rel="nofollow">Javassist</a>) some of the precepts of HiveMind were undermined. That is to say, in HiveMind (as in Spring), all that XML was an awkward way to describe a few basic Java operations: instantiating classes and invoking methods on those clas
 ses (to inject dependencies into the instantiated instances). The central concept in Tapestry IoC is to eliminate XML and build an equivalent system around simple objects and methods.</p><p>Tapestry IoC also represents many simplifications of HiveMind, building on lessons learned from both HiveMind and Tapestry 4. The HiveMind project itself is no longer under development, and most of the user base has moved to Tapestry 5.</p><h2 id="IOC-WhynotGuice?">Why not Guice?</h2><p><a  class="external-link" href="http://code.google.com/p/google-guice/" rel="nofollow">Google Guice</a> is a relative newcomer to the IoC landscape. Guice and T5 IoC are very close and, in fact, T5 IoC expressly borrows many great and innovative ideas from Guice. Guice abandons not only XML but even any concept of a service id ... for injection, services are matched by type and perhaps filtered based on annotations.</p><p>Guice is still missing some core ideas needed in T5 IoC. There's no concept of configurations
  or anything similar. And there are limitations on injection based on scope (a request scoped value can't be injected into a global scope service; in T5 IoC, scope is internal to the proxy and never an issue).</p><h1 id="IOC-Goals">Goals</h1><p>As with Tapestry 5 in general, the goal of Tapestry IoC is greater simplicity, greater power, and an avoidance of XML.</p><p>Existing IoC containers such as HiveMind and Spring typically contain large amounts of XML configuration that exists to describe how and when to instantiate a particular JavaBean, and how to provide that bean with its dependencies (either by constructor injection, or by property injection). Other XML is used to hook objects into some form of life cycle ... typically callback methods invoked when the object is instantiated and configured, or when it is being discarded.</p><p>The core concept of Tapestry IoC is that the Java language itself is the easiest and most succinct way to describe object creation and method invoca
 tion. Any approximation in XML is ultimately more verbose and unwieldy. As the <a  href="defining-tapestry-ioc-services.html">examples</a> show, a small amount of Java code and a handful of naming conventions and annotations is far simpler and easier than a big chunk of XML.</p><p>In addition, moving from XML to Java code encourages testing; you can unit test the service builder methods of your module class, but you can't realistically unit test an XML descriptor.</p><p>Tapestry IoC modules are easily packaged into JAR files, supporting zero-configuration usage: just drop the JAR onto the classpath.</p><p>Another goal is "developer friendliness". This is a true cross-cutting concern, and one not likely to be packaged into an aspect any time soon. The Tapestry IoC framework is designed to be easy to use and easy to understand. Further, when things go wrong, it actively attempts to help you via comprehensive checks and carefully composed error messages. Further, all user-visible objec
 ts implement a <a  class="external-link" href="http://howardlewisship.com/blog/2003/08/importance-of-tostring.html" rel="nofollow">reasonable toString() method</a>, to help you understand what's going when you inevitably try to figure things out in the debugger.</p><p>In terms of building services using Tapestry IoC ... the objective here is "lightness", a term borrowed from the board game <a  class="external-link" href="http://boardgamegeek.com/game/188" rel="nofollow">Go</a>. In Go, two players place stones on an initially empty board, creating walls to enclose territory or eliminate the encroaching stones played by the opponent. The winner at the end of the game controls the most territory, and it is the constant tension between taking territory and defending existing territory that drives the game. In Go, groups of playing stones are "light" (or have "good shape") when the minimum number of them control the maximum area on the board. Playing "heavy" just gives your opponent a fr
 ee chance to take control of another section of the board.</p><p>In software development, we are also attempting to create complex systems from simple pieces, but our tension is derived from the need to add functionality balanced against the need to test and maintain existing code. Too often in the world of software development, the need to add functionality trumps all, and testing and maintenance is deferred ... until too late.</p><p>IoC containers in general, and Tapestry IoC very specifically, exist to address this issue, to provide the foundations for balancing the need to quickly add functionality against the need to test new functionality and maintain existing functionality. IoC containers provide the means to break large, complex, monolithic blocks into light, small, testable pieces.</p><p>When building a registry of services, lightness refers to the proper division of responsibility, the separation of concerns, and the limiting of dependencies between different parts of the 
 system. This style is often called <a  class="external-link" href="http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/general-formulation.html" rel="nofollow">Law of Demeter</a>. Using an IoC container makes it easier to embrace this approach, since one critical concern, which objects are responsible for instantiating which others, is entirely managed by the container. With this life cycle concern removed, it becomes very easy to reduce complex chunks of code into small, testable, reusable services.</p><p>"Light" means:</p><ul><li>Small interfaces of two or three methods.</li><li>Small methods, with two or three parameters (because dependencies are injected in behind the scenes, rather than passed into the method).</li><li>Anonymous communication via events, rather than explicit method invocations. The service implementation can implement an event listener interface.</li></ul><p>See <a  class="external-link" href="http://www.pragmaticprogrammer.com/ppbook/index.shtm
 l" rel="nofollow">The Pragmatic Programmer</a> for more insights into building solid code.</p><h1 id="IOC-Terminology">Terminology</h1><p>The basic unit in Tapestry IoC is a <strong>service</strong>. A service consists of a <strong>service interface</strong> and a <strong>service implementation</strong>. The service interface is an ordinary Java interface. The service implementation is a Java object that implements the service interface. Often there will only be a single service per service interface, but in some situations, there may be many different services and service implementations all sharing the same service interface.</p><p>Services are identified by a unique id. Typically, a service id matches the unqualified name of the service interface, but this is simply a convention.</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-i
 nformation-macro-body"><p>The evolutionary direction of the Tapestry IoC is to eventually eliminate service ids and work totally in terms of service interfaces and marker annotations.</p></div></div><p>Services are aggregated into <strong>modules</strong>:</p><ul><li>A module is defined by a <strong>module class</strong>, a specific class containing a mix of static or instance methods, used to define services, decorate them (see below), or contribute to service configurations (again, more below).</li><li>Methods of the module class define the services provided by the module, and the same methods are responsible for instantiating the service implementation.</li></ul><p>The methods which define and construct services are called <strong>service builder methods</strong>.</p><p>The <strong>registry</strong> is the outside world's view of the modules and services. From the registry, it is possible to obtain a service, via its unique id or by its service interface. Access by unique id is <
 em>caseless</em> (meaning, a match will be found even the case of the search key doesn't match the case of the service id itself).</p><p>Services may be <strong>decorated</strong> by <strong>service decorator methods</strong>. These methods create <strong>interceptor</strong> objects that wrap around core service implementations, adding behavior such as logging, security access, or transaction management. Interceptors implement the same service interface as the service. Control is given over the order in which decorators are applied to a service.</p><p>A service may have a <strong>configuration</strong>. The configuration is either a map, a collection, or an ordered list. The service defines the type of object allowed to be contributed into the configuration. The configuration is constructed from <strong>contributions</strong> provided by one or more modules. <strong>Service contributor methods</strong> are invoked to contribute objects into configurations.</p><p>Services are instan
 tiated as needed. In this case, "need" translates to "when a method of the service is invoked". A service is represented (to the outside world, or to other services) as a <strong>proxy</strong> that implements the service interface. The first time a method is invoked on the proxy, the full service (consisting of the core service implementation wrapped with any interceptors) is constructed. This occurs in a completely <strong>thread-safe</strong> manner. Just-in-time instantiation allows for more complex, more finely grained networks of services, and improves start-up time.</p><p>Instantiating a service, injecting dependencies, and decorating the service are all parts of service <strong>realization</strong>, the point at which a service transitions from virtual (just a proxy) to real (fully instantiated and ready to operate).</p><p>Services define a <strong>scope</strong> that controls when the service is constructed, as well as its visibility. The default scope is <strong>singleton<
 /strong>, meaning a single global instance created as needed. Other scopes allow service implementations to be bound to the current thread (i.e., the current request in a servlet application).</p><p><strong>Dependencies</strong> are other services (or other objects) that are needed by a service implementation. These dependencies can be <strong>injected</strong> into a service builder method and provided, from there, to a service implementation via its constructor, or via methods on the service implementation. These may also be referred to as <strong>collaborators</strong>, especially in the context of writing unit tests.</p><p>The <strong>point of Injection</strong> is a field, method parameter, or constructor parameter that receives an injected value. The type of service (or other dependency) is determined by the type of the field or parameter. Often, annotations further identify what is to be injected, or in the case of field injection, that an injection is required.</p><h2 id="IO
 C-IoCSubtopics">IoC Subtopics</h2><p></p><ul class="childpages-macro"><li><a  href="tapestry-ioc-overview.html">Tapestry IoC Overview</a></li><li><a  href="tapestry-ioc-modules.html">Tapestry IoC Modules</a></li><li><a  href="defining-tapestry-ioc-services.html">Defining Tapestry IOC Services</a></li><li><a  href="service-advisors.html">Service Advisors</a></li><li><a  href="tapestry-ioc-decorators.html">Tapestry IoC Decorators</a></li><li><a  href="tapestry-ioc-configuration.html">Tapestry IoC Configuration</a></li><li><a  href="case-insensitivity.html">Case Insensitivity</a></li><li><a  href="autoloading-modules.html">Autoloading Modules</a></li><li><a  href="service-implementation-reloading.html">Service Implementation Reloading</a></li><li><a  href="ordering-by-constraints.html">Ordering by Constraints</a></li><li><a  href="symbols.html">Symbols</a></li><li><a  href="chainbuilder-service.html">ChainBuilder Service</a></li><li><a  href="pipelinebuilder-service.html">PipelineBuild
 er Service</a></li><li><a  href="shadowbuilder-service.html">ShadowBuilder Service</a></li><li><a  href="strategybuilder-service.html">StrategyBuilder Service</a></li><li><a  href="injection-in-detail.html">Injection in Detail</a></li><li><a  href="object-providers.html">Object Providers</a></li><li><a  href="service-serialization.html">Service Serialization</a></li><li><a  href="type-coercion.html">Type Coercion</a></li><li><a  href="starting-the-ioc-registry.html">Starting the IoC Registry</a></li><li><a  href="registry-startup.html">Registry Startup</a></li><li><a  href="parallel-execution.html">Parallel Execution</a></li><li><a  href="logging-in-tapestry.html">Logging in Tapestry</a></li><li><a  href="using-jsr-330-standard-annotations.html">Using JSR 330 standard annotations</a></li><li><a  href="operation-tracker.html">Operation Tracker</a></li></ul></div>
+                <div id="ConfluenceContent"><p>Tapestry's <strong>Inversion of Control</strong> container is a built-in Tapestry module based on <a  class="external-link" href="http://www.martinfowler.com/articles/injection.html" rel="nofollow">inversion of control</a> (IoC), a design approach that allows a working system to be fabricated from many small, easily testable pieces.</p><parameter ac:name="style">float:right</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="class">aui-label</parameter><rich-text-body><parameter ac:name="showLabels">false</parameter><parameter ac:name="showSpace">false</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="cql">label = "ioc" and space = currentSpace()</parameter></rich-text-body><p>An additional benefit of using IoC is that, by breaking a complex system into small pieces, it becomes easier to modify and extend the system, by overriding or replacing selected parts of the sy
 stem.</p><p>The use of IoC in Tapestry represents an evolution from Tapestry 3 to Tapestry 4 to Tapestry 5. Tapestry 3 did not use IoC, though it included some weaker mechanisms, such as extensions, that served a similar purpose. To make large scale changes to the behavior of Tapestry 3 required subclassing key classes and overriding methods.</p><p>Tapestry 4 introduced the use of the <a  class="external-link" href="http://hivemind.apache.org/">Apache HiveMind</a> IoC container. In fact, the HiveMind project was created specifically for use as the IoC container for Tapestry 4. Tapestry 4 has met its goals for extensibility and configurability, largely because of HiveMind's flexibility.</p><p>Tapestry 5 extends on this, replacing HiveMind with a new container specifically build for Tapestry 5, designed for greater ease of use, expressiveness and performance. HiveMind itself has been subsequently shelved; T5 IoC can be considered a streamlined and improved HiveMind. And T5 IoC can be 
 used separately from the rest of Tapestry!</p><h2 id="IOC-WhyNotSpring?">Why Not Spring?</h2><p><a  class="external-link" href="http://www.springframework.org" rel="nofollow">Spring</a> is the most successful IoC container project. The Spring project combines a very good IoC container, integrated <a  class="external-link" href="http://www.eclipse.org/aspectj/" rel="nofollow">AspectJ</a> support, and a large number of libraries built on top of the container. Spring is an excellent <em>application</em> container, but lacks a number of features necessary for a <em>framework</em> container:</p><ul><li>Spring beans can be wired together by name (or id), but it is not possible to introduce additional naming abstractions. Tapestry 4's "infrastructure:" abstraction was the key to allowing easy spot overrides of internal Tapestry services without having to duplicate the large web of interrelated services (nearly 200 in Tapestry 4.0).</li><li>Although Spring allows beans to be intercepted, it
  does so in the form of a new bean, leaving the un-intercepted bean visible (and subject to misuse). Tapestry IoC "wraps" the service inside interceptors, preventing un-intercepted access to the core service implementation.</li><li>Spring's XML configuration files are quite verbose. This has improved with Spring 2.0, but still far more verbose that T5 IoC module classes.</li><li>Spring has a simple map/list/value configuration scheme, but it is not distributed; it is part of a single bean definition. Tapestry 5 IoC allows a service configuration to be assembled from multiple modules. This is very important for seamless extensibility of the framework, with zero configuration (just drop the module into the classpath and everything hooks together).</li></ul><h2 id="IOC-WhyNotHiveMind?">Why Not HiveMind?</h2><p>The difficulty of managing the release schedules of two complex frameworks proved to be an issue.</p><p>The use of HiveMind was also related to one of the common criticisms of Ta
 pestry 4: startup time. The time it took to parse and organize all that XML showed up as several seconds of startup time. Creating a streamlined IoC container that is not driven by XML has alleviated those issues.</p><p>With the advent of new technologies (in particular, JDK 1.5 <a  class="external-link" href="http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html" rel="nofollow">Annotations</a> and runtime class generation via <a  class="external-link" href="http://www.jboss.org/products/javassist" rel="nofollow">Javassist</a>) some of the precepts of HiveMind were undermined. That is to say, in HiveMind (as in Spring), all that XML was an awkward way to describe a few basic Java operations: instantiating classes and invoking methods on those classes (to inject dependencies into the instantiated instances). The central concept in Tapestry IoC is to eliminate XML and build an equivalent system around simple objects and methods.</p><p>Tapestry IoC also represents man
 y simplifications of HiveMind, building on lessons learned from both HiveMind and Tapestry 4. The HiveMind project itself is no longer under development, and most of the user base has moved to Tapestry 5.</p><h2 id="IOC-WhynotGuice?">Why not Guice?</h2><p><a  class="external-link" href="http://code.google.com/p/google-guice/" rel="nofollow">Google Guice</a> is a relative newcomer to the IoC landscape. Guice and T5 IoC are very close and, in fact, T5 IoC expressly borrows many great and innovative ideas from Guice. Guice abandons not only XML but even any concept of a service id ... for injection, services are matched by type and perhaps filtered based on annotations.</p><p>Guice is still missing some core ideas needed in T5 IoC. There's no concept of configurations or anything similar. And there are limitations on injection based on scope (a request scoped value can't be injected into a global scope service; in T5 IoC, scope is internal to the proxy and never an issue).</p><h1 id="I
 OC-Goals">Goals</h1><p>As with Tapestry 5 in general, the goal of Tapestry IoC is greater simplicity, greater power, and an avoidance of XML.</p><p>Existing IoC containers such as HiveMind and Spring typically contain large amounts of XML configuration that exists to describe how and when to instantiate a particular JavaBean, and how to provide that bean with its dependencies (either by constructor injection, or by property injection). Other XML is used to hook objects into some form of life cycle ... typically callback methods invoked when the object is instantiated and configured, or when it is being discarded.</p><p>The core concept of Tapestry IoC is that the Java language itself is the easiest and most succinct way to describe object creation and method invocation. Any approximation in XML is ultimately more verbose and unwieldy. As the <a  href="defining-tapestry-ioc-services.html">examples</a> show, a small amount of Java code and a handful of naming conventions and annotatio
 ns is far simpler and easier than a big chunk of XML.</p><p>In addition, moving from XML to Java code encourages testing; you can unit test the service builder methods of your module class, but you can't realistically unit test an XML descriptor.</p><p>Tapestry IoC modules are easily packaged into JAR files, supporting zero-configuration usage: just drop the JAR onto the classpath.</p><p>Another goal is "developer friendliness". This is a true cross-cutting concern, and one not likely to be packaged into an aspect any time soon. The Tapestry IoC framework is designed to be easy to use and easy to understand. Further, when things go wrong, it actively attempts to help you via comprehensive checks and carefully composed error messages. Further, all user-visible objects implement a <a  class="external-link" href="http://howardlewisship.com/blog/2003/08/importance-of-tostring.html" rel="nofollow">reasonable toString() method</a>, to help you understand what's going when you inevitably t
 ry to figure things out in the debugger.</p><p>In terms of building services using Tapestry IoC ... the objective here is "lightness", a term borrowed from the board game <a  class="external-link" href="http://boardgamegeek.com/game/188" rel="nofollow">Go</a>. In Go, two players place stones on an initially empty board, creating walls to enclose territory or eliminate the encroaching stones played by the opponent. The winner at the end of the game controls the most territory, and it is the constant tension between taking territory and defending existing territory that drives the game. In Go, groups of playing stones are "light" (or have "good shape") when the minimum number of them control the maximum area on the board. Playing "heavy" just gives your opponent a free chance to take control of another section of the board.</p><p>In software development, we are also attempting to create complex systems from simple pieces, but our tension is derived from the need to add functionality b
 alanced against the need to test and maintain existing code. Too often in the world of software development, the need to add functionality trumps all, and testing and maintenance is deferred ... until too late.</p><p>IoC containers in general, and Tapestry IoC very specifically, exist to address this issue, to provide the foundations for balancing the need to quickly add functionality against the need to test new functionality and maintain existing functionality. IoC containers provide the means to break large, complex, monolithic blocks into light, small, testable pieces.</p><p>When building a registry of services, lightness refers to the proper division of responsibility, the separation of concerns, and the limiting of dependencies between different parts of the system. This style is often called <a  class="external-link" href="http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/general-formulation.html" rel="nofollow">Law of Demeter</a>. Using an IoC container mak
 es it easier to embrace this approach, since one critical concern, which objects are responsible for instantiating which others, is entirely managed by the container. With this life cycle concern removed, it becomes very easy to reduce complex chunks of code into small, testable, reusable services.</p><p>"Light" means:</p><ul><li>Small interfaces of two or three methods.</li><li>Small methods, with two or three parameters (because dependencies are injected in behind the scenes, rather than passed into the method).</li><li>Anonymous communication via events, rather than explicit method invocations. The service implementation can implement an event listener interface.</li></ul><p>See <a  class="external-link" href="http://www.pragmaticprogrammer.com/ppbook/index.shtml" rel="nofollow">The Pragmatic Programmer</a> for more insights into building solid code.</p><h1 id="IOC-Terminology">Terminology</h1><p>The basic unit in Tapestry IoC is a <strong>service</strong>. A service consists of 
 a <strong>service interface</strong> and a <strong>service implementation</strong>. The service interface is an ordinary Java interface. The service implementation is a Java object that implements the service interface. Often there will only be a single service per service interface, but in some situations, there may be many different services and service implementations all sharing the same service interface.</p><p>Services are identified by a unique id. Typically, a service id matches the unqualified name of the service interface, but this is simply a convention.</p><rich-text-body><p>The evolutionary direction of the Tapestry IoC is to eventually eliminate service ids and work totally in terms of service interfaces and marker annotations.</p></rich-text-body><p>Services are aggregated into <strong>modules</strong>:</p><ul><li>A module is defined by a <strong>module class</strong>, a specific class containing a mix of static or instance methods, used to define services, decorate t
 hem (see below), or contribute to service configurations (again, more below).</li><li>Methods of the module class define the services provided by the module, and the same methods are responsible for instantiating the service implementation.</li></ul><p>The methods which define and construct services are called <strong>service builder methods</strong>.</p><p>The <strong>registry</strong> is the outside world's view of the modules and services. From the registry, it is possible to obtain a service, via its unique id or by its service interface. Access by unique id is <em>caseless</em> (meaning, a match will be found even the case of the search key doesn't match the case of the service id itself).</p><p>Services may be <strong>decorated</strong> by <strong>service decorator methods</strong>. These methods create <strong>interceptor</strong> objects that wrap around core service implementations, adding behavior such as logging, security access, or transaction management. Interceptors im
 plement the same service interface as the service. Control is given over the order in which decorators are applied to a service.</p><p>A service may have a <strong>configuration</strong>. The configuration is either a map, a collection, or an ordered list. The service defines the type of object allowed to be contributed into the configuration. The configuration is constructed from <strong>contributions</strong> provided by one or more modules. <strong>Service contributor methods</strong> are invoked to contribute objects into configurations.</p><p>Services are instantiated as needed. In this case, "need" translates to "when a method of the service is invoked". A service is represented (to the outside world, or to other services) as a <strong>proxy</strong> that implements the service interface. The first time a method is invoked on the proxy, the full service (consisting of the core service implementation wrapped with any interceptors) is constructed. This occurs in a completely <st
 rong>thread-safe</strong> manner. Just-in-time instantiation allows for more complex, more finely grained networks of services, and improves start-up time.</p><p>Instantiating a service, injecting dependencies, and decorating the service are all parts of service <strong>realization</strong>, the point at which a service transitions from virtual (just a proxy) to real (fully instantiated and ready to operate).</p><p>Services define a <strong>scope</strong> that controls when the service is constructed, as well as its visibility. The default scope is <strong>singleton</strong>, meaning a single global instance created as needed. Other scopes allow service implementations to be bound to the current thread (i.e., the current request in a servlet application).</p><p><strong>Dependencies</strong> are other services (or other objects) that are needed by a service implementation. These dependencies can be <strong>injected</strong> into a service builder method and provided, from there, to a
  service implementation via its constructor, or via methods on the service implementation. These may also be referred to as <strong>collaborators</strong>, especially in the context of writing unit tests.</p><p>The <strong>point of Injection</strong> is a field, method parameter, or constructor parameter that receives an injected value. The type of service (or other dependency) is determined by the type of the field or parameter. Often, annotations further identify what is to be injected, or in the case of field injection, that an injection is required.</p><h2 id="IOC-IoCSubtopics">IoC Subtopics</h2><p></p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/javascript-faq.html
==============================================================================
--- websites/production/tapestry/content/javascript-faq.html (original)
+++ websites/production/tapestry/content/javascript-faq.html Sat Sep 16 02:22:40 2017
@@ -27,16 +27,6 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
-          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
-    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
-    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
-          <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
-          <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
-          <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
-        <script>
-      SyntaxHighlighter.defaults['toolbar'] = false;
-      SyntaxHighlighter.all();
-    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -77,7 +67,7 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h2 id="JavaScriptFAQ-JavaScript">JavaScript</h2><p>Main article: <a  href="legacy-javascript.html">Legacy JavaScript</a></p><h3 id="JavaScriptFAQ-WhydoIgeta&quot;Tapestryisundefined&quot;erroronformsubmit?(5.3andearlier)">Why do I get a "Tapestry is undefined" error on form submit? (5.3 and earlier)</h3><p>This client-side error is clear but can be awkward to solve. It means your browser has not been able to load the tapestry.js file properly. The question is, why? It can be due to multiple reasons, some of them below:</p><ul><li>First, check if 'tapestry.js' is present in the head part of your resulting HTML page.</li><li><p>If you have set the <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/SymbolConstants.html#COMBINE_SCRIPTS">tapestry.combine-scripts</a> configuration symbol to true, Tapestry generates one single URL to retrieve all the JS files. Sometimes, this can produce long URLs tha
 t browsers are unable to retrieve. Try setting the symbol to false.</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>This only applies to Tapestry 5.1.</p></div></div></li><li>If you have included jQuery in conjunction with Tapestry's prototype, that will cause a conflict with the '$' selector used by both. In this case, you should put jQuery on top of the stack and turn on the <a  class="external-link" href="http://api.jquery.com/jQuery.noConflict/" rel="nofollow">jQuery.noConflict</a> mode.</li><li>Also, if you have included a custom or third-party JS library on top of the stack that causes the JavaScript parsing to fail, then check the JavaScript syntax in that library.</li><li>If you have used a tool to minimize your JavaScript libraries, this can lead to JavaScript syntax errors, so check if it works 
 with all the JavaScript files unpacked.</li></ul><h3 id="JavaScriptFAQ-What'sthedifferencebetweentheT5objectandtheTapestryobjectinthebrowser?(5.3andearlier)">What's the difference between the <code>T5</code> object and the <code>Tapestry</code> object in the browser? (5.3 and earlier)</h3><p>Both of these objects are <em>namespaces</em>: containers of functions, constants, and nested namespaces.</p><p>The <code>T5</code> object is a replacement for the <code>Tapestry</code> object, starting in release 5.3. Increasingly, functions defined by the <code>Tapestry</code> object are being replaced with similar or equivalent functions in the <code>T5</code> object.</p><p>This is part of an overall goal, spanning at least two releases of Tapestry, to make Tapestry JavaScript framework agnostic; which is to say, not depend specifically on Prototype or jQuery. Much of the code in the <code>Tapestry</code> object is specifically linked to Prototype and Scriptaculous.</p><p>The <code>T5</code> 
 object represents a stable, documented, set of APIs that are preferred when building components for maximum portability between underlying JavaScript frameworks. In other words, when building component libraries, coding to the <code>T5</code> object ensures that your component will be useful regardless of whether the final application is built using Prototype, jQuery or something else.</p></div>
+                <div id="ConfluenceContent"><plain-text-body>{scrollbar}</plain-text-body><h2 id="JavaScriptFAQ-JavaScript">JavaScript</h2><p>Main article: <a  href="legacy-javascript.html">Legacy JavaScript</a></p><h3 id="JavaScriptFAQ-WhydoIgeta&quot;Tapestryisundefined&quot;erroronformsubmit?(5.3andearlier)">Why do I get a "Tapestry is undefined" error on form submit? (5.3 and earlier)</h3><p>This client-side error is clear but can be awkward to solve. It means your browser has not been able to load the tapestry.js file properly. The question is, why? It can be due to multiple reasons, some of them below:</p><ul><li>First, check if 'tapestry.js' is present in the head part of your resulting HTML page.</li><li><p>If you have set the <a  class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/SymbolConstants.html#COMBINE_SCRIPTS">tapestry.combine-scripts</a> configuration symbol to true, Tapestry generates one single URL to retrieve all the JS fi
 les. Sometimes, this can produce long URLs that browsers are unable to retrieve. Try setting the symbol to false.</p><rich-text-body><p>This only applies to Tapestry 5.1.</p></rich-text-body></li><li>If you have included jQuery in conjunction with Tapestry's prototype, that will cause a conflict with the '$' selector used by both. In this case, you should put jQuery on top of the stack and turn on the <a  class="external-link" href="http://api.jquery.com/jQuery.noConflict/" rel="nofollow">jQuery.noConflict</a> mode.</li><li>Also, if you have included a custom or third-party JS library on top of the stack that causes the JavaScript parsing to fail, then check the JavaScript syntax in that library.</li><li>If you have used a tool to minimize your JavaScript libraries, this can lead to JavaScript syntax errors, so check if it works with all the JavaScript files unpacked.</li></ul><h3 id="JavaScriptFAQ-What'sthedifferencebetweentheT5objectandtheTapestryobjectinthebrowser?(5.3andearlier)
 ">What's the difference between the <code>T5</code> object and the <code>Tapestry</code> object in the browser? (5.3 and earlier)</h3><p>Both of these objects are <em>namespaces</em>: containers of functions, constants, and nested namespaces.</p><p>The <code>T5</code> object is a replacement for the <code>Tapestry</code> object, starting in release 5.3. Increasingly, functions defined by the <code>Tapestry</code> object are being replaced with similar or equivalent functions in the <code>T5</code> object.</p><p>This is part of an overall goal, spanning at least two releases of Tapestry, to make Tapestry JavaScript framework agnostic; which is to say, not depend specifically on Prototype or jQuery. Much of the code in the <code>Tapestry</code> object is specifically linked to Prototype and Scriptaculous.</p><p>The <code>T5</code> object represents a stable, documented, set of APIs that are preferred when building components for maximum portability between underlying JavaScript framew
 orks. In other words, when building component libraries, coding to the <code>T5</code> object ensures that your component will be useful regardless of whether the final application is built using Prototype, jQuery or something else.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/javascript-modules.html
==============================================================================
--- websites/production/tapestry/content/javascript-modules.html (original)
+++ websites/production/tapestry/content/javascript-modules.html Sat Sep 16 02:22:40 2017
@@ -27,15 +27,6 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
-          <link href='/resources/highlighter/styles/shCoreCXF.css' rel='stylesheet' type='text/css' />
-    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css' />
-    <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
-          <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
-          <script src='/resources/highlighter/scripts/shBrushJScript.js' type='text/javascript'></script>
-        <script>
-      SyntaxHighlighter.defaults['toolbar'] = false;
-      SyntaxHighlighter.all();
-    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -45,13 +36,26 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  href="index.html">Home</a></li><li><a  href="getting-started.html">Getting Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  href="download.html">Download</a></li><li><a  href="about.html">About</a></li><li><a  class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a  href="community.html">Community</a></li><li><a  class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a  class="external-link" href="http://www.apache.org/">Apache</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a  class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div>
+
+</div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">JavaScript Modules</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html">
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">JavaScript Modules</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -63,72 +67,19 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><strong>JavaScript Modules</strong> are a mechanism for bringing modern concepts of variable scope and dependency management to JavaScript. <em>Starting with version 5.4</em>, Tapestry uses <a  class="external-link" href="http://requirejs.org/" rel="nofollow">RequireJS</a> <a  class="external-link" href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md" rel="nofollow">&#160;</a>modules internally, and provides support for using RequireJS modules in your own Tapestry application.</p><div class="aui-label" style="float:right" title="Related Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="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> 
-  <div class="details"> 
-   <a  href="client-side-javascript.html">Client-Side JavaScript</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="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> 
-  <div class="details"> 
-   <a  href="javascript-faq.html">JavaScript FAQ</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="ajax-and-zones.html">Ajax and Zones</a> 
-  </div> </li><li> 
-  <div> 
-   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> 
-  </div> 
-  <div class="details"> 
-   <a  href="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> 
-  <div class="details"> 
-   <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> 
-  <div class="details"> 
-   <a  href="assets.html">Assets</a> 
-  </div> </li></ul></div><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) {
+                <div id="ConfluenceContent"><p><strong>JavaScript Modules</strong> are a mechanism for bringing modern concepts of variable scope and dependency management to JavaScript. <em>Starting with version 5.4</em>, Tapestry uses <a  class="external-link" href="http://requirejs.org/" rel="nofollow">RequireJS</a> <a  class="external-link" href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md" rel="nofollow">&#160;</a>modules internally, and provides support for using RequireJS modules in your own Tapestry application.</p><parameter ac:name="style">float:right</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="class">aui-label</parameter><rich-text-body><parameter ac:name="showLabels">false</parameter><parameter ac:name="showSpace">false</parameter><parameter ac:name="title">Related Articles</parameter><parameter ac:name="cql">label = "javascript" and space = currentSpace()</parameter></rich-text-body><h2 id="JavaScriptModules-TheNeedfor
 Modules">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><parameter ac:name="language">js</parameter><plain-text-body>function onclickHelp(event) {
   if (helpModal === undefined) {
     helpModal = ...
   }
   document.getElementById("modalContainer") ...
 }
-$("#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() {
+$("#helpButton").click(onClickHelp);</plain-text-body><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><parameter ac:name="language">js</parameter><plain-text-body>(function() {
   var helpModal = null;
 
   function onClickHelp(event) { ... }
 
   $("#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() {
+})();</plain-text-body><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 o
 f bells and whistles that can themselves be quite important.</p><rich-text-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></rich-text-body><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><parameter ac:name="language">js</parameter><parameter ac:name="title">Module t5/core/confirm-click</parameter><plain-text-body>(function() {
   define(["jquery", "./events", "./dom", "bootstrap/modal"], function($, events, dom) {
     var runDialog;
     runDialog = function(options) {
@@ -144,15 +95,11 @@ $("#helpButton").click(onClickHelp);</pr
       runDialog: runDialog
     };
   });
-}).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; 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">monkey 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")
+}).call(this);</plain-text-body><rich-text-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></rich-text-body><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><rich-text-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></rich-text-body><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 JavaScript 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; per
 haps 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 conflicts. 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; 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">monkey 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><parameter ac:name="language">java</parameter><plain-text-body>@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
+}</plain-text-body><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><parameter ac:name="language">java</parameter><plain-text-body>  @Environmental
   JavaScriptSupport javaScriptSupport;
 
   ...
@@ -161,15 +108,12 @@ 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" src="javascript-modules.data/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png"></span></p><p>This lists modules&#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 M
 odules</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 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 module, 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/o
 rg/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> 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 depende
 ncy 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)
+  javaScriptSupport.require("my-module").invoke("setup").with(clientId, actionUrl);</plain-text-body><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" src="javascript-modules.data/Tapestry_Integration_Test_Application_and_JavaScriptSupport__Tapestry_API_Documentation_.png"></span></p><p>This lists modules&#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 libra
 ries 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 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><rich-text-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 the client-side cache when its developer tools are open.</p></rich-text-body><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> 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><parameter ac:name="language">java</parameter><plain-text-body>    @Contribute(JavaScriptStack.class)
     @Core
     public static void addAppModules(OrderedConfiguration&lt;StackExtension&gt; configuration) {
         configuration.add("tree-viewer", StackExtension.module("tree-viewer"));
 		configuration.add("app-utils", StackExtension.module("app-utils"));
-    }</pre>
-</div></div><p>To break this down:</p><ul><li>@Contribute indicates we are contributing to a JavaScriptStack service</li><li>Since there are (or at least, could be) multiple services that implement JavaScriptStack, we provide the&#160;@Core annotation to indicate which one we are contributing to (this is a marker annotation, which exists for this exact purpose)</li><li>It is possible to contribute libraries, CSS files, other stacks, and modules; here we are contributing modules</li><li>Each contribution has a unique id and a <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/StackExtension.html">StackExtension</a> value</li></ul><p>The core stack includes several libraries and modules; the exact configuration is subject to a number of factors (such as whether Prototype or jQuery is being used as the underlying framework). That being said, this is the&#160;<em>current</em> list of modules aggregated into the core stack:</p>
 <ul><li>jquery</li><li>underscore</li><li>t5/core/<ul><li>alert</li><li>ajax</li><li>bootstrap</li><li>console</li><li>dom</li><li>events</li><li>exception-frame</li><li>fields</li><li>pageinit</li><li>messages</li><li>util</li><li>validation</li></ul></li></ul><p>The optimum configuration is always a balancing act between including too little and including too much. Generally speaking, including too much is less costly than including too little. It is up to you to analyze the requests coming into your application and determine what modules should be aggregated.</p></div>
+    }</plain-text-body><p>To break this down:</p><ul><li>@Contribute indicates we are contributing to a JavaScriptStack service</li><li>Since there are (or at least, could be) multiple services that implement JavaScriptStack, we provide the&#160;@Core annotation to indicate which one we are contributing to (this is a marker annotation, which exists for this exact purpose)</li><li>It is possible to contribute libraries, CSS files, other stacks, and modules; here we are contributing modules</li><li>Each contribution has a unique id and a <a  class="external-link" href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/javascript/StackExtension.html">StackExtension</a> value</li></ul><p>The core stack includes several libraries and modules; the exact configuration is subject to a number of factors (such as whether Prototype or jQuery is being used as the underlying framework). That being said, this is the&#160;<em>current</em> list of modules aggregated into the core
  stack:</p><ul><li>jquery</li><li>underscore</li><li>t5/core/<ul><li>alert</li><li>ajax</li><li>bootstrap</li><li>console</li><li>dom</li><li>events</li><li>exception-frame</li><li>fields</li><li>pageinit</li><li>messages</li><li>util</li><li>validation</li></ul></li></ul><p>The optimum configuration is always a balancing act between including too little and including too much. Generally speaking, including too much is less costly than including too little. It is up to you to analyze the requests coming into your application and determine what modules should be aggregated.</p></div>
       </div>
 
       <div class="clearer"></div>