Back Contents Next

Service to Workers

The initial delegation point of the Service to Workers architecture, shown visually below, is a worker bean that processes our business and data access code, once again via a client-side business abstraction. As with each of the dispatcher architectures, the Servlet handles the request from the client, providing the opportunity for the processing of common services. After the worker bean has completed its responsibility of populating the intermediate model for the JSP, the Servlet dispatches to the JSP to generate the presentation:

 


This architecture provides a cleaner separation between the view and the controller, since the JSP page is no longer making business calls, but simply accessing the state of the pre-populated worker bean. Depending on the workflow needs of the system, a decision will have to be made about the suitability of this architecture versus one where the initial delegation point is a JSP, such as the Mediator-View. The cleaner separation of view and controller is indeed an important factor in the decision as well, and often an overriding one. Certainly, if there is not a need for multiple business calls to generate the intermediate model, then this type of architecture is a good choice.

 

In some cases, though, we may only want portions of a model to be utilized in a display and we may not want to reuse this code across requests. If the granularity of the data access components necessitate multiple calls to retrieve the data, then the Mediator-View architecture may be better suited to handle this type of situation, since the server page will make business calls on the beans as necessary.

 

Our example will allow an authenticated user to examine his or her previously stored guesses. One could imagine this feature being expanded to allow modification of the previously stored data, as well.

 

The HTML for the user interface consists of a couple input fields for the user to enter their id and password for authentication purposes. The dispatchto hidden field has been modified appropriately, and another hidden field, a flag called delegatetobean, has been added, and signals to the Servlet that we want to use our worker bean as the initial dispatch point in this scenario. It allows us to reuse the Servlet that we have been utilizing throughout our discussion with minor modifications. The screen shot below shows this HTML page:

 

 

The HTML source for this page, <jswdk-root>/examples/jsp/servicetoworkers/babygameSW.html, is as follows:

 

<!-- babygameSW.html -->

<html>

<head>

<title>Baby Game -- Retrieve stored guesses</title>

</head>

<body bgcolor="#FFFFFF">

<form method="post" action="/examples/servlet/BabyGameServlet" name="">

<center>

<h3>

Baby Game -- Retrieve stored guesses</h3></center>

 

<center>

<hr>

<br>


 

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

<br><br>

<input type=hidden name="dispatchto" value="/jsp/servicetoworkers/BabyGameSW.jsp">

<input type=hidden name="delegatetobean" value="true">

 

<input type=submit value="Retrieve">

 

</form>

</body>

</html>

 

The Servlet has been modified to include a conditional check for the delegatetobean flag. If it is set, then the Servlet uses the worker bean as the initial delegation point. In previous examples, the Servlet uses the JSP as the initial delegation point.

 

Adding this conditional, which will evaluate to true in this Service to Workers example only, allows us to reuse similar Servlet code throughout our discussion; the Servlet source is shown below. After successfully authenticating the user, the Servlet delegates to the worker bean (BabyGameWorkerSW), instructing it to load previously stored guesses based on the user's id. The worker bean is set as an attribute of the request object with the same bean id that is used in the presentation JSP (an id value of "SWworker"). This allows the JSP to share this previously instantiated and initialized bean, instead of creating a new one. In effect, we have passed the bean as an argument to the JSP.

 

The code for the Servlet is as follows, and is kept in <jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet.java:

 

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

 

import examples.auth.*;

import examples.servicetoworker.BabyGameWorkerSW;

 

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 {

      String guesser = request.getParameter("guesser");

      String password = request.getParameter("password");

 

      // Authenticate each request


 

      Authenticator auth =

        AuthenticatorFactory.create(AuthenticatorFactory.SIMPLE);

      AuthContext authContext =

        AuthenticatorFactory

          .createContext(AuthenticatorFactory.SIMPLE);

      authContext.addValue("guesser", guesser);

      authContext.addValue("password", password);

 

      auth.init(authContext);

 

      if (auth.authenticate()) {

        String dispatchto = request.getParameter("dispatchto");

        String delegateToBean =

          request.getParameter("delegatetobean");

 

        // Delegate to worker bean

        if (delegateToBean != null) {

          BabyGameWorkerSW worker = new BabyGameWorkerSW();

          worker.load(guesser);

          request.setAttribute("SWworker", worker);

        }

 

        // 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(dispatchto)

            .forward(request, response);

      } else {

        PrintWriter outy = response.getWriter();

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

      }

    } catch (Exception ex) {

      ex.printStackTrace();

    }

  }

}

 

