Welcome!

Java Authors: Liz McMillan, Walter H. Pinson, III, Maureen O'Gara, Yakov Werde, Tony Bishop

Related Topics: Java

Java: Article

Development of Component-Oriented Web Interfaces

A Case for the Vitrage Framework

HTML renders use content renders to arrange content into a required HTML structure. Vitrage contains a broad selection of HTML renders including CellRender, RowRender, TableRender and SpanRender. FlatRender plays a special role; it's used to insert a static HTML fragment, usually obtained from the resource bundle, into the generated HTML structure. For instance, when an HTML table is generated, the FlatRender can provide a spacer between rows.

Composite renders like Serial-Render and ConditionalRender logically combine other renders.

The SerialRender serves as an ordered container of other renders that invokes them sequentially. The ConditionalRender contains a collection of pairs of objects. Each pair consists of a render object and a condition object that implements the interface ICondition. The ConditionalRender in the build() method iterates over each pair, checking if the condition is true, and for the first of such pairs, invokes a build() method on a corresponding render. Only one render is invoked. If no condition satisfied, the ConditionalRender returns an empty string.

The following code fragment demonstrates assembling standard Vitrage renders into a custom render for the JSP-block that implements the P&C compartment described above.

1 public ARender prepareRender(
2 IBlockData data)
3 {
4 CntRefRender crr =
5 new CntRefRender(BASE_ALIGN);
6 crr.setImageCntrParam(true,
7 true, true);
8 crr.rightHanderBlock();
9 crr.setLayout(new ConRefLayout(
10 cssClass, 0, 0, 0));
11 CellRender cr =
12 new CellRender(crr, BASE_ALIGN);
13 RowRender rr = new RowRender(cr,
14 BASE_ALIGN);
15 ConditionalRender spr =
16 new ConditionalRender();
17 spr.addRender(new FlatRender(rs),
18 new NotRslv(new FirstElemRslv()));
19 SerialRender mr =
20 new SerialRender();
21 mr.addRender(spr);
22 mr.addRender(rr);
23 return mr;
24}

At the top of the hierarchy is the main render object mr of class SerianRender. That render contains two renders: rr, which renders the actual rows, and spr. The second one is responsible for spacing between rows of the result table. It is a conditional render that will include a spacer HTML fragment defined in rs for all rows except the first one. The value is read from a resource bundle at startup. The first row in the result table doesn't require a spacer. The object of class FirstElemRslv recognizes the first row in a table and the result is negated by object NotRsvl.

The second part of the main render is the chain of RowRender, CellRender and CntRefRender renders. These renders draw row tag, cell tag and the content reference object representation correspondingly. The following diagram illustrates how a block render is assembled from standard renders.

Let's consider how a render processes each contentlet.

When method build() is invoked on a render, it normally creates a StringBuffer and generates some HTML code into that buffer. For instance, if the main render is a RowRender, it adds an opening tag <TR> to the buffer with attributes specified in its layout object. Then the render invokes build() method on all contained renders in turn, passing along the contentlet. It adds the results from the containing renders to the buffer; then performs necessary post-processing (i.e., adds a closing </TR> tag and returns the content of the buffer). The outer render can always intercept and modify results of its inner renders.

JSP-blocks
The top level of code generation is provided by JSP-blocks. All blocks implement the IBlock interface with the method:

String build(HttpServletRequest r);

That method is invoked at the time of rendering from the JSP.

The Vitrage Framework implements three types of blocks: Controls, Regular blocks, and Composites.

Controls are the simplest kind of blocks to extend class ABlock directly and have to provide their own implementation of method build(). Typically they don't render contentlets but are used to create smart titles, pagination controls and A-to-Z indices, for example.

Regular blocks are responsible for rendering collections of contentlets in compartments. They encompass probably more than 90% of all blocks in a typical application. Regular blocks extend abstract class SimpleBlock. They should implement only two methods:

IBlockData getData(HttpServletRequest r, String gn);
ARender prepareRender(IBlockData d);

