The J2EETM Tutorial
Home
TOC
Index
PREV TOP NEXT Search
Feedback

Web Client

In the Duke's Bank application, the Web client is used by customers to access account information and perform operations on accounts. For example, Figure 18-6 shows an account history screen.

Figure 18-6 Account History

Table 18-2 lists the functions the client supports, the URLs used to access the functions, and the components that implement the functions.

Table 18-2 Web Client 
Function
URL Aliases
JSP Pages
JavaBeans Component
Home page
/main
main.jsp

Log on or off the application
/logon
/logonError
/logoff
logon.jsp
logonError.jsp
logoff.jsp

List account
/accountList
accountList.jsp

List the history of an account
/accountHist
accountHist.jsp
AccountHistoryBean
Transfer funds between accounts
/transferFunds
/transferAck
transferFunds.jsp
transferAck.jsp
TransferBean
Withdraw and deposit funds
/atm
/atmAck
atm.jsp
atmAck.jsp
ATMBean
Error handling
/error
error.jsp

Design Strategies

The main job of the JSP pages in the Duke's Bank application is presentation. A strategy for developing maintainable JSP pages is to minimize the amount of scripting embedded in the pages. In order to achieve this, most dynamic processing tasks are delegated to enterprise beans, custom tags, and JavaBeans components.

In the Duke's Bank application, the JSP pages use enterprise beans to handle interactions with the database. In addition, the JSP pages rely heavily on JavaBeans components for interactions with the enterprise beans. In the Duke's Bookstore application, presented in chapters 10 to 13, the BookDB JavaBeans component acted as a front end to a database or as a facade to the interface provided by an enterprise bean. In the Duke's Bank application, TransferBean plays the same role. However, the other JavaBeans components have much richer functionality. ATMBean invokes enterprise bean methods and sets acknowledgement strings according to customer input, and AccountHistoryBean massages the data returned from the enterprise beans in order to present the view of the data required by the customer.

The Web client uses a template mechanism implemented by custom tags (discussed in A Template Tag Library) to maintain a common look across all the JSP pages. The template mechanism consists of three components:

Finally, the Web client uses three logic tags--iterate, equal, and notEqual--from the Struts tag library discussed in the section The Example JSP Pages to perform flow control.

Web Client Life Cycle

Initializing the Client Components

Responsibility for managing the enterprise beans used by the Web client rests with the BeanManager class. It creates customer, account, and transaction controller enterprise beans and provides methods for retrieving the beans.

When instantiated, BeanManager retrieves the home interface for each bean from the helper class EJBGetter and creates an instance by calling the create method of the home interface. Because this is an application-level function, BeanManager itself is created and stored as a context attribute by a ContextListener (see Handling Servlet Life-Cycle Events) when the client is first initialized.

