Modified:
websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
==============================================================================
--- websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
(original)
+++ websites/production/tapestry/content/tapestry-inversion-of-control-faq.html
Mon Feb 19 19:21:08 2018
@@ -77,7 +77,14 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><h2
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h2><p>Main article: <a
href="tapestry-inversion-of-control-faq.html">Tapestry
IoC</a></p><p> </p><div class="aui-label" style="float:right"
title="Related Articles">
+ <div id="ConfluenceContent"><h1
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h1><p>Main article: <a
href="tapestry-inversion-of-control-faq.html">Tapestry IoC</a></p><h2
id="TapestryInversionofControlFAQ-Contents">Contents</h2><p><style
type="text/css">/*<![CDATA[*/
+div.rbtoc1519068035758 {padding: 0px;}
+div.rbtoc1519068035758 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1519068035758 li {margin-left: 0px;padding-left: 0px;}
+
+/*]]>*/</style></p><div class="toc-macro rbtoc1519068035758">
+<ul class="toc-indentation"><li><a
href="#TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</a></li><li><a
href="#TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</a></li><li><a
href="#TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</a></li></ul>
+</div><p> </p><div class="aui-label" style="float:right" title="Related
Articles">
@@ -128,7 +135,7 @@
</div>
-<h3
id="TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</h3><p>First of all: you can do exactly this, but you lose some
of the functionality that Tapestry's IoC container provides.</p><p>The reason
for the split is so that Tapestry can provide functionality for your service
around the core service implementation. It does this by creating
<em>proxies</em>: Java classes that implement the service interface. The
methods of the proxy will ultimately invoke the methods of your service
implementation.</p><p>One of the primary purposes for proxies is to encapsulate
the service's life cycle: most services are singletons that are created
<em>just in time</em>. Just in time means only as soon as you invoke a method.
What's going on is that the life cycle proxy (the object that gets injected
into pages, components or other service implementation
s) checks on each method invocation to see if the actual service exists yet.
If not, it instantiates and configures it (using proper locking to ensure
thread safety), then delegates the method invocation to the service.</p><p>If
you bind a service class (not a service interface and class), then the service
is fully instantiated the first time it is injected, rather than at that first
method invocation. Further, you can't use decorations or method advice on such
a service.</p><p>The final reason for the service interface / implementation
split is to nudge you towards always coding to an interface, which has manifest
benefits for code structure, robustness, and testability.</p><h3
id="TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</h3><p>This same concern applies to any long-lived
resource (a thread, a database connec
tion, a JMS queue connection) that a service may hold onto. Your code needs to
know when the application has been undeployed and shutdown. This is actually
quite easy, by adding some post-injection logic to your implementation
class.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
+<h3
id="TapestryInversionofControlFAQ-WhydoIneedtodefineaninterfaceformyservices?Whycan'tIjustusetheclassitself?">Why
do I need to define an interface for my services? Why can't I just use the
class itself?</h3><p>First of all: you can do exactly this, but you lose some
of the functionality that Tapestry's IoC container provides.</p><p>The reason
for the split is so that Tapestry can provide functionality for your service
around the core service implementation. It does this by creating
<em>proxies</em>: Java classes that implement the service interface. The
methods of the proxy will ultimately invoke the methods of your service
implementation.</p><p>One of the primary purposes for proxies is to encapsulate
the service's life cycle: most services are singletons that are created
<em>just in time</em>. Just in time means only as soon as you invoke a method.
What's going on is that the life cycle proxy (the object that gets injected
into pages, components or other service implementation
s) checks on each method invocation to see if the actual service exists yet.
If not, it instantiates and configures it (using proper locking to ensure
thread safety), then delegates the method invocation to the service.</p><p>If
you bind a service class (not a service interface and class), then the service
is fully instantiated the first time it is injected, rather than at that first
method invocation. Further, you can't use decorations or method advice on such
a service.</p><p>The final reason for the service interface / implementation
split is to nudge you towards always coding to an interface, which has manifest
benefits for code structure, robustness, and testability.</p><h3
id="TapestryInversionofControlFAQ-Myservicestartsathread;howdoIknowwhentheapplicationisshuttingdown,tostopthatthread?">My
service starts a thread; how do I know when the application is shutting down,
to stop that thread?</h3><p>This same concern applies to any long-lived
resource (a thread, a database connec
tion, a JMS queue connection) that a service may hold onto. Your code needs to
know when the application has been undeployed and shutdown. This is actually
quite easy, by adding some post-injection logic to your implementation
class.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>MyServiceImpl.java</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: true; theme: Default"
style="font-size:12px;">public class MyServiceImpl implements MyService
{
private boolean shuttingDown;
@@ -157,7 +164,7 @@
}
}
</pre>
-</div></div><p>After Tapestry invokes the constructor of the service
implementation, and after it performs any field injections, it invokes post
injection methods. The methods must be public and return void. Parameters to a
post injection method represent further injections ... in the above example,
the RegistryShutdownHub is injected into the PostInjection method, since it is
only used inside that one method.</p><div class="confluence-information-macro
confluence-information-macro-warning"><span class="aui-icon aui-icon-small
aui-iconfont-error confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>It is <strong>not</strong>
recommended that MyServiceImpl take RegistryShutdownHub as a constructor
parameter and register itself as a listener inside the constructor. Doing so is
an example of <a class="external-link"
href="http://www.ibm.com/developerworks/java/library/j-jtp0618.html"
rel="nofollow">unsafe publishing</a>, a remote but potential thr
ead safety issue.</p></div></div><p>This same technique will work for any kind
of resource that must be cleaned up or destroyed when the registry shuts
down.</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>Be careful not to invoke methods
on any service proxy objects as they will also be shutting down with the
Registry. A RegistryShutdownListener should not be reliant on anything outside
of itself.</p></div></div><h3
id="TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</h3><p>Tapestry services are designed to be <em>lazy</em>; they are
only fully realized when needed: when the first method on the service interface
is invoked.</p><p>Sometimes a service does extra work
that is desirable at application startup: examples may be registering message
handlers with a JMS implementation, or setting up indexing. Since the service's
constructor (or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/PostInjection.html">@PostInjection</a>
methods) are not invoked until the service is realized.</p><p>The solution is
the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/EagerLoad.html">@EagerLoad</a>
annotation; service implementation classes marked with this annotation are
loaded when the Registry is first startup, rather than lazily.</p></div>
+</div></div><p>After Tapestry invokes the constructor of the service
implementation, and after it performs any field injections, it invokes post
injection methods. The methods must be public and return void. Parameters to a
post injection method represent further injections ... in the above example,
the RegistryShutdownHub is injected into the PostInjection method, since it is
only used inside that one method.</p><div class="confluence-information-macro
confluence-information-macro-warning"><span class="aui-icon aui-icon-small
aui-iconfont-error confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>It is <strong>not</strong>
recommended that MyServiceImpl take RegistryShutdownHub as a constructor
parameter and register itself as a listener inside the constructor. Doing so is
an example of <a class="external-link"
href="http://www.ibm.com/developerworks/java/library/j-jtp0618.html"
rel="nofollow">unsafe publishing</a>, an unlikely but potential
thread safety issue.</p></div></div><p>This same technique will work for any
kind of resource that must be cleaned up or destroyed when the registry shuts
down.</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>Be careful not to invoke methods
on any service proxy objects as they will also be shutting down with the
Registry. A RegistryShutdownListener should not be reliant on anything outside
of itself.</p></div></div><h3
id="TapestryInversionofControlFAQ-HowdoImakemyservicestartupwiththerestoftheapplication,ratherthanlazily?">How
do I make my service startup with the rest of the application, rather than
lazily?</h3><p>Tapestry services are designed to be <em>lazy</em>; they are
only fully realized when needed: when the first method on the service interface
is invoked.</p><p>Sometimes a service does extra w
ork that is desirable at application startup: examples may be registering
message handlers with a JMS implementation, or setting up indexing. Since the
service's constructor (or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/PostInjection.html">@PostInjection</a>
methods) are not invoked until the service is realized.</p><p>The solution is
the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/EagerLoad.html">@EagerLoad</a>
annotation; service implementation classes marked with this annotation are
loaded when the Registry is first startup, rather than lazily.</p></div>
</div>
<div class="clearer"></div>