Modified: websites/production/tapestry/content/ioc.html
==============================================================================
--- websites/production/tapestry/content/ioc.html (original)
+++ websites/production/tapestry/content/ioc.html Sat Feb  3 17:21:22 2018
@@ -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,58 @@
       </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><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 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 spo
 t 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 No
 t 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 classes (to inject dependenci
 es 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 invocation. Any approximation i
 n XML is ultimately more verbose and unwieldy. As the <a  
href="ioc.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 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 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 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 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="extern
 al-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.shtml"; rel="nofollow">The 
Pragmatic Programmer</a> for m
 ore 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-information-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 eve
 n 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 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 
<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 a
 s 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><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">PipelineBuilder Service</a></li><li><a  
href="shadowbuilder-servi
 ce.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>
 
       <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 Feb  3 
17:21:22 2018
@@ -45,13 +45,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,55 +76,94 @@
       </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">
+                <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) {
   if (helpModal === undefined) {
     helpModal = ...
@@ -145,7 +197,7 @@ $("#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; 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">
+</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="javascript-modules.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 n
 aming conflicts. Tapestry's own modules are prefixed with 
<code>t5/core</code>.</p><p>If you are using the optional&#160;<code><a  
href="javascript-modules.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 existi
 ng 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")
 public class Confirm
 {
@@ -162,7 +214,7 @@ 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">
+</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)
     @Core
     public static void 
addAppModules(OrderedConfiguration&lt;StackExtension&gt; configuration) {


Reply via email to