public class BeanManager {	
   private CustomerController custctl;	
   private AccountController acctctl;	
   private TxController txctl; 	
   public BeanManager() {	
      if (custctl == null) {	
         try {	
            CustomerControllerHome home =	
               EJBGetter.getCustomerControllerHome();	
            custctl = home.create();	
         } catch (RemoteException ex) {	
            System.out.println("...");	
         } catch (CreateException ex) {	
            System.out.println();	
         } catch (NamingException ex) {	
            System.out.println();	
      }	
   }	
   public CustomerController getCustomerController() {	
      return custctl;	
   }	
   ...	
}	
	
public final class ContextListener	
   implements ServletContextListener {	
   private ServletContext context = null;	
   ...	
   public void contextInitialized(ServletContextEvent event) {	
      this.context = event.getServletContext();	
      context.setAttribute("beanManager", 	
         new BeanManager());	
      context.log("contextInitialized()");	
   }	
   ...	
}
 

Request Processing

All requests for the URLs listed in Table 18-2 are mapped to the dispatcher Web component, which is implemented by the Dispatcher servlet:

public class Dispatcher extends HttpServlet {	
   public void doPost(HttpServletRequest request,	
      HttpServletResponse response) {	
   ...	
   String selectedScreen = request.getServletPath(); 	
	
   request.setAttribute("selectedScreen", selectedScreen);	
   BeanManager beanManager = getServletContext().getAttribute(	
      "beanManager"); 	
   ...	
   if (selectedScreen.equals("/accountHist")) {	
      ...	
   } else if (selectedScreen.equals("/transferAck")) {	
      String fromAccountId = 	
         request.getParameter("fromAccountId");	
      String toAccountId =	
         request.getParameter("toAccountId");	
      if ( (fromAccountId == null) || (toAccountId == null)) {	
         request.setAttribute("selectedScreen", "/error");	
         request.setAttribute("errorMessage",	
            messages.getString("AccountError"));	
      } else { 	
         TransferBean transferBean = new TransferBean();	
         request.setAttribute("transferBean",	
         transferBean);	
         transferBean.setMessages(messages);	
         transferBean.setFromAccountId(fromAccountId); 	
         transferBean.setToAccountId(toAccountId);	
         transferBean.setBeanManager(beanManager);	
         try {	
            transferBean.setTransferAmount(new	
               BigDecimal(request.	
                  getParameter("transferAmount")));	
            String errorMessage = transferBean.populate();	
            if (errorMessage != null) {	
               request.setAttribute("selectedScreen",	
                  "/error");	
               request.setAttribute("errorMessage",	
                  errorMessage);	
            } 	
         } catch (NumberFormatException e) {	
            request.setAttribute("selectedScreen",	
               "/error");	
            request.setAttribute("errorMessage",	
               messages.getString("AmountError"));	
         }	
      }	
      ...	
      try {	
      request.getRequestDispatcher("/template.jsp").	
         forward(request, response);	
      } catch(Exception e) {	
      }	
   }	
}
 

When a request is delivered, Dispatcher does the following:

  1. Retrieves and saves the incoming request URL in the request attribute selectedScreen. This is done because the URL will be modified when the request is later forwarded to the application's template page.
  2. Creates a JavaBeans component and stores the bean as a request attribute.
  3. Parses and validates the request parameters. If a parameter is invalid, Dispatcher may reset the request alias to an error page. Otherwise, it initializes the JavaBeans component.
  4. Calls the populate method of the JavaBeans component. This method retrieves data from the enterprise beans and processes the data according to options specified by the customer.
  5. Forwards the request to template.jsp.

As mentioned earlier, template.jsp generates the response by including the responses from subcomponents. If the request is a GET, the body subcomponent usually retrieves data from the enterprise bean directly; otherwise it retrieves data from the JavaBeans component initialized by Dispatcher.

Figure 18-7 summarizes the interaction between these components.

Figure 18-7 Web Component Interaction

Protecting the Web Resources

In the J2EE platform, a Web resource is protected from anonymous access by specifying which security roles can access the resource (see Controlling Access to Web Resources). This is known as a security constraint. The Web container guarantees that only certain users acting in roles specified in the security constraint can access the resource. In order for the Web container to enforce the security constraint, the application must specify a means for users to identify themselves (described in Authenticating Users of Web Resources) and the Web container must support mapping a role to a user.

In the Duke's Bank Web client, all of the URLs listed in Table 18-2 are restricted to the security role BankCustomer. The application requires users to identify themselves via the form-based login mechanism. When a customer tries to access a Web client URL, and has not been authenticated, the Web container displays the form-based login URL /logon, which is mapped to the JSP page logon.jsp. This page contains a form that requires a customer to enter an identifier and password. The Web container retrieves this information, maps it to a security role, and verifies that the role matches that specified in the security constraint. Note that in order for the Web container to check the validity of the authentication information and perform the mapping, you must perform these two steps when you deploy the application:

  1. Add the customer's group, ID, and password to the default realm of the container (see J2EE Users, Realms, and Groups).
  2. Map the BankCustomer role to the customer or customer's group (see J2EE Users, Realms, and Groups).

Once the customer has been authenticated, the identifier provided by the customer is used as a key to identify the customer's accounts. The identifier is retrieved from the request as follows:

<% ArrayList accounts = 
beanManager.getAccountController().getAccountsOfCustomer(	
   request.getUserPrincipal().getName()); %>
 
Home
TOC
Index
PREV TOP NEXT Search
Feedback