In our earlier examples, we collected and stored a user's guesses to a text file. Now the example evolves such that the worker bean called examples.servicetoworker.BabyGameWorkerSW adds a method that loads our previously stored guesses from the store, based on an authenticated user's id. The method is defined as follows:

 

public void load(String id) {

  try {

    Store storer = StoreFactory.createStore(StoreFactory.SIMPLE);

    Properties props = (Properties) storer.load(id);

    setProperties(props);

  } catch (StoreException e) {

    e.printStackTrace();

  }

}


Additionally, the worker bean has a method that is included so that our example may make use of JSP error processing. The method is invoked as a guard clause from within the JSP in order to validate the accuracy of the data before it is presented to the user. The method throws an exception if the bean's state is incomplete, and is defined as follows:

 

public void validationGuard() throws Throwable {

  if (getGender() == null) {

    throw new Throwable("Error populating guess data.");

  }

}

 

The JSP, <jswdk-root>/examples/jsp/servicetoworkers/BabyGameSW.jsp, is shown below. Notice that it includes an explicit reference to an error page:

 

<HTML>

<HEAD><TITLE>Baby Game - Your Guesses</TITLE></HEAD>

<BODY bgcolor=FFFFFF>

<%@ page language="java" errorPage="errorPageSW.jsp" buffer="8k" %>

 

If an uncaught exception occurs within a JSP, the flow of control immediately transfers to the referenced error page, in this case errorPageSW.jsp. As mentioned, the JSP includes a guard clause at the beginning, which checks for valid data. If valid data does not exist, then the worker bean will throw an exception, which will present the error page to the user, notifying him or her of the problem. In our example, if the client enters an id and password for a valid user who has not previously stored any guesses, then the bean state will be invalid and the bean's validationGuard() method will indeed throw an exception. The error page display could easily be made as informative as necessary for the user:

 

<jsp:useBean id="SWworker" class="examples.servicetoworker.BabyGameWorkerSW" scope="request" />

 

Notice also that the JSP has the same bean id that the Servlet previously included in its setAttribute() invocation. Thus, the JSP will reuse the existing bean, which was created in the Servlet:

 

<jsp:setProperty name="SWworker" property="*" />

 

<% SWworker.validationGuard(); %>

 

<br>

<jsp:getProperty name="SWworker" property="guesser" />, here are your previously stored choices:<br>

<table BORDER COLS=5 WIDTH="75%" >

<caption></caption>

<tr>

<td> <jsp:getProperty name="SWworker" property="gender" />

</td>

<td>

<jsp:getProperty name="SWworker" property="pounds" />  lbs <jsp:getProperty name="SWworker" property="ounces" />  oz

</td>

<td>


 

<jsp:getProperty name="SWworker" property="month" />  <jsp:getProperty name="SWworker" property="day" />

</td>

<td>

<jsp:getProperty name="SWworker" property="length" />  inches

</td>

</tr>

</table>

 

<br>

 

</BODY>

</HTML>

 

The full elements of the "Service To Workers" example are:

 

q        The HTML UI, which POSTs the request to the Servlet:
<jswdk-root>/examples/jsp/servicetoworkers/babygameSW.html

q        The Servlet, which dispatches to the JSP:
<jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet

q        The JSP:
<jswdk-root>/examples/jsp/servicetoworkers/BabyGameSW.jsp

q        The ErrorPage:
<jswdk-root>/examples/jsp/servicetoworkers/errorpageSW.jsp

q        The worker bean: examples.servicetoworker.BabyGameWorkerSW

q        The supporting code, which is reused from a previous example:
examples.mediatorview.StoreFactory, examples.mediatorview.Store, examples.mediatorview.SimpleStore, examples.mediatorview.StoreException, examples.auth.AuthenticatorFactory, examples.auth.Authenticator, examples.auth.SimpleAuthenticator, examples.auth.AuthContext, and examples.auth.SimpleAuthContext

 


BackContentsNext
©1999 Wrox Press Limited, US and UK.