Digital Edition

SYS-CON.TV
Creating a JSP JavaBeans Framework
Creating a JSP JavaBeans Framework

JavaServer Pages (JSP), an API layer that extends the servlet architect, provide developers with a standard for creating template-based HTML applications. The JSP specification marries scripting tags and Java code in an HTML template with nonvisual JavaBeans and servlets running in the JSP/servlet engine. It provides a flexible solution that caters to Web developers who use a scripting approach with display logic embedded in a Web page and application developers who prefer to separate the HTML from the controlling logic by using a component-driven approach.

This article shows how to build JSP applications using a component-based framework. By leveraging nonvisual JavaBean components, the Java event model and a bean-aware IDE, I'll demonstrate how you can realize many of the rapid development advantages of component development without having to use an application server-specific IDE and API.

HTML, Application Servers and JSP
Before JSP, application server vendors created their own server-side API to display HTML Web pages. Using products such as Sun NetDynamics, SilverStream and Bluestone Web/Sapphire, developers can create a containment hierarchy of controls, set properties via property sheets and bind the controls to a database. Tags corresponding to their controls are then inserted into the HTML and used during the rendering process. Vendors developed some productive approaches to this process (they also provided input to the JSP specification); however, each vendor developed a different approach. This is now a problem since the productivity resulted from using the vendor's own API, which, of course, ran only on that vendor's server. The approach discussed in this article isn't very different from the vendors'. However, we're using commonly available tools and leveraging existing standards to improve productivity while creating a portable framework across JSP implementations.

Application server vendors are now beginning to support JSP - a good development. The products already provide most of the enterprise services needed by the JSP presentation layer. Yet base-level support of JSP differs from productive JSP support. In many of these products productive support in the form of IDE enhancements and API extensions is six months to a year away. In the meantime, you can start leveraging JSP productivity today while the vendors work toward more comprehensive solutions that differentiate their products.

Before We Begin
I'll now show what you can currently build using the tools you already own (or that are readily available). The code is limited in scope, functionality and error checking. In other words, don't try this in production!

First we'll build a JSP framework, which will consist of several JavaBeans and base classes for our application. Next we'll create a small Web application (one page) that uses the framework and beans to build the display of a JSP page. To further limit the scope of the code in demoland, we won't connect to a database or an EJB (Enterprise JavaBean) even though we would in the real world. For now we'll focus on the display aspects of a page. Most (though not all) of the code is given at the end of this article. The complete source is located on SYS-CON's Web site at www.JavaDevelopersJournal.com.

Using Components with JSP
Our JavaBeans components will encapsulate display aspects of HTML or XML tags. These tag components will reside on a JavaBeans palette in your IDE just like visual Swing JavaBeans components. Our beans will comprise HTML tags such as an input button, input text or just static HTML text. The framework is extendible, so all types of data-driven, text-based objects can be built. Does using a component-based approach sound vaguely familiar? It should. Although developing component-based JSP applications is similar to developing client-side JavaBean applications, there are several major differences. One example is event flow. In applets and applications, user actions can occur in varying sequences. In JSP/HTML applications the set of options is more defined; once the user chooses an action, the display process is a controlled event flow or batch process as the display of the page follows a predictable order of events. On demand, our tag components will "render" themselves using their properties and data. Our tags will also fire Java events during the rendering process to provide "user exits" for developers to add code that dynamically changes the runtime display. This provides a flexible architecture that the developer can exploit for Web pages with complex display logic and business rules.

JSP Scopes and the Framework
An important part of JSP and servlet development is knowing the thread safety rules for each JSP scope. JavaBeans can be instantiated in different scopes ranging from page scope (local to a page rendering) to application scope (global to all JSPs and servlets in an application). The JSPs in this article create page scope beans. This means bean instance variables are okay because the bean itself is local to a single page rendering. While page scope eliminates thread-safety concerns, heavy use of page-scope objects also creates more overhead and drags down performance.

Fortunately, the JSP framework developer can choose one of two approaches when using a framework such as this in a wider scope without making life harder for the JSP application developer. The first approach is object pooling of the beans. Application servers such as Sun NetDynamics use this technique extensively to limit the creation of new objects while serving a large number of concurrent users. The concept is the same as database connection pooling in which an instance is checked out, utilized, then checked back into the pool. The second approach separates the framework into two sets of classes: lighter-weight property objects created in a page scope that contain variable data specific to each page, and corresponding application scope objects that contain design-time property settings and methods that operate on the data. Again, our objects will be page scope objects so these measures aren't needed but I did want to address this important issue.

First Up, Events and Listeners
First we'll define the events the DataTag bean can fire. For example, the bean could fire a preDataFetch event to allow a developer to set some defaults before data is received. In another case a preHtmlOutput event that enables a developer to change the completed tag before display could be fired, or he or she could decide not to display if the current user has inadequate security. Since we're working with JavaBean components, many IDEs will recognize the events and provide visual support for easily adding them to our source code. This speeds development while providing structure to our process. For this article we'll define one event, formatOutputProperties, that fires when we're ready to add formatting to our display value. For example, we may want to format a date or add a currency format to our value. See Listing 1 for the event and listener code.

