Back Contents Next

The "Dispatcher" Approach

We now move on to look at architectures based on the dispatcher or "N-tiered" approach, where a Servlet (or JSP) acts as a mediator or controller, delegating requests to JSP pages and JavaBeans. We will look at the mediator-view, mediator-composite view, and service to workers architectures.

 

In an N-tier application, the server side of the architecture is broken up into multiple tiers, as illustrated in the next figure:

 

 

In this case, the application is composed of multiple tiers, where the middle tier, the JSP, interacts with the back end resources via another object or Enterprise JavaBeans component. The Enterprise JavaBeans server and the EJB provide managed access to resources, support transactions and access
to underlying security mechanisms, thus addressing the resource sharing and performance issues of
the 2-tier approach. This is the programming model supported by the Java 2 Enterprise Edition
(J2EE) platform.


The first step in N-tiered application design should be identifying the correct objects and their interactions, in other words, object modeling. This is the part where class diagrams and tools like Rational Rose (http://www.rational.com) step in for architects. Quite often a line has to be drawn as to what objects need to be modeled: being over zealous can cause unnecessary complexity. If you get this part right, you're half way there!

 

The second part is identifying the JSPs or Servlets. As a rule of thumb, these should be divided into two categories, depending on the role they play, often called "web components" in the J2EE terminology

 

q        Front end JSPs or Servlets that manage application flow and business logic evaluation. This is where a lot of method invocation on the objects, or usage of EJBs, can be coded. They are not responsible for any presentation, and act as a point to intercept the HTTP requests coming from the users. They provide a single entry point to an application, simplifying security management and making application state easier to maintain.

q        Presentation JSPs that generate HTML (or even XML), with their main purpose in life being presentation of dynamic content. They contain only presentation and rendering logic.

 

The figure below shows the relationship between these two categories. The front-end component accepts a request, and then determines the appropriate presentation component to forward it to. The presentation component then processes the request and returns the response to another front component or directly back to the user:

 

Sometimes this distinction is hard to maintain, but the clearer the distinction, the cleaner the design.

These categories are analogous to the Model-View design pattern, where the front-end component is the model and the presentation component the view. This approach was referred to as the "Model 2" programming model in earlier releases of the JSP specifications. It differs from Model 1 essentially in the location at which the bulk of the request processing is performed. The figure below shows the Model 2 approach:


 

 

In this approach, JSPs are used to generate the presentation layer, and either JSPs or Servlets to perform process-intensive tasks. The front-end component acts as the controller and is in charge of the request processing and the creation of any beans or objects used by the presentation JSP, as well as deciding, depending on the user's actions, which JSP to forward the request to. There is no processing logic within the presentation JSP itself: it is simply responsible for retrieving any objects or beans that may have been previously created by the Servlet, and extracting the dynamic content for insertion within static templates.

 

Instead of writing Servlets for the front-end components you can choose, if you wish, to use a JSP that contains only code and doesn't have any presentation responsibilities. Whichever option is used (and in this chapter we only use Servlets in this role), this approach typically results in the cleanest separation of presentation from content, leading to delineation of the roles and responsibilities of the developers and page designers, especially in complex applications.

 

Beans that are used by JSPs are not the same as Enterprise JavaBeans (EJBs), but are usually simple classes that serve as data wrappers to encapsulate information. They have simple get and set methods for each bean property .The properties further correspond by name to the HTML variables on the screen. This allows the bean properties to be set dynamically by the jsp:usebean tag without doing an individual request.getParameter(parametername) on the request object. See Chapter 4 for bean usage.

Mediator-View

Factoring common services, such as authentication out to a mediating Servlet allows us to remove potential duplication from our JSP pages. The code below is an example of a Servlet that provides us with central forwarding control for our game system, and includes a simple authentication check that will be reused across requests. A Bean could be used for this purpose, but you would have to add the same code to each page to perform the authentication checks. Instead, each request will be serviced by the Servlet, which now includes our authentication code.


The mediating Servlet, BabyGameServlet.java, is shown below. It is placed in the <jswdk-root>/examples/WEB-INF/servlets/ directory:

 

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

 

public class BabyGameServlet extends HttpServlet {

  public void doGet(HttpServletRequest request,

                    HttpServletResponse response) {

    processRequest(request, response);

  }

 

  public void doPost(HttpServletRequest request,

                     HttpServletResponse response) {

    processRequest(request, response);

  }

 

  protected void processRequest(HttpServletRequest request,

                                HttpServletResponse response) {

 

    try {

 

      // If we added actual authentication, this is where it would go

      // For example purposes, if the parameters exist, we consider the

      // auth successful.

      if ((request.getParameter("guesser") != null)

              && (request.getParameter("password") != null)) {

 

        // Note: Based on the successful authentication of this user we may

        // want to consider writing something into the session state that

        // signifies that this is the case.  For example, if we wanted to

        // limit direct access to certain JSP pages only to authenticated

        // users, then we could include code that would check for this

        // session state before allowing such access.

 

        // In order to reuse this Servlet for multiple examples, we pass as

        // a request parameter the resource name to which we dispatch our

        // request.

        getServletConfig().getServletContext()

          .getRequestDispatcher(request.getParameter("dispatchto"))

          .forward(request, response);

      } else {

        PrintWriter outy = response.getWriter();

        outy.println("Unable to authenticate, please try again.");

      }

    } catch (Exception ex) {

      ex.printStackTrace();

    }

  }

}

 

A new architectural pattern is emerging, with the mediating Servlet working with a JSP page and worker bean pair to fulfill a service request. This 'Mediator-View' architecture is shown below, and illustrating how each service is partitioned. The Servlet initially handles the request and delegates to a JSP software page/worker bean combination. The JSP populates bean properties from the request parameters and then uses the bean to prepare the data for presentation:


 

 

Continuing our attempts at creating the appropriate abstractions in our system, we shall consider how to better partition our business logic and data access code, attempting to reduce the coupling among the various parts of the system.

 

As we discussed, this request is handled first by a basic Servlet that dispatches to a JSP page for formatting and display. The JSP is responsible for delegating the processing of business functionality to a business delegate via a worker bean, which act as façades for the back-end resources. We call this component a business delegate, because it is a client-side business abstraction used to complete the basic business processing by abstracting out the code that deals with the back-end communication. The worker beans might communicate through the business delegate with the back-end via Enterprise JavaBeans components running in a scalable, load-balancing container.

 

In this case, we are able to decouple the EJB implementation from the JSP worker bean by moving the EJB-related code, such as the code relating to JNDI lookup, into the business delegate. If we include our EJB-related code in our worker beans, then we are closely coupling the bean to a specific underlying implementation, and if this implementation is modified or changed we must make modifications to our worker bean accordingly. So we have succeeded in creating abstractions that have reduced the coupling among the distinct pieces of our system. We can see how the worker bean and the business delegate reduce coupling between the client request and the ultimate back-end resource.

 

In other words, the public interfaces need not change even if the API to the underlying resource changes. The worker beans can be combined with different JSP pages in order to provide different views of the same underlying information. Also, the Servlet that initially handles each request, and is responsible for authenticating each user, may restrict direct access to our JSP pages, an added security mechanism. Once a user has been successfully authenticated, the Servlet might store certain information in that user's session, and access to certain JSP pages might only be allowed to users whose session state contained such that information. The mechanism could be made more fine grained by including authorization information within this session state that would directly relate to which pages a user may view.


Our baby guessing game example will need to change, in order to adhere to this new design. The HTML user interface needs to change only slightly, adding an input field for each user to enter a password. The table caption in Babygame1.html is modified as shown below in order to add the password input field, and the revised file, babygame2.html, is placed in <jswdk-root>/examples/jsp/mediatorview/:

 

<caption>Please enter your userID:<input type="text" name="guesser">Please enter your Password:<input type="password" name="password"></caption> >

 

The other change to the HTML is to change the hidden input field called dispatchto.

The Servlet uses this value to dispatch the request via the forward() method to the appropriate JSP, and the value is supplied simply to allow for easy modification of these examples. In this case we modify the value attribute to reference the JSP for our "Mediator-View" example, and the modified line looks like this:

 

<input type="hidden" name="dispatchto" value="/jsp/mediatorview/BabyGame2.jsp">

 

We have already seen the next piece of the puzzle in the Servlet, which handles each request, authenticating each user and dispatching the request appropriately. The Servlet and worker beans now contain Java code that is owned by an individual in the software development role, and the syntax and semantics of which may be modified without any changes to our JSP. The property sheets remain a simple contract between the web-production team and the software developers.