tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r971322 - in /websites/production/tapestry/content: cache/main.pageCache tapestry-ioc-overview.html
Date Wed, 04 Nov 2015 12:20:03 GMT
Author: buildbot
Date: Wed Nov  4 12:20:03 2015
New Revision: 971322

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/tapestry-ioc-overview.html

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

Modified: websites/production/tapestry/content/tapestry-ioc-overview.html
==============================================================================
--- websites/production/tapestry/content/tapestry-ioc-overview.html (original)
+++ websites/production/tapestry/content/tapestry-ioc-overview.html Wed Nov  4 12:20:03 2015
@@ -31,8 +31,6 @@
   <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' type='text/css'
/>
   <script src='/resources/highlighter/scripts/shCore.js' type='text/javascript'></script>
   <script src='/resources/highlighter/scripts/shBrushJava.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushXml.js' type='text/javascript'></script>
-  <script src='/resources/highlighter/scripts/shBrushPlain.js' type='text/javascript'></script>
   <script type="text/javascript">
   SyntaxHighlighter.defaults['toolbar'] = false;
   SyntaxHighlighter.all();
@@ -67,8 +65,46 @@
   </div>
 
 <div id="content">
-<div id="ConfluenceContent"><p>Even today, with the overwhelming success of <a
shape="rect" class="external-link" href="http://www.springframework.org" >Spring</a>
and the rise of smaller, simpler approaches to building applications (in contrast to the heavyweight
EJB approach), many people still have trouble wrapping their heads around Inversion of Control.</p><p>Really
understanding IoC is a new step for many developers. If you can remember back to when you
made the transition from procedural programming (in C, or BASIC) to object oriented programming,
you might remember the point where you "got it". The point where it made sense to have methods
on objects, and data inside objects.</p><p>Inversion of Control builds upon those
ideas. The goal is to make code more robust (that is, with fewer errors), more reusable and
much easier to test.</p><p>Prior to IoC approaches, most developers were used
to a more <em>monolithic</em> design, with a few core objects and a <code>main()</code>
m
 ethod somewhere that starts the ball rolling. <code>main()</code> instantiates
the first couple of classes, and those classes end up instantiating and using all the other
classes in the system.</p><p>That's an <em>unmanaged</em> system.
Most desktop applications are unmanaged, so it's a very familiar pattern, and easy to get
your head around.</p><p>By contrast, web applications are a <em>managed</em>
environment. You don't write a main(), you don't control startup. You <em>configure</em>
the Servlet API to tell it about your servlet classes to be instantiated, and their life cycle
is totally controlled by the servlet container.</p><p>Inversion of Control is
just a more general application of this approach. The container is ultimately responsible
for instantiating and configuring the objects you tell it about, and running their entire
life cycle of those objects.</p><p>Web applications are more complicated to write
than monolithic applications, largely because of <em>multithreading</
 em>. Your code will be servicing many different users simultaneously across many different
threads. This tends to complicate the code you write, since some fundamental aspects of object
oriented development get called into question: in particular, the use of <em>internal
state</em> (values stored inside instance variables), since in a multithreaded environment,
that's no longer the safe place it is in traditional development. Shared objects plus internal
state plus multiple threads equals an broken, unpredictable application.</p><p>Frameworks
such as Tapestry &#8211; both the IoC container, and the web framework itself &#8211;
exist to help.</p><p>When thinking in terms of IoC, <strong>small is beautiful</strong>.
What does that mean? It means small classes and small methods are easier to code than large
ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods
a thousand lines long, and no distinction between business logic and view logic. Everyt
 hing mixed together into an untestable jumble.</p><p>At the other extreme is
IoC: small objects, each with a specific purpose, collaborating with other small objects.</p><p>Using
unit tests, in collaboration with tools such as <a shape="rect" class="external-link" href="http://easymock.org/"
>EasyMock</a>, you can have a code base that is easy to maintain, easy to extend,
and easy to test. And by factoring out a lot of <em>plumbing</em> code, your code
base will not only be easier to work with, it will be smaller.</p><h2 id="TapestryIoCOverview-LivingontheFrontier">Living
on the Frontier</h2><p>Coding applications the traditional way is like being a
homesteader on the American frontier in the 1800's. You're responsible for every aspect of
your house: every board, every nail, every stick of furniture is something you personally
created. There <em>is</em> a great comfort in total self reliance. Even if your
house is small, the windows are a bit drafty or the floorboards creak a little
 , you know exactly <em>why</em> things are not-quite perfect.</p><p>Flash
