In Part 1 of this article (JDJ, Vol. 6, issue 2) we discussed the problems associated with J2EE's Servlet/JSP container. In Part 2 we'll discuss Cybelink's Jlink architecture and how it solves those problems.
Jlink is built on various architectural and software design patterns. In this section we'll discuss the software patterns, specifically, the Model-View-Controller (MVC) patterns.
MVC Architectural Pattern
MVC is an architectural pattern that's been widely used in architecting distributed component-based applications. It facilitates the division of the application into logical components that can be designed and developed independently. This division increases the reusability of components by reducing the couplings between them.
In the MVC pattern the Model components represent the business logic (e.g., JavaBeans and EJBs), the View components represent the UI that displays the processing results of the business logic, and the Controller components manage the coordination between the Model and View components. Figure 1 shows the relationship between the various components of the MVC pattern. The Model components maintain the state of the business object and when the state of the Model object changes, they notify the View components, which update the UI with new data. It's also possible for the View components to request state changes directly from the Model components. The View components enable the Controller components to change the display according to the user's request. The Controller components map the user's actions from the View to the Model components.
Mapping MVC with Servlets and JSP
In Part 1 we discussed the problems associated with Sun's Servlet/JSP container; in the previous section we discussed the MVC pattern. Now that we understand the Servlet/JSP Container model and the MVC pattern, we can start applying the MVC to the Servlet/JSP Container model. Traditionally, the MVC pattern was used to build client/server applications; in this section we'll see how we can use it to develop Web-based applications using Servlets/JSP. In our Jlink we'll use the JSP and JavaBean as the Controller components, the JSP pages as the View components, and JavaBeans as Model components.
JSP and JavaBeans as
The AppController.jsp (see Listing 1) and AppController bean (see Listing 2) are used as Controller components that are responsible for accepting the HTTP requests and passing them to the appropriate RequestHandler object. (Listings 1-7 can be found below) The RequestHandler objects are designed using JavaBeans. These beans strip the browser requests and send them to the appropriate Command JavaBean components. The Command beans are modeled after Command Design patterns. Before handling the request to the RequestHandler objects, the AppController.jsp creates a ClientContext (see Listing 3) object for each request and passes it to the RequestHandler object. The ClientContext contains javax.servlet.HttpRequest, javax.servlet.HttpResponse, and javax.servlet.http.HttpSession objects. Thus the ClientContext encapsulates the Client state by maintaining the necessary objects in one place, eliminating the spaghetti code discussed in Part 1. Other objects should get parameters, such as Request and Query, from the ClientContext object.
JSP as View Components
In our Jlink, JSP pages represent the View components. These pages interact directly with the JavaBean Model components to get the results to display on the Browser.
The Jlink has been architected in such a way that we can use JavaBeans, EJB, C++, or any other component as the Model. The Controller and View components are not affected when we change our Model components from JavaBeans to EJBs. The Command JavaBean objects shield the Controller and View components from the Model components.
The Command JavaBean shields the Controller and View components from the Model components. They get the requests from the handler objects and pass them to the Model components located either in the same machine as the Command JavaBean or in a different one. Once the Model components execute the requests, they collect the results, which are then retrieved by the View components. The RequestHandler objects or the JSPs will worry about issues such as transactions, the Model object's location, and more. The Command JavaBean shields these issues from the Controller and View components, thereby increasing the reusability and coupling of the components.
In our Jlink all HTTP requests go to the AppController.jsp, which creates the AppController JavaBean for the first request (see Figure 2). The javax.servlet.ServletContext object is set in the AppController JavaBean. For a Web application the AppController.jsp creates one AppController JavaBean that will be shared by all the Model and View components in the Jlink. The AppController.jsp acts as a bridge between the browser and the AppController JavaBean. For each HTTP request, it creates a ClientContext object and prompts the RequestHandler to call the handleRequest method by passing the ClientContext object.
Figure 2 shows the architecture of the Jlink. If you compare Figure 1 with Figure 2 you can see how Jlink is modeled after the MVC pattern.
Now that we've discussed the high-level workings of Jlink, we'll look at individual classes and interfaces in more detail.
Jlink Classes and Interfaces
This Jlink is built on JSP, Java interfaces, and abstract and concrete classes. In this section we'll discuss the individual classes and interfaces. Figure 3 shows the UML class diagram of the Jlink.
As mentioned earlier, the AppController.jsp (see Listing 1) creates the AppController JavaBean the first time the HTTP request comes from the browser. After creating the bean, it sets the ServletContext object to the AppController bean. For each request, the AppController creates a new ClientContext object by passing the HttpServletRequest, HttpServletResponse, and HttpSession objects. Using the ClientContext object it gets the RequestHandler object from the AppController JavaBean and calls the handleRequest method by passing the ClientContext object. The RequestHandler computes the result and selects a JSP page that's appropriate for displaying it. The AppController.jsp retrieves the JSP page and passes it to the browser. Note that neither the Controller components (AppController.jsp and AppController bean) nor the View components (JSP pages) know how the results are computed in the RequestHandler object.
This interface (see Listing 4) provides basic methods that all AppControllers need to implement in order to qualify as an AppController.
The AppController JavaBean implements the Controller interface (see Listing 2). One AppController object is created per Web application the first time an HTTP request comes to that application. This AppController manages application-wide objects. The AppController JSP sets the ServletContext object to the AppController bean, which is used to store application-wide objects and can be accessed by all the JavaBeans within the application.
The java.util.ResourceBundle object is used to read the resource names and paths from a property text file. The methods getAppObject and putAppObject retrieve and add application-wide objects to the ServletContext. This provides any JSP or JavaBean within the Web application with the flexibility to add or retrieve the objects. The important method in this class is geRequestHandler, which we'll discuss in detail. Listing 5 shows the implementation of the getRequestHandler.
getRequestHandler accepts a ClientContext and checks if a RequestHandler already exists for the session in which the ClientContext object was created. If the RequestHandler doesn't exist, a new RequestHandler is created. It uses the forName static method from the class to get the Class object and the newInstance method on the Class object to create the appropriate RequestHandler object. The forName method takes the name of the class as a parameter. The class name is obtained from the property file using the key obtained from the query parameter, which is passed from the browser. This design solves our problem of mapping browser requests to proper Servlet/JSPs and avoids the big if-then-else statement in the AppController bean. Thus we can add more RequestHandler objects as the Web site grows.
Request Handler Interface
This interface (see Listing 6) provides basic methods that all RequestHandler classes must implement to qualify as a RequestHandler.
This is an abstract class (see Listing 3) that implements the RequestHandler interface and provides a generic implementation for handling HTTP requests. The Constructor is called from the AppController JSP for each HTTP request. The Constructor creates a java.util.ResourceBundle object. The name for the ResourceBundle object comes from the method getName, an abstract method in the GenericRequestHandler object. The subclasses of GenericRequestHandler must provide the actual name for the ResourceBundle. This approach provides the subclasses of the GenericRequestHandler with the flexibility to have their own ResourceBundle names. The methods getClientContext and setClientContext retrieve and set the ClientContext object. The method getNextPage returns the JSP page (View component). The handleRequest method does nothing in this abstract class. The subclasses of the GenericRequestHandler must provide the actual implementation for this method. This approach allows Jlink users to have their own project-specific implementation for the RequestHandler objects and still use the infrastructure provided by Jlink.
The ClientContext is a crucial object in our Jlink (see Listing 7). The Constructor takes HttpServletRequest, HttpServletResponse, and HttpSession objects. The methods getSessionObject and putSessionObject retrieve the objects using the HttpSession object. As explained earlier, the HttpSession object and all other objects added to the HttpSession become potential candidates for garbage collection if the browser that created the HttpSession object is timed out. The methods getRequestObject and setRequestObject retrieve the HttpServletRequest. Including the HttpServletRequest object, all other objects that are added to it become potential candidates for garbage collection when a new HTTP request comes from the browser. The methods getRequestParameterNames() and getRequestParameterValues() retrieve the names and values of the parameters set by the browser. The method getQueryString() returns the query parameter that's set by the browser. As explained earlier, the Query string is used to find the appropriate Class Name to create the RequestHandler object.
Thus the ClientContext object (see Figure 4) provides a wrapper for HttpServletRequest, HttpServletResponse, and HttpSession objects and the outside world can access them through the ClientContext object. This design avoids spaghetti code in the JSP and JavaBean source code described in Part 1.
Figure 4 shows the structure of the ClientContext object. For each HTTP request a new ClientContext object is created.
Jlink Class Diagram
In any Java-based framework Java interfaces play a critical role in creating the frameworks that provide tools for the architects, designers, and developers to create reusable components. Jlink is no different; Figure 5 shows the class diagram for the Jlink interfaces and classes described earlier. The AppController implements the Controller interface and we can create several application-specific AppController classes by implementing it. The Controller interface provides coordination among all the AppController objects within the framework. This mechanism allows us to add more application-specific AppController classes, thereby making the framework adaptable to various types of Web applications.
The GenericRequestHandler implements the RequestHandler interface and provides an abstract behavior for all the handler classes in a particular Web application. Depending on the Web application's needs, we can create several application-specific GenericRequestHandler classes by implementing the RequestHandler interface.
How Jlink Works
In the previous section we discussed the static aspects of Jlink. In this section we'll discuss the dynamic aspects. An HTTP request comes from a browser to the AppController.jsp (see Figure 5). On the first request for a Web application the AppController.jsp creates an AppController bean and sets the ServletContext object. This ServletContext object lives as long as the Web application is alive in the Servlet/JSP container. Next, the AppController JSP creates a ClientContext for every HTTP request by passing the HttpRequest, HttpResponse, and HttpSession objects. Then it uses the ClientContext to get the RequestHandler from the AppController bean.
At this level the AppController.jsp deals only with the interface RequestHandler, but the AppController bean creates an object of the class it inherits from the GenericRequestHandler class. When the AppController.jsp asks for a RequestHandler, the AppController bean gets the Session ID from the ClientContext and checks if the RequestHandler already exists by passing the Session ID to the getSessionObject method on the ClientContext. If the RequestHandler is already created, getSessionObject retrieves it from the HttpSession object stored in the ClientContext. Even though a new ClientContext is created for each new HTTP request in the AppController.jsp, the HttpSession is the same for a single browser connection. Only the HttpServletRequest and HttpServletResponse objects are created every time an HTTP request comes to the AppController.jsp. Finally, once a RequestHandler object is created, it remains as long as the corresponding browser connection is valid.
In Part 2 we discussed the Jlink's architecture and how it solves the problems of creating scalable enterprise-wide Web architecture. Jlink was built using industry best practices such as OO methodology and software design patterns. Using Jlink, organizations can create reusable component-based architecture that will evolve with the technology and the organization.
- Sun J2EE Blueprint: http://java.sun.com/j2ee/blueprints
- Gamma, E., Helm, R., Johnson, R., and Vlissides, J. (1995). Design Patterns - Elements of Reusable Object-Oriented Software. Addison-Wesley.
- Buschmann, F., et al. (1996). Pattern-Oriented Software Architecture. John Wiley & Sons.
- Fields, D.K., and Kolb, M.A. (2000). Web Development with JavaServer Pages. Manning Publications.
- Servlet/JSP API: http://java.sun.com/products/servlet/2.2/javadoc/index.html
Mani Malarvannan is CEO and cofounder
(www.cybelink.com), a Minnesota-based
company that specializes in e-business consulting and training. Mani has several years of OO analysis and design
experience and has been working in Internet and Java technologies since their inception. He holds a BS and an MS in
Download Assoicated Source Files (Zip format ~ 8.44 KB)