Thursday, December 7, 2006

JavaServer Faces and ASP.NET - A Side by Side Look

If you develop web applications you have probably heard the names JavaServer Faces and ASP.NET. It is also likely that you are much more familiar with one technology than the other. Both represent the next generation in web development frameworks. ASP.NET is a member of the .NET platform owned by Microsoft and is a successor to Microsoft's ASP (Active Server Pages) technology that became popular in the 1990s. JavaServer Faces is a member of the J2EE (Java 2 Enterprise Edition) family. JSF can be thought of as the successor to pure JSP (JavaServer Pages) web applications, though JSP is still a supported standard. JavaServer Faces, commonly referred to simply as JSF, is a technology with the backing of software vendors such as Sun, Oracle, and IBM, all of whom have made strong commitments to J2EE. Together, JSF and ASP.NET share a common goal: bring the same component-oriented, event-driven approach to web development that made programming languages such as Visual Basic so popular.

As these two frameworks have evolved, they have become surprisingly similar in many ways. Both ASP.NET and JSF are huge topics in themselves and it would be impossible, and probably impractical, for a detailed look at even one of these frameworks in a single article. It is worthwhile, I think, to take a quick look at both of these frameworks together to illustrate their similarities and differences. Rather than diving into technical details, I want to take a pragmatic approach and attempt to educate while stepping through a sample application. This will require touching briefly on related technologies. For example, a quick look at data access strategies in .NET and J2EE will be necessary because most applications, whether they are web-oriented applications or not, will utilize these data access technologies. This article will be part one of a two part series. In this article, we will get a basic application working. Next month, we will discuss additional features that are common to most web applications.

Overview of Frameworks

Building applications with classic ASP or JSP technology often meant mixing code with HTML markup. At the time they were introduced, these platforms offered big advantages over previous methods used for building web applications. Both JSP and ASP provided similar object models. Objects utilized in JSP and ASP applications included Request, Response, and Session objects. There was no real attempt to conceal the complexities of dealing with the stateless nature of the HTTP protocol. Developers used to developing traditional thick client applications found programming for the web challenging because simple things like retaining field state between screens could no longer be taken for granted.

The ASP.NET and JSF frameworks are component-based and event-driven. That is, components on a form respond to user actions by firing application events. These events give the programmer the opportunity to write code to perform necessary logic. This is a very different paradigm than the 'request-driven' development required for JSP and ASP. The intent here is to create a more intuitive programming model similar to what you would find when building a Visual Basic or Java Swing application. JSF and ASP.NET web pages are an assemblage of components. Each framework provides a standard set of components and there are a number of individuals and open-source and commercial organizations that offer custom components (often referred to as 'Controls' in the ASP.NET world). Microsoft recently released ASP.NET 2.0, which adds many more components than the previous release. Unlike ASP.NET, which is owned by a single vendor, JSF is a standard specification that was developed through the collaboration of many J2EE vendors. There are numerous implementations in addition to the reference implementation provided by Sun Microsystems and many vendors have added their own component libraries. JSF is a newer technology than ASP.NET and lags a bit in component market but the JSF component market seems to be growing.

ASP.NET and JSF applications can be built using simple text editors. An IDE (Integrated Development Environment) is not required. However, tools are critical to the success you will have when building ASP.NET or JSF applications. A good IDE such as Microsoft's Visual Studio.NET or the Sun Java Studio Creator allows you to drag and drop components from a palette onto the page and customize its behavior and appearance through property editors. Recently, with the introduction of .NET 2.0, Microsoft announced an Express Edition of Visual Studio.NET that is free for developers and compatible with the commercial versions of the tool. Sun Java Studio Creator is also a free tool. In this article, I'll use both the Express Edition of Visual Studio.NET and Sun's Java Studio Creator.

Visual Studio / Java Studio Creator Component Palettes