forward to modern cities or modern suburbia and it's a whole different story. Houses are built
to specification from design plans, made from common materials, by many specializing tradespeople.
Construction codes dictate how plumbing, wiring and framing should be performed. A home-owner
may not even know how to drive a nail, but can still take comfort in draft-free windows, solid
floors and working plumbing.</p><p>To extend the metaphor, a house in a town is
not alone and self-reliant the way a frontier house is. The town house is situated on a street,
in a neighborhood, within a town. The town provides services (utilities, police, fire control,
streets and sewers) to houses in a uniform way. Each house just needs to connect up to those
services.</p><h2 id="TapestryIoCOverview-TheWorldoftheContainer">The World of
the Container</h2><p>So the IoC container is the "town" and in the world of the
IoC container, eve
 rything has a name, a place, and a relationship to everything else in the container. Tapestry
calls this world "The Registry".</p><p><span class="confluence-embedded-file-wrapper"><img
class="confluence-embedded-image" src="tapestry-ioc-overview.data/ioc-overview.png"></span></p><p>Here
we're seeing a few services from the built-in Tapestry IoC module, and a few of the services
from the Tapestry web framework module. In fact, there are over 100 services, all interrelated,
in the Registry ... and that's before you add your own to the mix. The IoC Registry treats
all the services uniformly, regardless of whether they are part of Tapestry, or part of your
application, or part of an add-on library.</p><p>Tapestry IoC's job is to make
all of these services available to each other, and to the outside world. The outside world
could be a standalone application, or it could be an application built on top of the Tapestry
web framework.</p><h2 id="TapestryIoCOverview-ServiceLifeCycle">Service 
 Life Cycle</h2><p>Tapestry services are <em>lazy</em>, which means
they are not fully instantiated until they are absolutely needed. Often, what looks like a
service is really a proxy object ... the first time any method of the proxy is invoked, the
actual service is instantiated and initialized (Tapestry uses the term <em>realized</em>
for this process). Of course, this is all absolutely thread-safe.</p><p>Initially
a service is <em>defined</em>, meaning some module has defined the service. Later,
the service will be <em>virtual</em>, meaning a proxy has been created. This occurs
most often because some other service <em>depends</em> on it, but hasn't gotten
around to invoking methods on it. Finally, a service that is ready to use is <em>realized</em>.
What's nice is that your code neither knows nor cares about the life cycle of the service,
because of the magic of the proxy.</p><p>In fact, when a Tapestry web application
starts up, before it services its first request, only about 
 20% of the services have been realized; the remainder are defined or virtual.</p><h2
id="TapestryIoCOverview-Classvs.Service">Class vs. Service</h2><p>A Tapestry
service is more than just a class. First of all, it is a combination of an <em>interface</em>
that defines the operations of the service, and an <em>implementation class</em>
that implements the interface.</p><p>Why this extra division? Having a service
interface is what lets Tapestry create proxies and perform other operations. It's also a very
good practice to code to an interface, rather than a specific implementation. You'll often
be surprised at the kinds of things you can accomplish by substituting one implementation
for another.</p><p>Tapestry is also very aware that a service will have dependencies
on other services. It may also have other needs ... for example, in Tapestry IoC, the container
provides services with access to Loggers.</p><p>Tapestry IoC also has support
for other configuration that may be provided to
  services when they are realized.</p><h2 id="TapestryIoCOverview-DependencyInjection">Dependency
Injection</h2><p>Main Article: <a shape="rect" href="injection.html">Injection</a></p><div
class="navmenu" style="float:right; background:#eee; margin:3px; padding:3px">
-<div class="error"><span class="error">Error formatting macro: contentbylabel:
com.atlassian.confluence.api.service.exceptions.BadRequestException: Could not parse cql :
null</span> </div></div>Inversion of Control refers to the fact that the
container, here Tapestry IoC's Registry, instantiates your classes. It decides on when the
classes get instantiated.<p>Dependency Injection is a key part of <em>realization</em>:
this is how a service is provided with the other services it needs to operate. For example,
a Data Access Object service may be injected with a ConnectionPool service.</p><p>In
Tapestry, injection occurs through constructors, through parameters to service builder methods,
or through direct injection into fields. Tapestry prefers constructor injection, as this emphasizes
that dependencies should be stored in <strong>final</strong> variables. This is
the best approach towards ensuring thread safety.</p><p>In any case, injection
"just happens". Tapestry finds the construc
 tor of your class and analyzes the parameters to determine what to pass in. In some cases,
it uses just the parameter type to find a match, in other cases, annotations on the parameters
may also be used. It also scans through the fields of your service implementation class to
identify which should have injected values written into them.</p><h2 id="TapestryIoCOverview-Whycan'tIjustusenew?">Why
can't I just use <code>new</code>?</h2><p>That's a common question.
All these concepts seem alien at first. What's wrong with <code>new</code>?</p><p>The
problem with new is that it rigidly connects one implementation to another implementation.
Let's follow a progression that reflects how a lot of projects get written. It will show that
in the real world, <code>new</code> is not as simple as it first seems.</p><p>This
example is built around some real-world work that involves a Java Messaging Service queue,
part of an application performance monitoring subsystem for a large application. Code in
 side each server collects performance data of various types and sends it, via a shared JMS
