Don't Do Too Much

The client-tier of the application produces a HTML response for each page request. This CDEJ begins to send this HTML response to the web browser before the full HTML content of the page is complete. The CDEJ invokes a renderer for each field, serializes the DocumentFragment populated by the renderer to a HTML string, and then writes this HTML string to the response before invoking the next renderer. This way, very little of the response is held in memory at any one time and resource usage is minimized. This is particularly important for pages that can contain a lot of content or when the application is under heavy load.

A renderer plug-in class is free to produce any HTML content for a field, but bear in mind that the contents of the DocumentFragment will be held in memory until the render method returns. Only at this time is the fragment serialized and its allocated memory freed. The memory use of widgets that produce a large volume of HTML content may or may not pose a problem. If such a widget is used on many pages and by many concurrent users, asses the potential impact of its high memory use. For widgets that are used rarely or by only a limited number of users, memory use may not be a significant problem.

Using a lot of memory when producing the HTML is not the only resource use issue that can be caused by a renderer plug-in. Renderer plug-ins can also consume a lot of processing resources. Technologies such as Extensible Stylesheet Language Transformations (XSLT) can be employed by renderers to manage the generation of the HTML content. Such processing can require significant processing resources (in addition to memory). Determine if such processing is necessary and plan from the beginning to reduce the impact this may have on the application as a whole.

XSLT processing, for example, is both memory and processor intensive. However, this can be mitigated to some degree by taking care to avoid unnecessary processing. XSLT stylesheets can be loaded from resource on the classpath, but this only needs to be performed once. An instance of a javax.xml.transform.Templates object can maintain a copy of the stylesheet in memory and can be used multiple times in a thread-safe manner to eliminate the overhead of loading the XSLT stylesheet each time it is required.

Not only can single, large processing operations pose a problem, so can an excessive number of smaller operations. A renderer is invoked every time the value of a field is rendered on a page, both in clusters and in lists. Minor inefficiencies in renderers that are used to present field values in clusters may go unnoticed, but the same inefficiencies may pose a serious problem in the context of long lists of data. The same view renderer plug-in is used to present read-only fields values in a cluster or in a list where the type of the data is the same. If one or two values are presented in a cluster, the resource use may be acceptable. However, if hundreds of values are presented in a long list, the resource use will increase dramatically.

Renderers that depend on receiving their data in the form of XML documents are a particular common concern. While XML is suitable and convenient in many cases, it is inadvisable to use it for values that may be presented in lists. For each field in a list column, the CDEJ will create an XML parser, parse the XML document, store the result, allow the renderer to query the result, and then, at the end of the request, free all of the used resources. This may appear to perform adequately in a development environment with a single user, but is unlikely to perform well with concurrent users on a heavily loaded application server. Pagination in its current implementation does not change this. All of the data in a paginated list is still rendered up front, it is just presented as if it were being rendered piecemeal.

To avoid serious resource use issues, a developer may decide to present values used in clusters in one way and values used in lists, another. This is only possible if the values have different domain definitions, as it is not possible to configure renderer plug-ins based on the context (cluster or list) in which they will be used. Using two different domain definitions for the same data can require considerable changes to the application UML model.