From this point on we will begin building a simple application that employees can use to reserve conference rooms. I have used this application in previous articles because it is simple yet offers just enough features to provide an adequate demonstration. As we build the application we will look at some of the core concepts of both frameworks. The applications in this article use the same Mysql database that contains two tables, conference_rooms and room_reservations. The tables contain some sample data as well. Here is the SQL.

Building the Applications

A logical first step would be to create the web pages that users will see when starting each of these applications. The start pages will serve as more than just a welcome page. They display a table view of the available conference rooms that the user can reserve for a specific time interval. Ideally, ASP.NET and JSF web pages should contain little code. Rather, they will contain HTML and tags necessary to render the page's components. The logic for a page's events will reside in code files. In ASP.NET each web page is associated with a corresponding .NET class file that subclasses the Page ASP.NET class. These files are sometimes referred to as 'code-behind' files. In JSF, every web page has an associated backing JavaBean class. Both the ASP.NET code-behind file and the JSF backing bean contain the page properties such as labels and input fields. JSF beans are written in Java. ASP.NET code-behind files can be written in any of the .NET languages such as VB.NET or C#. ASP.NET code-behind classes handle the associated page's events. The Java class that handles a component's events is not necessarily the page's backing JavaBean. We will come back to this shortly. It should be noted that separate code-behind files are not a requirement in ASP.NET. It is possible to code events directly in the pages themselves. This is considered a bad practice in general as doing so would reintroduce the familiar problems that result when developers mix HTML and code together.

Below is a screen shot of the two start pages for our sample ASP.NET and JSF applications. They look slightly different due to the visual differences inherent in the two components and also because I did not bother to apply matching visual styles. In both pages, a grid of conference rooms displays along with buttons for viewing reservations tied to that room and adding a new reservation for the room.

ASP.NET
JSF

These components were added through drag-and-drop. I customized their appearances and much of their behaviors by modifying properties in a property palette. I had the option of course of customizing the components by editing their tags in the HTML source. Hopefully you will agree that the 'visual' approach is preferable to editing text, therefore I will not spend time looking at the markup code. We will, however, look at the code files behind the web pages to get a glimpse of the event code.

I thought that displaying tabular data like this was a good place to start, as it is a very common requirement for applications. ASP.NET and JSF do not overlook the need for components that provide a convenient display of data. Both of the displayed components provide built in functionality for tasks like sorting and pagination. ASP.NET provided numerous data display components prior to ASP.NET 2.0, the Datagrid component being the most widely used. ASP.NET 2.0 ships with a new Gridview component and I have chosen to use it as it adds several new and useful features. ASP.NET components take advantage of ADO.NET technology, which is the data access technology for the .NET framework. ADO.NET provides a robust object model for working with various types of data sources. The Dataset object, for example, allows you to work with data in a disconnected fashion, meaning your application does not need a constant database connection in order to work with data. A Dataset also allows you to conceal database specifics behind its interface, enabling you to switch databases with little impact on the rest of the application. The JSF component I am using in this example is the Table component that ships with Java Studio Creator. It uses a DataProvider object that allows you to utilize JDBC (Java Database Connectivity) Rowset technology. JDBC Rowsets also enable you to work with a database in a disconnected, easy to use fashion.

These start pages contain a single label component for the page heading. Page components can be accessed and modified during a page's event handlers. Using an IDE, you can wire most events to a component by simply double-clicking the component in the visual editor. This will take you to the place in the code file where you can add code. As we noted earlier, the ASP.NET Page class associated with the web page is where your event code will reside. In JSF, it's not quite as simple as that. JSF events follow the Observer design pattern. Objects that want to be notified of certain events register themselves as listeners for that event. There are just two types of events in JSF: a Value Changed event and an Action event. Value Changed events typically occur from such actions as list box selections. Action events result from user actions such as a button click. Any Java class can respond to a web form's events. The backing bean for the JSF page, however, is a convenient place for event methods and tools such as Sun Java Studio Creator will assume this is where you want to put them.