queue, to a central server for collection and reporting.</p><p>This code is for
a metric that periodically counts the number of rows in a key database table. Other implementations
of MetricProducer will be responsible for measuring CPU utilization, available disk space,
number of requests per second, and so forth.</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
+<div id="ConfluenceContent"><p>Even today, with the overwhelming success of <a
shape="rect" class="external-link" href="http://www.springframework.org" >Spring</a>
and the rise of smaller, simpler approaches to building applications (in contrast to the heavyweight
EJB 2.0 approach), many people still have trouble wrapping their heads around Inversion of
Control.</p><p>Really understanding IoC is a new step for many developers. If
you can remember back to when you made the transition from procedural programming (in C, or
BASIC) to object oriented programming, you might remember the point where you "got it". The
point where it made sense to have methods on objects, and data inside objects.</p><p>Inversion
of Control builds upon those ideas. The goal is to make code more robust (that is, with fewer
errors), more reusable and much easier to test.</p><p>Prior to IoC approaches,
most developers were used to a more <em>monolithic</em> design, with a few core
objects and a <code>main()</cod
 e> method somewhere that starts the ball rolling. <code>main()</code> instantiates
the first couple of classes, and those classes end up instantiating and using all the other
classes in the system.</p><p>That's an <em>unmanaged</em> system.
Most desktop applications are unmanaged, so it's a very familiar pattern, and easy to get
your head around.</p><p>By contrast, web applications are a <em>managed</em>
environment. You don't write a main(), you don't control startup. You <em>configure</em>
the Servlet API to tell it about your servlet classes to be instantiated, and their life cycle
is totally controlled by the servlet container.</p><p>Inversion of Control is
just a more general application of this approach. The container is ultimately responsible
for instantiating and configuring the objects you tell it about, and running their entire
life cycle of those objects.</p><p>Web applications are more complicated to write
than monolithic applications, largely because of <em>multithreadi
 ng</em>. Your code will be servicing many different users simultaneously across many
different threads. This tends to complicate the code you write, since some fundamental aspects
of object oriented development get called into question: in particular, the use of <em>internal
state</em> (values stored inside instance variables), since in a multithreaded environment,
that's no longer the safe place it is in traditional development. Shared objects plus internal
state plus multiple threads equals an broken, unpredictable application.</p><p>Frameworks
such as Tapestry &#8211; both the IoC container, and the web framework itself &#8211;
exist to help.</p><p>When thinking in terms of IoC, <strong>small is beautiful</strong>.
What does that mean? It means small classes and small methods are easier to code than large
ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods
a thousand lines long, and no distinction between business logic and view logic. Ev
 erything mixed together into an untestable jumble.</p><p>At the other extreme
is IoC: small objects, each with a specific purpose, collaborating with other small objects.</p><p>Using
unit tests, in collaboration with tools such as <a shape="rect" class="external-link" href="http://easymock.org/"
>EasyMock</a>, you can have a code base that is easy to maintain, easy to extend,
and easy to test. And by factoring out a lot of <em>plumbing</em> code, your code
base will not only be easier to work with, it will be smaller.</p><h2 id="TapestryIoCOverview-LivingontheFrontier">Living
on the Frontier</h2><p>Coding applications the traditional way is like being a
homesteader on the American frontier in the 1800's. You're responsible for every aspect of
your house: every board, every nail, every stick of furniture is something you personally
created. There <em>is</em> a great comfort in total self reliance. Even if your
house is small, the windows are a bit drafty or the floorboards creak a li
 ttle, you know exactly <em>why</em> things are not-quite perfect.</p><p>Flash
forward to modern cities or modern suburbia and it's a whole different story. Houses are built
to specification from design plans, made from common materials, by many specializing tradespeople.
Construction codes dictate how plumbing, wiring and framing should be performed. A home-owner
may not even know how to drive a nail, but can still take comfort in draft-free windows, solid
floors and working plumbing.</p><p>To extend the metaphor, a house in a town is
not alone and self-reliant the way a frontier house is. The town house is situated on a street,
in a neighborhood, within a town. The town provides services (utilities, police, fire control,
streets and sewers) to houses in a uniform way. Each house just needs to connect up to those
services.</p><h2 id="TapestryIoCOverview-TheWorldoftheContainer">The World of
the Container</h2><p>So the IoC container is the "town" and in the world of the
IoC container,
  everything has a name, a place, and a relationship to everything else in the container.