Method getData() is responsible for obtaining data, normally from the request object. Typically, IBlockData would contain a collection of contentlets and other supplementary data, such as the title of the compartment. Method prepareRender() assembles a block-specific render from standard renders.

Class SimpleBlock implements method build(). This implementation generates the block's header, then iterates over contentlets passed in the IBlockData object and generates the footer. While iterating over contentlets, it passes each one to the block's render, accumulating the result and recovering from any exceptions. If one contentlet was rendered successfully, build() returns the entire HTML; otherwise, it flushes the buffer and returns an empty string.

Such architecture allows implementing presentation logic on multiple levels: for each contentlet inside the block's render and for the entire block in build() method. Composite blocks implement such logic on an inter-block level.

This design facilitates a high degree of code reuse among blocks. Figure 7 contains a complete implementation for a class that renders the P&C compartment with all the business requirements listed above:

1 public class PAProgramsCompaigns
2 extends RegularRightBlock
3 {
4 public PAProgramsCompaigns(
5 String title, String blockID)
6 {
7 super(title, blockID);
8 setEndFrag(
9 getResource(blockId, END_FRAG));
10 setCssClass(
11 getResource(blockId, CSS_CLASS));
12 rowSpacer = getResource(blockId,
13 ROW_SPACER);
14 }
15}

Class PAProgramsCompaigns inherits from RightHandBlock, as shown in Error! Reference source not found. Error! Reference source not found.contains com-pletes the RightHandBlock class implementation.

1 abstract public class RightHandBlock
2 extends CTSearchEntryBlock
3 {
4 String rowSpacer;
5 public RightHandBlock(String title,
6 String id)
7 { super(title, blockID); }
8
9 protected String getStartFrag()
10 {return getResource(id, FSTART);}
11
12 public ARender prepareRender(
13 IBlockData data)
14 { // see Figure 5 }
15}

More Stories By Alexey Yakubovich

Alexey Yakubovich works as a framework architect at Roundarch, Inc. He received his PhD in mathematics in Moscow State University for research in mathematical logic, and has published more than two dozen articles in mathematical magazines. Alexey has spent 20 years in software development.

More Stories By Alex Maclinovsky

Alex works at Sun Microsystems as the Engineering Manager for Sun SOA Governance Solution. For nearly two decades he architected and built distributed systems on enterprise, national and global scale. Alex specializes in SOA Infrastructure, Security and Composite Applications. He blogs at http://blogs.sun.com/RealSOA/ and can be contacted at maclinovsky@yahoo.com

Comments (4) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Alex Maclinovsky 04/07/05 01:15:09 PM EDT

I understand how immodest it is to leave feedback to my own article, however:
1) It took a verylong time for the article to get published, and a lot happened during this time. So both authours are no longer with RoundArch. I can be contacted at maclinovsky@yahoo.com
2) We did get the eprmission of RoundArch management to place Vitrage into public domain, but having switched jobs we never got to actually doing it. If you are interested in almost productized version, write to me. If enough people show interest we can start an open source project.
3) To answer Marina's question and preempt many other "... but have you seen ...?" ones. Yes it is a neat and very reach tag library, however it does nto change the fundamental issue that JSP is not a place to exercise imperative programming, in fact the richness of this library, would make the code required to implement a heavily compartmentalized page even harder to understand and maintain.

Jack C. Holt 03/30/05 11:49:23 AM EST

I just tried to send email to the email addresses for the authors and my email server is telling me that those email addresses don't exist. How can I reach the authors?

Jack C. Holt 03/30/05 11:34:31 AM EST

Unfortunately, I noticed some typos in this article. For instance the white paper for Vitrage is actually at http://www.roundarch.com/features/vitrage.html. I would have appreciated a link to where I can download the code Vitrage code.

Marina Prikaschikova 03/22/05 09:54:46 AM EST

>The reason custom tags lead to such complexity is that
>tag libraries are designed to cover the basic HTML
>constructs like anchors, tables and forms.
maybe it is true for JSTL/JSF but have you seen Coldtags suite for example: http://www.servletsuite.com/jsp.htm ?