When an ASP.NET application is started, configuration settings located in a file called web.config are parsed and applied. Every ASP.NET application has a web.config. We took advantage of this file by storing our connection string to the Mysql database there. The web.config is often used to hold database connection strings to keep this information outside of code. Here's a snippet of the web.config file:

 
connectionString="Driver={MySQL ODBC 3.51 Driver};server=localhost;database=test;uid=testuser;pwd=testpassword"
providerName="System.Data.Odbc"/>

JSF applications rest upon the architecture of a typical Java Servlet-based application. A 'WEB-INF' folder exists with subfolders and a file called 'web.xml' contains application settings much like ASP.NET's web.config. The Mysql connection string is not stored in the web.xml of this JSF application. Rather, Studio Creator automatically added the connection information to the server's configuration file and our application accesses it through JNDI (Java Naming and Directory Interface), a common way to look up J2EE services. Every JSF application's web.xml file specifies a Java Servlet of type FacesServlet. The FacesServlet is responsible for configuring our application's settings pertaining to its use of JSF. In a JSF application all requests are channeled through the FacesServlet. This Servlet controls the flow between an application's pages based upon the outcome of component events. This is known as the 'Front Controller' design pattern. This level of indirection is missing from ASP.NET, where the page itself controls the page flow, known as the 'Page Controller' design pattern. The FacesServlet knows how to route requests by referencing page–to–page mappings stored in a configuration file called ’faces-config.xml’. This configuration file also contains a number of JSF configurations that we will address in a bit.

ASP.NET and JSF pages follow very similar lifecycles. We've discussed how components generate events based upon user actions but events are only part of this lifecycle. Taking a high-level view of the lifecycle of a page, it goes something like this: a user makes a request and the page is initialized, the entire component tree of the page is read in and the state of the components is restored, events are handled according to user actions and the values of components are updated, then the resulting page is rendered back to the user. Of course, it is much more complex than that and there are important stages such as data validation that fall in between those steps. One key difference between JSF and ASP.NET is how components are rendered to the user. ASP.NET components render themselves on the page. In JSF, components can render themselves, but more often they delegate rendering to special Renderer objects, made available in a 'RenderKit'. A different RenderKit can be supplied for each different type of presentation medium. A default HTML RenderKit is provided by every JSF implementation. What this all means is that the same JSF component can be rendered differently in a web browser or wireless device by simply plugging in a different Render object. This is a powerful capability.

A convenient point to add code not related to any specific type of user request is when the page object is initialized. ASP.NET provides a Page_Load event that is called when a user makes any kind of request against the page. With JSF pages, you can use the class constructor method for equivalent page initialization logic. Below is the event handling code for both applications that respond to actions users take upon the data display component.


//ConferenceRooms.Java event code:

public String btnViewReservations_action() {
//Store selected room id and name of selected row...
Object id = getValue("#{currentRow.value['conference_rooms.room_id']}");
Object name = getValue("#{currentRow.value['conference_rooms.room_name']}");
ReservationsSessionBean resBean =
(ReservationsSessionBean)this.getBean("ReservationsSessionBean");
resBean.setRoomId(id.toString());
resBean.setRoomName(name.toString());

return "view";
}


public String btnMakeReservation_action() {
Object id = getValue("#{currentRow.value['conference_rooms.room_id']}");
ReservationsSessionBean resBean =
(ReservationsSessionBean)this.getBean("ReservationsSessionBean");
resBean.setRoomId(id.toString());

return "reserve";
}

//ConferenceRooms.cs event code:

protected void GrdVwRooms_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("Sort")) {
SortDirection sd;
if (((SortDirection)Session["sortRooms"]).Equals(SortDirection.Ascending)) {
sd = SortDirection.Descending;
}
else {
sd = SortDirection.Ascending;
}
Session.Add("sortRooms", sd);
this.GrdVwRooms.Sort(e.CommandArgument.ToString(), sd);
}
else
{
DataKey data = GrdVwRooms.DataKeys[Convert.ToInt32(e.CommandArgument)];
Session.Add("roomId", data.Values["room_id"].ToString());
Session.Add("roomName", data.Values["room_name"].ToString());

if (e.CommandName.Equals("Reserve")) {
Server.Transfer("Reserve.aspx");
}
else
{
if (e.CommandName.Equals("View")) {
Server.Transfer("RoomReservations.aspx");
}
}
}
}

The code is a little different and the Java class is separated into two methods because that is how the IDE chose to do it when I double-clicked the view and reserve buttons from the visual designer. The two Java events are both 'Action' events. I chose to add all event logic in the ASP.NET application in a single 'RowCommand' event and interrogate the event's argument to determine which user event occurred. Grouping related events like this in one method is done quite often. This particular event handler responds to both the view and reserve button clicks and also sorting requests as a bit of sorting logic was necessary for this ASP.NET component. Both applications save the roomId and roomName attributes for use later in the application. Here is the complete code for ConferenceRooms.java and ConferenceRooms.cs. Keep in mind that much of the code in these class files is tool-generated and that you can use code folds in the editor to make things more readable. In these event methods, the values of page components are immediately accessible to you for reading and modification. I alluded to state management being a key benefit of each framework. Developers of thick client applications such as Visual Basic have taken such behavior for granted but it is a welcome change for web developers who used to have to set and retrieve state with additional code. ASP.NET and JSF preserve view state by writing it out in hidden HTML fields and passing it along from request to request. Of course, the same methods you used to store state in traditional ASP and JSP applications are still available to you. For example, in both the ASP.NET and JSF pages, room id and name are placed in the user's Session so it can be retrieved later.

Notice in the event code above that the ASP.NET file invokes a method called 'Server.Transfer' to transfer control to another page. In the JSF event code, however, you will not find any such direct reference to another page, only the return strings "view" and "reserve". This is because JSF handles page flows via the faces-config configuration file that we discussed earlier. This will look familiar to any Java developer who has worked with the Struts open-source framework. There are two entries in faces-config.xml under the ConferenceRooms.jsp, keyed on the strings "view" and "reserve". At runtime, the application looks up the page address using these strings. Below are the navigation rules in XML for the ConferenceRooms.jsp page found in the faces-config file. I created these mappings using a visual designer in Java Studio Creator.


/ConferenceRooms.jsp

view
/RoomReservations.jsp


reserve
/ReserveRoom.jsp



Visual designer shows navigation rules in Java Studio Creator

The faces-config file is also where you list all JavaBeans associated with your JSP page file. In fact, this is where you can configure any Java objects your application needs to reference. These Java objects are referred to as 'managed beans'. All JSF backing beans will be listed as managed beans in this configuration file, but any other objects you need will be found here too. A managed bean contains the fully qualified class name, the scope of the bean (whether to store it at the Request, Session, or Application level of the application), and the name to use when referencing the bean. In the XML below, the backing bean for the starting web page is listed as well as an entry for an EJB (Enterprise JavaBean) called ReservationsSessionBean that we use to share data in the application:

    
ReservationsSessionBean
webreservations.ReservationsSessionBean
session


ConferenceRooms
webreservations.ConferenceRooms
request


A delete button accompanies each row of data. Both of these components allow you to modify table data with very little effort. Last, each form contains a button which takes you to a form for adding a new reservation for that room. These forms appear below. These were created quickly by dragging and dropping a text field for the name of the group reserving the room, two calendar components for selecting the start and end times of the reservation, and a button to save the reservation. The calendar components provided by Java Studio Creator and Visual Studio display differently, but serve the same purpose.

ASP.NET
JSF

At this point, we need to have the user enter some data and deal with the issues that arise when accepting user input, validation for example. My next article will take up where we left off here. In it, we will look at other issues most applications face such as validating input, converting data, providing error messages, and internationalization.