Creating a DataAdapter Class
Next, we'll define a DataAdapter class. This wrapper class retrieves values from an instance (or member) field and provides the value to the DataTag. The DataAdapter concept can become quite flexible, and subclasses could support access to JDBC resultsets and EJB components. For now we'll keep our class simple and support only single-value and array objects that use the toString() method to convert their values to string format. Wrapping an object is completed by simply passing it via the appropriate constructor. The adapter then returns values as requested, using getValue() methods. The method signatures are shown below. See Listing 2 for the complete source.

Public DataAdapter(
Object value)
Public DataAdapter(
Object[] value)
Public Object getValue()
Public Object getValue(
int Index)

Adding the DataTag Class
Now we're ready to define the DataTag. This is the core class in the framework. It controls the process of rendering text by retrieving data from a source and firing events the developer uses to customize the display process. We'll create the class and then extend it to render HTML Input Button and Text tags along with static HTML text. Our framework users will see the extensions to this object as components that are residing on the palette as JavaBeans.

Our base bean tag has two primary methods and several important properties: (1) display(int index) drives the tag-rendering process, firing events as needed - we implement this in the DataTag; (2) render(int index) is an abstract polymorphic method implemented in our subclasses - this method is called during the display process and creates and returns the HTML. Our class also contains several instance variables (see Figure 1):

  • String jspName: Name applied to a form tag for "name" and servlet request parameter purposes
  • DataAdapter valueSource: Source object from which the tag's data value will be retrieved
  • String defaultStringValue: Value used when a tag isn't bound to a source
  • String stringValue: Temporary value changed on each rendering by retrieving either a data value from the source or a copy of the default value; developer formats this value in the formatOutputProperties event
  • String extraAttr: Free-form field used by the developer to add JavaScript or other scripting information - appended as last property
  • Vector displayListeners: Event source support
Other properties work as well. For example, an extraAttributes tag, extraAttr, is included for adding JavaScript to our tags. All of our variables that have accessor methods conforming to the JavaBean specification (or defined in BeanInfo) can be set in the bean's property sheet. However, the stringValue property is meant solely for use via the API. No problem. We can choose to hide it from the property sheet by creating a BeanInfo class. The source code for the key instance variables and methods in DataTag is located in Listing 3.

Now let's examine the display method in closer detail. This is where the real action takes place. It executes property get and set statements and fires DataTag defined events. As mentioned earlier, it makes sense to define events that fire at different points in the display process to allow runtime customization. For example, the snippet of the display logic below checks for the existence of a DataAdapter as a source of our value. If none is found, it uses a default string value provided via a property sheet.

This is another example where we could consider defining an event prior to executing this logic. Why? On a tag-by-tag basis, we could then listen for the event and execute logic to change the default value or change the source DataAdapter based on user-specific information. Let's say we're including news headlines on our JSP page. One user may prefer Wall Street Journal headlines while another prefers Newsweek. We could swap the source at runtime before the value is retrieved without changing the core display process.

if(getValueSource() == null) {
setStringValue(
getDefaultStringValue());
} else {
setStringValue(
getValueSource().
getValue(index).toString());
}

Once we set our string value for display, we execute our own event, formatOutputProperties. To utilize the event, all our framework users need to do is set up a listener and add the business logic. Since most IDEs provide event and listener code-generation support, it's a snap to implement.

With our DataTag base class coded, we can now extend the class to create other tags. Only a single method, render(int index), must be implemented, though many tags will add additional properties. For example, an HTML text tag requires size and maxlength properties. The HtmlTextTag demonstrates this in Listing 4 (property getters and setters have been eliminated to save space). The complete source and the source for other tags used in the application can be found at www.JavaDevelopersJournal.com.

Finishing Our Framework
The last class to create in our framework is the container class for the DataTags. We'll call this class PageBean because it'll be created based on a reference in a JSP page (see Listing 5 for the complete source). The bean will be the connector between the JSP page and our DataTags. We could also use it to pass JSP variables, such as the pageContext, to our DataTags. The PageBean maintains a hashtable of DataTags to the JSP page. When a developer codes one of the following tags in the JSP template,

<%=pageBean.display(
"costCenter")%>
<%=pageBean.display(i,
"costCenter")%>

the method on our PageBean directs the call to the correct DataTag using the following code:

return ((DataTag) tagTable
.get(name)).display(index);

With our lightweight framework complete, we can deploy it and build the JSP application. After we JAR the classes and install them as components in our JavaBean palette, the role of the framework developer is complete. We can now leverage our IDE's capabilities to utilize our framework to speed development of the JSP.

Creating the JSP Application
For this example we'll create a budget maintenance page to list departments and their annual budgets (see Figure 2). First we create the BudgetPageBean class to extend the PageBean class (see Listing 6). Next, we use our IDE (I'm using VisualCafé) to drag and drop DataTags representing HTML tags onto the BudgetPageBean.

