|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Features JavaServer Faces: The Importance of Components
How JSF and reusable components can shorten your development time
By: Jim Cook
Jan. 23, 2009 04:24 PM
JavaServer Faces has established itself as the leading framework for JEE development. In spite of its rising popularity, many development teams are unfamiliar with its use of components: so let's begin with a description of JSF components and what they have to offer. At its most basic, a component begins as a new tag, sometimes called a "custom tag" that you can add to a JavaServer Page (JSP). When the JSP is compiled, the tag is converted to a more complicated HTML-base structure. For example a simple tag like <mylib:emailSearch> might be converted to an entire HTML form to look up someone's e-mail, maybe something like: <form method-"post" action="goGetEmails"> This code is generated from a Java class: the JSP compiler locates this class via a processing instruction that's placed at the top of the file, like this: <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%>. If you've been working with JSPs you're probably familiar with the JSP Standard Template Library (JSTL) that uses this Central to the use of JSTL is the JSP expression language. The "EL," as it's called, makes server-side data available to the JSTL tags as they are being compiled. For example this tag, <c:out value="${sessionScope.userName}" default="Smith" /> will look in the current session for an attribute called "userName" and print out its value. If there's no session, or if the session doesn't contain this attribute, the tag will simply print out "Smith." While this is great for dynamically displaying data, it falls short when you're working with data that the user needs to change. JSTL gives you a way to put data into the browser, but no way to detect changes to that data. This is where JSF comes in. The JSF framework can track all the data that is passed between the browser and server, validate it, and convert the simple text strings that the server gets from the browser into proper Java objects. JSF ships with a set of component tags built in. Let's use one for another example. The inputText tag creates an input field whose data can be tracked, validated and converted. <h:inputText id="uname1" required="true" value="#{myBean.userName}" maxlength="25" /> This tag will produce an HTML input type="text" field. Assuming that this line is part of a form, here's how JSF will handle it.
Attributes like reaquired and maxlength are called "validators." JSF provides a solid core of validators for commonly used data constraints. You can examine them at http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/tlddocs/index.html. Let's briefly examine one before we move on. The Long Range validator lets you check that the data in an input field is a valid number and that it falls between some minimum and maximum value. Suppose we want to accept numeric input between the values 199 and 4042. We would code our tags as: <h:inputText id="counter" required="true" value="#{myBean.myCounter}"> If the user enters non-numeric data, he'll get a message that the data isn't the correct type. If he enters a number that's out of range, he'll get a message that tells him so. So What About Components? This component requires a collection of beans that it will convert to rows in an HTML table. The data in the table will be sortable, pageable, and editable. For this example let's assume an EmployeeBean that stores the following data: Strings: firstName, lastName Let's further assume that our employee data has been put in this Bean and collected into an ArrayList called employees. So to set up our table we'd start with: <ig:webGrid The pageSize attribute specifies that only 10 rows will be displayed at a time. The topPagerRendered attribute causes a paging subcomponent to be rendered at the top of the grid. The dataSource attribute indicates the server-side bean that will supply the data. Next we'll add tags to specify the columns in the table. <ig:column sortBy="lastName"> The sortBy attribute makes this column sortable on the employees' last names - no other code is needed for this. The facet tag adds a header to the column. The outputTExt tag after the facet adds the data to the column. All remaining columns would be added in the same manner. In the browser, the table would resemble the following image, taken from the company's Web site. Hopefully this example helps clarify the power and reusability of a component. To use these tags with another set of data, you'd need to change only the dataSource and values of the outputText value attributes. While this approach to generating tables is easy and powerful, it's only one example of component usage. There are dozens of components from companies that make it easy to build rich interactive interfaces. I think it's clear that what we've seen so far can, by itself, speed up the development of Web 2.0-style interfaces, but we've really just scratched the surface of what's possible. Next, we'll look at techniques for changing attribute values dynamically using the example data table we examined above. After that we'll see how to generate entire components from server-side Java objects. When writing EL expressions for JSF we're normally referring to the accessor methods of plain Java Beans. In an expression like #{myExampleClass.employees}myExampleClass refers to a class. The name itself is specified in a faces-config.xml configuration class: here you'll see the name set up much as a servlet name is set up in web.xml. The employees node refers to a public ArrayList getEmployees() method inside the class. You'll recall that I explained that JSF automatically updates all data values when a page is submitted. Typically (there are several way to manage this) all those values will be available to the bean that contains the getEmployees method. That means that getEmployees can make decisions about what to display based on other values on the page. So the user can make choices that affect what is displayed back to them. Let's work through an example. Imagine a page that will display the employees of a company (see Figure 1). The user contains a set of radio buttons that lets him select on "Hourly," "Salaried," or "Both." There's also a submit button to send their choice to the server. Based on their selection, the page will show the correct set of employees (hourly, salaried, or both) in a table below the radio and submit buttons. When the submit button is pressed the form is sent to the server where the JSF framework starts examining the data. The getEmployees method can then check the state of the radio buttons to decide which data to return to the grid. The code would resemble this: public ArrayList getEmployees() { GridDataDAO x = new GridDataDAO(); if(tableChoices.getValue().equals("hourly")) If you read this code carefully, you'll probably find yourself wondering where tableChoices came from. tableChoices is the server-side component that mirrors the radio button list in the HTML. Setting it up is easy. In the same class that holds the getEmployees method, declare private UIInput tableChoices = null; and generate accessor (get/set) methods for it. To associate the UIInput object with the radio button list, add a "binding" to the latter in your JSP like this: <ig:radioButtonList Notice in getEmployees that we can extract the selected value of the radio button list as a string with a simple getValue call. This gives us a simple data filter: the user has some control over what he wants to see, and we can provide a different data source to the component based on the user's choice. The component in this page can be used with different data sources without any JSP recoding. However, in the example above, this only works as long as the different ArrayLists that are sent to the JSP always contain the same type of data bean. Suppose, instead, that we want to display a completely different table based on user choices. For example, the user might want to select between commercial and residential real estate properties. To do this we'll use the "rendered" attribute of the data table. This attribute, which is a part of every JSF component, allows you to set whether or not a particular component is drawn on the page. So, to display different tables based on a user choice, we'll include tags for two different tables but set their rendered attribute to true or false based on user actions. The value of the rendered attribute will be set via an EL: <ig:webGrid The columns for the table remain the same. We must add our second table. In the JSP we can simply place it directly after the first table. <ig:webGrid Back in the server class, we'll use methods for each of these ELs. The userChoice node should be bound to a component - a radio button, dropdown list. etc. So each table has its own data source, but only the one the user selects will be appear in the browser. Let's pause for a moment and consider what would have been required to do this without the JSF framework. For each table, a lengthy method for generating the HTML would have to be coded and the code that accepts the user choice would have to decode the data from the radio buttons before it could be acted on. Further Benefits of Components Using built-in JavaScript, the Infragistics Web grid includes columns that can be moved (reordered in the grid) and resized via mouse drags. Any cell in the grid can be converted to an editable field with a mouse click, and the editable field can be any JSF component. There's more, but you get the idea. As these features pile up, the additional coding needed to support them increases exponentially. With JSF, though, it doesn't matter. A component vendor builds out all the supporting code and the JSF developer simply inserts the tag with the correct attributes and EL expressions, and then writes a little supporting code on the server. Using AJAX with JSF This doesn't include the simple components included with JSF, which aren't AJAX-enabled anyway. Summary JSF is now included in the JEE core implementation. As JEE users upgrade to EE5 (and up) they'll find that they already have JSF installed and ready to use. More and more shops are moving to JSF from both Model 2- and Struts-based applications. I hope this article has helped you see why. Reader Feedback: Page 1 of 1
Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week
Breaking Cloud Computing News
|
|||||||||||||||||||||||||||||||||||||||||||||||||