Tapestry calls this world "The Registry".</p><p><span class="confluence-embedded-file-wrapper"><img
class="confluence-embedded-image" src="tapestry-ioc-overview.data/ioc-overview.png"></span></p><p>Here
we're seeing a few services from the built-in Tapestry IoC module, and a few of the services
from the Tapestry web framework module. In fact, there are over 100 services, all interrelated,
in the Registry ... and that's before you add your own to the mix. The IoC Registry treats
all the services uniformly, regardless of whether they are part of Tapestry, or part of your
application, or part of an add-on library.</p><p>Tapestry IoC's job is to make
all of these services available to each other, and to the outside world. The outside world
could be a standalone application, or it could be an application built on top of the Tapestry
web framework.</p><h2 id="TapestryIoCOverview-ServiceLifeCycle">Serv
 ice Life Cycle</h2><p>Tapestry services are <em>lazy</em>, which
means they are not fully instantiated until they are absolutely needed. Often, what looks
like a service is really a proxy object ... the first time any method of the proxy is invoked,
the actual service is instantiated and initialized (Tapestry uses the term <em>realized</em>
for this process). Of course, this is all absolutely thread-safe.</p><p>Initially
a service is <em>defined</em>, meaning some module has defined the service. Later,
the service will be <em>virtual</em>, meaning a proxy has been created. This occurs
most often because some other service <em>depends</em> on it, but hasn't gotten
around to invoking methods on it. Finally, a service that is ready to use is <em>realized</em>.
What's nice is that your code neither knows nor cares about the life cycle of the service,
because of the magic of the proxy.</p><p>In fact, when a Tapestry web application
starts up, before it services its first request, only ab
 out 20% of the services have been realized; the remainder are defined or virtual.</p><h2
id="TapestryIoCOverview-Classvs.Service">Class vs. Service</h2><p>A Tapestry
service is more than just a class. First of all, it is a combination of an <em>interface</em>
that defines the operations of the service, and an <em>implementation class</em>
that implements the interface.</p><p>Why this extra division? Having a service
interface is what lets Tapestry create proxies and perform other operations. It's also a very
good practice to code to an interface, rather than a specific implementation. You'll often
be surprised at the kinds of things you can accomplish by substituting one implementation
for another.</p><p>Tapestry is also very aware that a service will have dependencies
on other services. It may also have other needs ... for example, in Tapestry IoC, the container
provides services with access to Loggers.</p><p>Tapestry IoC also has support
for other configuration that may be provide
 d to services when they are realized.</p><h2 id="TapestryIoCOverview-DependencyInjection">Dependency
Injection</h2><p>Main Article: <a shape="rect" href="injection.html">Injection</a></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 shape="rect" href="injection-in-detail.html">Injection in
Detail</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span>
       </div>
+
+        <div class="details">
+                        <a shape="rect" href="injection-faq.html">Injection 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 shape="rect" href="injection.html">Injection</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div><p>Inversion of Control refers to the fact that the container, here Tapestry
IoC's Registry, instantiates your classes. It decides on when the classes get instantiated.</p><p>Dependency
Injection is a key part of <em>realization</em>: this is how a service is provided
with the other services it needs to operate. For example, a Data Access Object service may
be injected with a ConnectionPool service.</p><p>In Tapestry, injection occurs
through constructors, through parameters to service builder methods, or through direct injection
into fields. Tapestry prefers constructor injection, as this emphasizes that dependencies
should be stored in <strong>final</strong> variables. This is the best approach
towards ensuring thread safety.</p><p>In any case, injection "just happens". Tapestry
finds the constructor of your class and analyzes the parameters to determine what to pass
in. In some cases, it uses just the parameter type to find a match, in other cases, annotations
on the parame
 ters may also be used. It also scans through the fields of your service implementation class
to identify which should have injected values written into them.</p><h2 id="TapestryIoCOverview-Whycan'tIjustusenew?">Why
can't I just use <code>new</code>?</h2><p>That's a common question.
All these concepts seem alien at first. What's wrong with <code>new</code>?</p><p>The
problem with new is that it rigidly connects one implementation to another implementation.
Let's follow a progression that reflects how a lot of projects get written. It will show that
in the real world, <code>new</code> is not as simple as it first seems.</p><p>This
example is built around some real-world work that involves a Java Messaging Service queue,
part of an application performance monitoring subsystem for a large application. Code inside
each server collects performance data of various types and sends it, via a shared JMS queue,
to a central server for collection and reporting.</p><p>This code is for a metric
t
 hat periodically counts the number of rows in a key database table. Other implementations
of MetricProducer will be responsible for measuring CPU utilization, available disk space,
number of requests per second, and so forth.</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public
class TableMetricProducer implements MetricProducer
 {
   . . . 



Mime
View raw message