Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

One of the best features of Tapestry 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're using Tapestry IoC). Starting in version 5.8.3, you enable multiple classloader mode, which allows smarter page class invalidation.

Alert
titleThrowing away all cached pages
typeWarning

Since Tapestry 5.8.3, Tapestry can be run in multiple classloaders mode. When it's on, only the affected cached page instances are discarded and rebuilt instead of all of them. 


Contents

Table of Contents
excludeContents|Related Articles|Live Class and Template Reloading
printablefalse

...

On a change to any 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.

Persistent field data on the pages will usually not be affected (as it is stored separately, usually in the session). This allows you to make fairly significant changes to a component class even while the application continues to run.

...

  • Be sure your project source files (your workspace in Eclipse, for example), are on a local drive, NOT a network location. Network drives are always slower, and the file system scanning needed for LCR can add a noticable lag if I/O is slow. If you use Maven, be sure to put your local repository (e.g. ~/.m2/repository) on a local drive for similar reasons.
  • Java 7 and below: Since LCR adds classes to your PermGen space, you may be running low on PermGen memory (and may eventually get a "java.lang.OutOfMemoryError: PermGen space" error). Try increasing PermGen size with a JVM argument of something like -XX:MaxPermSize=400m. (PermGen settings are not relevant for Java 8 and above.)

Scrollbar

[5.8.3+] Multiple Classloader Mode/Smarter Page Class Invalidation

Since Tapestry 5.8.3, you can run Tapestry in multiple classloader mode, which implements smarter page class invalidation in live class reloading. In addition, other caches are also invalidated in smarter way when something changes, avoiding throwing away everything. Multiple classloader mode isn't available when production mode is on.

To enable multiple classloader mode, you need to tapestry.multiple-classloaders symbol to true and run the webapp with production mode disabled.

When multiple classloaders are enabled, when a class in a controlled component, template, message properties file or asset is changed, Tapestry tries to invalidate as few cached objects as possible. This include page instances, processed templates, asset information, property bindings, etc. This is possible by 2 new internal features:

  1. A component dependency registry, which gathers and stores information about how component, page, mixin and base classes depend on each other. There are 3 kinds of dependencies: usage (i.e. a component or mixin used in a class), superclass (i.e. one class extending the other) and @InjectPage (i.e. one class injecting a page class using @InjectPage.
  2. The usage of multiple classloader instances, organized in a tree, instead of a single one. For example: if a component A is used in pages B and C, when B has its class changed, there's no need to invalidate a cached instance of C since Tapestry knows there's no dependency of B and C. On the other hand, if A is changed, both B and C instances need to be invalidated.

You can find a graph of all known dependencies at a time by going to the /t5dashboard/pagedependencygraph URL of your webapp. You can view the dependencies for one specific page by going to /t5dashboard/ and clicking the page's Structure Info link. Here's one partial example:

Image Added

Loading, Storing and Preloading Dependency Information

When starting up, Tapestry checks whether a file named tapestryComponentDependencies.json exists in the folder where the webapp is running. If it does, component dependency is loaded from it.

The T5Dashboard page has 2 new buttons related to dependencies, Store dependency information, writes all the dependency information as known at that moment.

Preload dependency information and page classloader contexts goes through all known pages, gathers its dependencies, also doing the same for all the components used directly and indirectly by them, and the preloads page the page classloader contexts, thus avoiding context invalidations when page instances are created. Notice this process won't work if any of the pages or their templates are invalid for any reason.

Caveats

Unfortunately, it wasn't possible to make the multiple classloader mode to work with all situations and code. Some known issues:

  1. On Java 9 and later, classes belonging to one classloader cannot call package-private methods of other classes even when both are in the same package. The solution is to change the method visibility to public.
  2. If you don't have component dependency information already loaded for a given class, problems, usually in the form of a ClassCastException claiming an object of a given type cannot be assigned to a variable of the same type. The best way to deal with this is to use the T5Dashboard to write the component dependency information to a file and restart the webapp. In some cases, it helps to preload dependency information for all classes.
  3. If you start your webapp without component dependency information, page instances may be created and invalidated a few times even when they didn't have any changes due to the page classloader context creation. The solution for this is the same one as the above.