I did this for each HTML tag on the page and then renamed the tags and set the properties. For example, two of our tags are a cost center text field and an OK button (see Figure 3). We may be able to drag and drop the objects to our bean using our editor. If not, we can do it by adding them to the source as instance variables. We'll also code several set methods to initialize properties. Again, an IDE may create this code for us via property sheet changes or we'll code the changes ourselves in a constructor or init event.

costCenterTag.setJSPName(
"costCenter");
costCenterTag.setMaxLength(8);
costCenterTag.setSize(8);
okTag.setJSPName("okButton");
okTag.setDefaultStringValue(
"OK");
okTag.setExtraAttr(
"onClick=\"return
buttonEvent(\'Ok\')\"");

Next, we'll add our instance variables that are our source data items. These values will be set by our business logic prior to displaying the page. Note: We include support for both single-value items and array items. This structure corresponds to the servlet API's support for both types via getParameter() and getParameterValues().

With all our variables defined, we'll complete the initial setup by linking the tag to its container and data source. enableTag() adds the tag to the pageBean's hashtable and setValueSource() sets the object from which we'll retrieve data values.

enableTag(costCenterTag);
costCenterTag.setValueSource(
costCenter);

Let's make this more interesting by adding currency formatting to the budget text field for display purposes. We'll just register an event listener with the budgetTag so we can respond to the formatOutputProperties event (see Figure 4). Your IDE may even add all the plumbing for the listener. In your listener, add the business logic to make the change. The code that changes the formatting is shown below.

DataTag tag = (DataTag)
event.getSource();
tag.setStringValue("$" +
tag.getStringValue() + ".00");

Creating the JSP Page
The last step in our process is to create the JSP page. Actually, this can be your first step, depending on your preferred approach. We'll create a basic JSP page with some single-value tags along with an HTML table. Note that very little business logic or display code is needed in the JSP page. This keeps our HTML clean and provides for easier graphical HTML editing via DreamWeaver or FrontPage. The controlling display logic is maintained in our PageBean-derived class instead of being interspersed with HTML in the JSP template. The JSP source is in Listing 7. Take note that we have easily incorporated an HTML table into our source. Since our framework supports arrays, we just pass a row number to our source.

<%for(int i=0; i<3; i++) {%>
<tr><td><%=pageBean.display(
i,"dept")%></td>
<td><%=pageBean.display(
i,"budget")%></td></tr>
<%}%>

There you have it! We've implemented a JSP component-based framework and built our first Web page by applying it. Using this approach isolates the HTML template from the dynamic display control logic, allows us to use a component-based approach and leverages the rapid application capabilities of today's IDEs.

About David Lyons
David Lyons is a technology director with Virtualogic in Bethesda, Maryland. A Sun NetDynamics certified instructor, David has developed Web applications using several Java application servers.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1



ADS BY GOOGLE
Subscribe to the World's Most Powerful Newsletters

ADS BY GOOGLE

SYS-CON Events announced today that DatacenterDynamics has been named “Media Sponsor” of SYS-CON's 1...
CloudEXPO New York 2018, colocated with DXWorldEXPO New York 2018 will be held November 11-13, 2018,...
Dynatrace is an application performance management software company with products for the informatio...
@DevOpsSummit at Cloud Expo, taking place November 12-13 in New York City, NY, is co-located with 22...
DXWordEXPO New York 2018, colocated with CloudEXPO New York 2018 will be held November 11-13, 2018, ...
Today, we have more data to manage than ever. We also have better algorithms that help us access our...
Bill Schmarzo, author of "Big Data: Understanding How Data Powers Big Business" and "Big Data MBA: D...
A valuable conference experience generates new contacts, sales leads, potential strategic partners a...
DXWorldEXPO LLC announced today that ICOHOLDER named "Media Sponsor" of Miami Blockchain Event by Fi...
SYS-CON Events announced today that IoT Global Network has been named “Media Sponsor” of SYS-CON's @...
The best way to leverage your Cloud Expo presence as a sponsor and exhibitor is to plan your news an...
DevOpsSummit New York 2018, colocated with CloudEXPO | DXWorldEXPO New York 2018 will be held Novemb...
DXWorldEXPO | CloudEXPO are the world's most influential, independent events where Cloud Computing w...
Disruption, Innovation, Artificial Intelligence and Machine Learning, Leadership and Management hear...
Enterprises are striving to become digital businesses for differentiated innovation and customer-cen...
DXWorldEXPO LLC announced today that Telecom Reseller has been named "Media Sponsor" of CloudEXPO | ...
Consumer-driven contracts are an essential part of a mature microservice testing portfolio enabling ...
"Calligo is a cloud service provider with data privacy at the heart of what we do. We are a typical ...
Digital Transformation: Preparing Cloud & IoT Security for the Age of Artificial Intelligence. As au...
DXWorldEXPO LLC announced today that "IoT Now" was named media sponsor of CloudEXPO | DXWorldEXPO 20...