Modified: websites/production/tapestry/content/ioc.html
==============================================================================
--- websites/production/tapestry/content/ioc.html (original)
+++ websites/production/tapestry/content/ioc.html Wed Sep 20 12:29:16 2017
@@ -36,26 +36,13 @@
 
   <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>
 
@@ -67,7 +54,31 @@
       </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><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 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>
 
       <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 Wed Sep 20 
12:29:16 2017
@@ -27,6 +27,16 @@
       </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"/>
 
@@ -67,7 +77,7 @@
       </div>
 
       <div id="content">
-                <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 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>
 
       <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 Wed Sep 20 
12:29:16 2017
@@ -27,6 +27,15 @@
       </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"/>
 
@@ -36,26 +45,13 @@
 
   <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>
 
@@ -67,19 +63,72 @@
       </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><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) {
+                <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 = ...
   }
   document.getElementById("modalContainer") ...
 }
-$("#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() {
+$("#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() {
   var helpModal = null;
 
   function onClickHelp(event) { ... }
 
   $("#helpButton").click(onClickHelp);
-})();</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() {
+})();</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() {
   define(["jquery", "./events", "./dom", "bootstrap/modal"], function($, 
events, dom) {
     var runDialog;
     runDialog = function(options) {
@@ -95,11 +144,15 @@ $("#helpButton").click(onClickHelp);</pl
       runDialog: runDialog
     };
   });
-}).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")
+}).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")
 public class Confirm
 {
   ...
-}</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
+}</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
   JavaScriptSupport javaScriptSupport;
 
   ...
@@ -108,12 +161,15 @@ public class Confirm
 
   ...
 
-  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)
+  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)
     @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"));
-    }</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>
+    }</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>
       </div>
 
       <div class="clearer"></div>


Reply via email to