tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Class Reloading
Date Mon, 16 Jan 2012 13:01:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/12/_/styles/combined.css?spaceKey=TAPESTRY&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Class+Reloading">Class
Reloading</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~bobharner">Bob
Harner</a>
    </h4>
        <div id="versionComment">
        <b>Comment:</b>
        Added link to Service Implementation Reloading page, added related links section<br
/>
    </div>
        <br/>
                         <h4>Changes (6)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-unchanged" >h1. Live Class and Template Reloading
<br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{float:right|background=#eee}
<br>{contentbylabel:title=Related Articles|showLabels=false|showSpace=false|space=@self|labels=class-reloading}
<br>{float} <br> <br></td></tr>
            <tr><td class="diff-unchanged" >One of the great features of Tapestry
5 is automatic reloading of changed classes and templates. _Page and component_ classes will
automatically reload when changed. Likewise, changes to component templates and other related
resources will also be picked up immediately.  In addition, starting in version 5.2, your
service classes will also be reloaded automatically after changes (if you&#39;re using
[Tapestry IoC|IoC]). <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >[Persistent field data|Persistent
Page Data] on the pages will usually not be affected (as it is stored separately, in the session).
This allows you to make fairly significant changes to a component class even while the application
continues to run. <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h1.
Page and Component Packages <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h1.
Packages Scanned <br></td></tr>
            <tr><td class="diff-unchanged" > <br>Only certain classes are
subject to reload. Reloading is based on package name; the packages that are reloaded are
derived from the [application configuration|Configuration]. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >* org.example.myapp.mixins <br>*
org.example.myapp.base <br></td></tr>
            <tr><td class="diff-changed-lines" >* org.example.myapp.services (Tapestry
5.2 and <span class="diff-changed-words">later<span class="diff-added-chars"style="background-color:
#dfd;">, with restrictions</span>)</span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{since:since=5.2} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Since
Tapestry 5.2, service implementation classes are also reloaded automatically after changes.
There are some limitations to this (see below). <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Starting
in Tapestry 5.2, live class reloading includes service implementation classes. There are some
limitations to this. See [Service Implementation Reloading] for more details. <br></td></tr>
            <tr><td class="diff-unchanged" >{since} <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="ClassReloading-LiveClassandTemplateReloading"></a>Live
Class and Template Reloading</h1>

<div class='navmenu' style='float:right; background:#eee; margin:3px; padding:3px'><table
class="tableview" width="100%">
            <tr><th style="padding: 3px 3px 3px 0px">Related Articles</th></tr>
                        <tr>
            <td>
                                 <span class="icon icon-page" title=Page>Page:</span>
                         <a href="/confluence/display/TAPESTRY/Service+Implementation+Reloading">Service
Implementation Reloading</a>
        
                                            </td>
        </tr>
            </table>
</div>

<p>One of the great features of Tapestry 5 is automatic reloading of changed classes
and templates. <em>Page and component</em> classes will automatically reload when
changed. Likewise, changes to component templates and other related resources will also be
picked up immediately.  In addition, starting in version 5.2, your service classes will also
be reloaded automatically after changes (if you're using <a href="/confluence/display/TAPESTRY/IoC"
title="IoC">Tapestry IoC</a>).</p>

<h2><a name="ClassReloading-TemplateReloading"></a>Template Reloading</h2>

<p>When a template changes, all page instances (as well as the hierarchy of components
below them) are discarded and reconstructed with the new template. However, classes are not
reloaded in this case.</p>

<h2><a name="ClassReloading-ClassReloading"></a>Class Reloading</h2>

<p>On a change to <em>any</em> loaded class from inside a controlled package
(or any sub-package of a controlled package), Tapestry will discard all page instances, and
discard the class loader.</p>

<p><a href="/confluence/display/TAPESTRY/Persistent+Page+Data" title="Persistent
Page Data">Persistent field data</a> on the pages will usually not be affected (as
it is stored separately, in the session). This allows you to make fairly significant changes
to a component class even while the application continues to run.</p>

<h1><a name="ClassReloading-PackagesScanned"></a>Packages Scanned</h1>

<p>Only certain classes are subject to reload. Reloading is based on package name; the
packages that are reloaded are derived from the <a href="/confluence/display/TAPESTRY/Configuration"
title="Configuration">application configuration</a>.</p>

<p>If your root package is <tt>org.example.myapp</tt>, then only classes
in the following packages will be scanned for automatic reloads:</p>

<ul>
	<li>org.example.myapp.pages</li>
	<li>org.example.myapp.components</li>
	<li>org.example.myapp.mixins</li>
	<li>org.example.myapp.base</li>
	<li>org.example.myapp.services (Tapestry 5.2 and later, with restrictions)</li>
</ul>




<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Added in
5.2</b><br /></td></tr></table></div>
<div style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;">
<p>Starting in Tapestry 5.2, live class reloading includes service implementation classes.
There are some limitations to this. See <a href="/confluence/display/TAPESTRY/Service+Implementation+Reloading"
title="Service Implementation Reloading">Service Implementation Reloading</a> for
more details.</p>
</div>

<h1><a name="ClassReloading-FileSystemOnly"></a>File System Only</h1>

<p>Reloading of classes and other files applies only to files that are actually on the
file system, and not files obtained from JAR files. This is perfect during development, where
the files in question are in your local workspace. In a deployed application, you are somewhat
subject to the implementation of your servlet container or application server.</p>

<h1><a name="ClassReloading-ClassLoaderIssues"></a>Class Loader Issues</h1>

<p>Tapestry uses an extra class loader to load page and component classes.</p>

<p>When a change to an underlying Java class file is detected, Tapestry discards the
class loader and any pooled page instances.</p>

<p>You should be careful to not hold any references to Tapestry pages or components
in other code, such as Tapestry IoC services. Holding such references can cause significant
memory leaks, as they can prevent the class loader from being reclaimed by the garbage collector.</p>

<h1><a name="ClassReloading-ClassCastExceptions"></a>ClassCastExceptions</h1>

<p>Tapestry's class loader architecture can cause minor headaches when you make use
of a services layer, or any time that you pass component instances to objects that are not
themselves components.</p>

<p>In such cases you may see ClassCastException errors. This is because the same class
name, say org.example.myapp.pages.Start, exists as two different class instances. One class
instance is loaded by the web application's default class loader. A second class instance
has been loaded <em>and transformed</em> by Tapestry's reloading class loader.</p>

<p>Ordinary classes, such as Tapestry IoC Services, will be loaded by the default class
loader and expect instances to be loaded by the same class loader (or a parent).</p>

<p>The solution to this problem is to introduce an interface; the component class should
implement the interface, and the service should expect an instance of the interface, rather
than a specific type.</p>

<p>It is important that the interface be loaded by the default class loader.  It should
not be in the pages or components package, but instead be in another package, such as services.</p>

<h1><a name="ClassReloading-HandlingReloadsinyourCode"></a>Handling Reloads
in your Code</h1>

<p>On occasion, you may need to know when invalidations occur, to clear your own cache.
For example, if you have a binding that creates new classes, the way <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PropertyConduitSource.html"
class="external-link" rel="nofollow">PropertyConduitSource</a> does, you need to
discard any cached classes or instances when a change is detected in component classes.</p>

<p>You do this by registering a listener with the correct <a href="http://tapestry.apache.org/current/apidocs/org/apache/tpaestry5/services/InvalidationEventHub.html"
class="external-link" rel="nofollow">InvalidationEventHub</a> service.</p>

<p>For example, your service may be in the business of creating new classes based on
component classes, and keep a cache of those classes:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">

<span class="code-keyword">public</span> class MyServiceImpl <span class="code-keyword">implements</span>
MyService, InvalidationEventListener
{
  <span class="code-keyword">public</span> <span class="code-keyword">final</span>
Map&lt;<span class="code-object">String</span>,<span class="code-object">Class</span>&gt;
cache = <span class="code-keyword">new</span> ConcurrentHashMap&lt;<span
class="code-object">String</span>,<span class="code-object">Class</span>&gt;();

  . . .

  <span class="code-keyword">public</span> void objectWasInvalidated() { cache.clear();
}
}
</pre>
</div></div>

<p>Here, the service implementation implements the InvalidationEventListener interface,
as well as its service interface. The question is: how does it register for notifications?</p>

<p>In your module, you will want to use a service builder method, such as:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> <span class="code-keyword">static</span>
MyService buildMyService(@Autobuild MyServiceImpl service, @ComponentClasses InvalidationEventHub
hub)
{
  hub.addInvalidationListener(service);

  <span class="code-keyword">return</span> service;
}
</pre>
</div></div>

<p>This is the intent of service builder methods; to do more than just injecting dependencies.</p>

<h1><a name="ClassReloading-CheckingForUpdates"></a>Checking For Updates</h1>

<p>The built in InvalidationEventHub services provide notifications of changes to component
classes, to component templates, and to component message catalogs. If you wish to check some
other resources (for example, files in a directory of the file system or rows in a database
table), you should register as an <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListener.html"
class="external-link" rel="nofollow">UpdateListener</a> with the <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListenerHub.html"
class="external-link" rel="nofollow">UpdateListenerHub</a> service.</p>

<p>Periodically (the frequency is configurable), UpdateListeners are notified that they
should check for updates. Typically, UpdateListeners are also InvalidationEventHubs (or provide
InvalidationEventHubs), so that other interested parties can be alerted when underlying data
changes.</p>

    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Class+Reloading">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=21792145&revisedVersion=7&originalVersion=6">View
Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message