Scratch pad for changes destined for the 5.4 release notes page.
A new DeprecationWarning service exists to write runtime warnings about deprecated component parameters.
There have been sweeping changes to the client-side support in JavaScript, including the long-awaited abstraction layer. Tapestry is moving to the use of asynchronously-loaded modules, using the RequireJS library. Virtually all of Tapestry's existing JavaScript libraries are being recoded as JavaScript modules; in 5.5, the remaining JavaScript libraries will be removed.
The abstraction layer, the t5/core/dom
module, is a set of wrappers that encapsulate most of the differences between Prototype and jQuery. By coding to the abstraction layer, it will be possible to swap out Prototype support for jQuery. Prototype will no longer be bundled with Tapestry starting in Tapestry 5.5. Ultimately it will be possible to efficiently support other foundation frameworks, such as MooTools or ExtJS, by providing your own implementation of the abstraction layer.
Prior releases of Tapestry would require several separate constructs to initialize client-side behavior:
Although this was well-structured, it had numerous pain points for developers, as well as some client-side performance issues. For example, it means that components that occur many times on the page will include many similar event handler functions.
Tapestry 5.4 represents a shift to a more modern, lighter approach. Behavior of components is encoded into data-
attributes on the element, and logic shifts to a module that provides top-level event handlers on the document object. This is an overall win: it reduces the number of event handlers, solves some timing issues related to running initialization functions, deals with DOM updates better, and is overall more performant.
Tapestry is moving away from “magic class names” to a more uniform approach based on the use of HTML 5 compliant data-
attributes.
The service proxies created by Tapestry-IoC for services defined on interfaces, not just a concrete class, now have the service implementation class annotations. The same now happens to annotations in service methods too.
The SubModule annotation has been deprecated; the new ImportModule annotation does exactly the same thing, but is more clearly named.
Prior versions of Tapestry created cacheable URLs for Assets that incorporated the application version number. The Assets were served with a far-future expires header: the client browser would not even need to check to see if the asset had changed.
Unfortunately, when any asset changed in a new deployment of the application, the version number of the entire application needed to change, resulting in all assets being downloaded (because the application version number in their URLs changed).
In this release, individual assets are given a URL containing a checksum based on the asset‘s content. When the underlying file is changed, the asset will be served with the new URL, but unchanged assets will not be affected. This means that when redeploying your application, you’ll see far less asset traffic, as most client web browsers will already have most assets (whose contents have not changed) in their local cache.
In prior releases of Tapestry, the response to an asset URL could be compressed (with GZip) if the client supported it, and the file was itself compressable. Compressable assets include CSS files and JavaScript, but not image format files (those have built in compression). The fact that two different versions of the file were available with the same URL could confuse some Content Delivery Networks. In Tapestry 5.4, compressed and uncompressed asset URLs are distinct.
Tapestry 5.4 now re-writes CSS files, expanding any url()
references in them into fully qualify URLs; this is to allow for the checksum embedded into each URL, which breaks relative references.
Tapestry 5.4 introduces a new module, tapestry-webresources, which provides support for compiling CoffeeScript into JavaScript, Less into CSS, and for minimizing CSS and JavaScript. All processing takes place at runtime.
Tapestry now properly handles the case for a base class referencing assets that is subclassed into a different library (or subclasses from a library to the application). As long as the new location, under META-INF/assets
, is used, then Tapestry will locate the base class asset inside the subfolder corresponding the the base class' library. In prior releases, the resolution was against the subclass' library, which would fail.
It is now possible to control, for each JavaScript Stack, how that stack treats its JavaScript libraries. The default is to aggregate the libraries and minimize them, but there are now options to aggregate them without minimizing, or to leave them as individual files (neither aggregating, nor minimizing).
A new service, ClasspathAssetProtectionRule
, which receives contributions of ClasspathAssetProtectionRule
instances, was created to you can easily add rules to block requests to classpath assets according to your security needs.
Three rules are added out-of-the-box and may be overriden:
ClassFile
: blocks access to assets with .class
endings (case insensitive).PropertiesFile
: blocks access to assets with .properties
endings (case insensitive).XMLFile
: blocks access to assets with .xml
endings (case insensitive).This new mixin for Field components adds the outer <div class="form-group">
and <label>
elements for a Field to layout correctly inside a Twitter Bootstrap form.
This new component renders a <span>
tag for a Bootstrap 3 Glyphicon.
A component that can be added to your application-specific Layout to provide some useful support when in development mode (but disabled in production mode):
The T5 Dashboard is a new page the consolidates Tapestry 5.3's PageCatalog and ServiceStatus pages. The page is itself extensible, allowing libraries or applications to add their own tabs.
The tapestry-test module contains base classes used when writing TestNG, Selenium, and EasyMock tests. It has been deprecated; users are directed to the Spock Framework (as a replacement for TestNG and EasyMock), and to Geb (which is a vastly improved wrapper around Selenium, and works nicely with Spock).
The useful RandomDataSource class has been extracted into a new module, tapestry-test-data.
The code for launching an instance of Jetty or Tomcat has been extracted to a new module, tapestry-runner.
The Select component has a new “secure” parameter which can be “always”, “never” or “auto”. When “always”, the submitted value must be listed somewhere in the SelectModel. When “never”, this check is not performed. When “auto” (the default), the check is performed only if the SelectModel exists (is non-null) at the time of the submission.
Now this annotation supports arrays: void onEvent(@RequestParameter("values") Integer[] values)
. Same conversion rules used to single values apply to arrays too.
The new PartialTemplateRenderer
service provides easy rendering to a string of blocks, component instances or any other object which implements RenderCommand
or coerced to it.
The Alert
class and the Alerts
component now support rendering raw HTML instead of just plain text.
It is now possible to pre-load pages at system startup time by making contributions to the new PagePreloader service. Pages can be pre-loaded only in development, only in production, never, or always.
As of version 5.4, Tapestry requires Java 1.6 at least.
Applications that perform server-side validation of form control data (such as TextField) as part of an Ajax Zone update should bind the Zone's simpleIds parameter to true. This disables the injection of a per-request unique id into allocated client-side ids and client-side control names.
Non-Ajax requests are not affected. Client-side validation is not affected. Only the rare case where validation only occurs on the server is affected; Tapestry has lost the ability to coordinate the Tapestry-generated id for the field (this is related to big improvements in rendering described below).
Tapestry now assumes that all text/* assets use the utf-8 character set. This is generally the case for JavaScript files (the primary text asset).
Previous versions of Tapestry included dependencies on both SLF4J (Simple Logging Facade for Java) and Log4J (the most common logging library), as well as the bridge between the two. Users who did not wish to use Log4J had to muck about with dependencies in their Maven or Gradle build file.
Tapestry 5.4 only has dependencies on SL4FJ and not on any particular logging implementation; SLF4J will write only a warning message that it needs to be configured. Application developers must provide additional dependencies (hint: use Logback!).
The tapestry-yuicompressor module has been removed and superseded by tapestry-webresources.
With tapestry-webresources in place, you can write your client-side code in CoffeeScript (with the “.coffee” file extension) and Tapestry will take care of converting it, at runtime, to JavaScript.
This support is separate and optional, as it is adds several large dependencies.
By default, tapestry-webresources enables:
The RenderSupport interface, which was deprecated in Tapestry 5.2, has been removed entirely.
The FormFragment component‘s visibleBound parameter is no longer supported; it was used to make a decision about how far up the DOM above the FormFragment’s client-side element should be searched when determining visibility. This may resurface in the future as a CSS expression, but is currently not supported.
The default exception report page has been improved dramatically:
It is now possible to use “page” as a suffix on a page name. The “page” suffix is stripped off of the logical page name; thus for AccountsPage.java, the logical page name will be “Accounts”, and this name (in lower case) will be used inside generated URLs. However, “AccountsPage” will also be recognized in URLs or in code. The component template should always be named after the Java class itself, here “AccountsPage.tml”.
This name stripping, combined with stripping out package names as prefixes and suffixes, can be somewhat hard to reason about. Tapestry has always logged a listing of all these aliases at startup; in rare cases, you may see conflicts or undesirable page names, and you should rename your classes to suit.
A new service, ExceptionReporter
, will now create a text file on the file system for each runtime request processing exception.
The definition of the symbol ‘tapestry.asset-path-prefix’ has changed; it no longer includes the leading and trailing slashes. The default in 5.3 was “/assets/”, in 5.4 it is simply “asset”.
A second symbol, “tapestry.compressed-asset-path-prefix” has been added; this is used when assets are to be compressed. It defaults to “${tapestry.asset-path-prefix}.gz”. You should generally see “/asset” URLs for image files, and “/asset.gz” URLs for CSS and JavaScript.
JavaScript Libraries (including stacks) are being replaced with modules. Note that libraries are now loaded with RequireJS, which may mean that global values exported by the libraries are not visible; you should explicitly attach properties to the global JavaScript window object, rather than assume that the context (the value of this
) is the window.
Only a limited number of properties exported in the T5
and Tapestry
namespaces (on the client) still exist; enough to continue to support the T5.initializers
approach to page initialization that was used in Tapestry 5.3 and earlier. These will be eliminated entirely in Tapestry 5.5.
The interface org.apache.tapestry5.services.assets.ResourceTransformer has had a new method added: getTransformedContentType(). This makes it possible to determine which file extensions map to which content types (for example, a ResourceTransformer for CoffeeScript files, with extension “coffee”, would map to “text/javascript”).
There have been some subtle changes to how rendering of page content (in both traditional and Ajax requests) occurs; such rendering now occurs deferred to a later stage of request processing, rather than immediately after a component event handler method returns a value.
Related to the rendering changes, the cloak()
and decloak()
methods of the Environment service are deprecated and should not be invoked: they now throw an UnsupportedOperationException.
Older versions of Tapestry included client-side support for an element with the CSS class “t-zone-update” as the actual element to be updated when new content is provided for the zone in a partial page render response. This feature has been removed with no replacement.
Tapestry code no longer makes use of Scriptaculous. Instead, Tapestry will fire events on elements, and user code may decide to animate them using whatever library is desired. The event names are defined in the t5/core/events
module.
On the client side, the “floating console” is now only used in cases where a native console is not available. The console should not be used to present information to ordinary users (Bootstrap provides Alerts for that purpose), but is only intended for use in development.
The floating console has also been extended with an improved UI and the ability to filter the content shown.
In development and testing it can be desirable to have the floating console always visible; in that case, add the attribute data-floating-console="enabled"
to the <body>
element. However, the floating console can sometimes obscure page content and interfere with tests; data-floating-console="invisible"
will enable the console, but keep it hidden; the messages written to the console will be visible in the page source.
Prior releases of Tapestry mapped “true” and “false” values for Form.clientValidation to BLUR and NONE. This mapping was introduced in Tapestry 5.2, and has now been removed.
Support for validating fields on blur (i.e., when tabbing out of a field) has been removed. Validation now occurs when the form is submitted, or not at all. The ClientValidation.BLUR enum value has been deprecated and is now treated identically to SUBMIT.
Tapestry now adds a “page loading mask” to the page; this mask will dim the browser window and add a spinning “wait cursor” until all JavaScript on the page has been loaded and initialized. The mask prevents all interaction with the page.
CSS animations are used to fade in the mask after a short period of time; this makes the mask less obtrusive.
Tapestry 5.3 contained client-side code that attempted to prevent Ajax requests until after the page had loaded; this was based on the function Tapestry.waitForPage()
. Server components no longer make use of this function, and the function itself now does nothing.
However, once initial page initialization has occurred, the attribute data-page-initialized
on the root HTML element is set to “true”. In many cases, automated tests should be updated to wait for this attribute to be set after loading a new page.
Tapestry now includes a default copy of Bootstrap 3.3.5, in addition to its own default set of CSS rules. The Tapestry CSS from prior releases has been largely eliminated; instead components now refer to standard Bootstrap CSS classes.
Tapestry now automatically imports the “core” stack for all pages (in previously releases, the “core” stack was only imported if the page made use of JavaScript). Because of this, the Bootstrap CSS will always be available.
ValidationDecorator and ValidationDecoratorFactory are deprecated in 5.4 and will be removed in 5.5. The default implementation of ValidationDecorator now does nothing. All the logic related to presentation of errors has moved to the client, and expects and leverages the Bootstrap CSS.
Fields that require validation messages to be displayed fire events, and the default handlers show and update help blocks that appear (by default) beneath the fields. To get the full effect, you should enclose your fields inside .form-group elements, as described in the Bootstrap documentation: http://getbootstrap.com/css/#forms
You may also use the new FormGroup mixin for most fields.
Bootstrap‘s JavaScript has been broken into multiple “shimmed” JavaScript modules; e.g., “bootstrap/modal” to enable the JavaScript to support Bootstrap’s modal dialogs. These modules do not export any value, but they do establish dependencies: to Bootstrap's “transition” module to enable animations, and ultimately to “jquery”.
Bootstrap is added to the core JavaScriptStack. Applications can override the tapestry.bootstrap-root symbol, or the StackElement entries contributed to the core JavaScript stack to use an application-customized version of Bootstrap.
Certain built-in Tapestry pages (the T5Dashboard, the default ExceptionReport page) are set up to ignore any changes to the core stack CSS, and use the default copy of Bootstrap (otherwise, the CSS changes can corrupt the layout of these pages).
TextField, PasswordField, TextArea, and Select now render the CSS class attribute form-control
; you may add additional CSS class names with the class
informal parameter. Generally, you will want to add an enclosing element with col-md-x
CSS class control the size of the element (otherwise it will stretch to 100% of the available width).
The Label component now renders the CSS class attribute as “control-label”; you may add additional CSS class names with the class
informal parameter.
When Tapestry must present a validation exception, it will often dynamically create the p.help-block
needed to display the message; it does a reasonable job of positioning the new element just after the field, or just after the .input-group
containing the field. The Error component can be used to explicitly place this element.
Also, note that part of the styling of the element is predicated on containment inside a .form-group
(which may have the has-error
selector added or removed).
This validator now always writes the pattern
and title
attributes into the element, even when the Form is configured to disable client side validation. On modern browsers, the pattern will be enforced, and the title will be displayed in a browser-supplied popup window.
The property edit blocks contributed to the BeanBlockSource service should expect to be nested inside a div.form-group, which is provided around the editor for each property.
This service, primarily used by built-in components in Tapestry 5.3, is no longer useful in 5.4. The service still exists, but the methods do nothing, and the service and interface will be removed in 5.5.
New methods have been added to allow JavaScript modules to be “required” into the page; it is possible to invoke the exported function of a module with JSON-compatible parameters; a module may also export multiple names functions that can be invoked.
The selected property is now type Collection
, not specifically type List
. It is no longer allowed to be null. You may need to provide a “prepare” event handler to initialize the property before it is read by the Palette component.
The Autocomplete mixin has been rewritten to use Twitter typeahead.js (0.10.5); this implies it will also force jQuery onto the page, to support the typeahead.js library. In addition, typeahead.js does not support multiple tokens, so this behavior (available in prior releases) has been removed.
The timing of this mixin has changed, it now has the @MixinAfter annotation, so it triggers its events after the component to which it is attached has executed its @BeginRender phase, and before the component executes its @AfterRender phase.
The method setNonPeristentLocaleFromLocaleName() was renamed to setNonPersistentLocaleFromLocaleName() to correct the typo (the missing ‘s’).
The OperationTracker interface has had a new method added, for performing an IO Operation (that may throw IOException).
The FormSupport interface has a new method, storeCancel(), which stores a component action that is only executed if the containing form is canceled.
Tapestry now uses a lock on access to the HttpSession; a shared read lock is acquired when reading session attribute names; an exclusive write lock is acquired when reading or writing session attributes. Locks, once acquired, are kept until the end of the request. A new configuration symbol can be used to turn this feature off, reverting to Tapestry 5.3 behavior.
The interface for AssetPathConstructor was changed incompatibly, to allow for individual asset checksums.
The enum type LinkSecurity was an internal class in 5.3 despite being used in methods of the public Link interface. It has been moved to package org.apache.tapestry5; this represents a minor incompatible change to the Link interface (which is rarely, if ever, implemented outside of the framework).
StreamableResource has been modified, adding a new getChecksum()
method; this interface is rarely, if ever, used or implemented by application code.
MutableComponentModel has been modified, adding a new `doHandleActivationEventContext()' method to help check activation context exactness; this interface is rarely, if ever, used or implemented by application code.
Traditionally, Tapestry IoC Module classes have lived in the same package as the service interfaces they define, and at the same time reference implementation classes in a separate (usually internal) package. This is not a desirable approach, as proper practices is to avoid cases where separate packages import classes from each other.
To resolve this, new modules
packages have been created, and module classes have been moved there. Since module classes are typically not used directly by end-user code, this is not expected to be a disruptive change.
Several constants defined in org.apache.tapestry5.test.TapestryTestConstants have moved to a new class, org.apache.tapestry5.test.TapestryRunnerConstants in the new tapestry-test-constants module. tapestry-core has a dependency on module tapestry-test-constants that is only needed when making use of the PageTester facility. When using PageTester, you will need to make tapestry-test-constants a testRuntime dependency.
The constructor for AbstractValidator has changed to include an instance of JavaScriptSupport.
Where Tapestry-specific CSS still exists (in support of the Palette component and the Tree component), the “t-” prefix has been removed. This may affect applications that overrode the Tapestry CSS rules to adapt Tapestry to the application look and feel.
The Grid component no longer emits CSS class names, instead it renders data attributes into Grid headers, rows, and cells, such as data-grid-row="first"
, data-grid-property="title"
, etc. These attributes may still be referenced using CSS rules where desired.
The automatic ValueEncoder from String to any Number type, or to Boolean have changed slightly. An empty input string is encoded to a null rather than being passed through the type coercer. This reflects the desire that a submitted value (in a URL or a form) that is blank is the same as no value: null.
Tapestry now determines if a client-persistent field is mutable and contains changes, using the same checks as for session-persistent objects (the OptimizedSessionPersistedObject interface and so forth). Previously, Tapestry would load a mutable object into a field, but a change to the internal state of that mutable field would not always be preserved in the serialized object data attached to links.
The ContentType objects, used to represent a content types such as “text/html” in a structured manner, has been revised significantly in 5.4; it is now an immutable data type. In addition, a few scattered interfaces that used a String content type have been changed to use the ContentType class instead.
The FormInjector component was removed; it was intended for use only inside the AjaxFormLoop component (which was rewritten in 5.4 and no longer uses FormInjector). FormInjector was not widely used elsewhere, if it was used at all.