Tuesday 8 January 2013

J2EE Design Patterns - Front Controller


The Front Controller provides a centralized entry point to access Application, that controls and manages Web request handling, by delegating request to appropriate Action OR Model files, who are responsible for rest of business processing at server-side.
The front controller design pattern means that all requests that come for a resource in an application will be handled by a single handler and then dispatched to the appropriate handler for that type of request.
Front Controllers are responsible for routing incoming user requests in application.
With Centralizing point of access, Front Controler can manage below things at a time -
- Dispatching Request to appropriate Request handler OR Models OR Action files for Business processing. Thus Front Controller can validate the   incoming requests and route them accordingly. i.e Controlling page flow and navigation.
- Applying security services to incomming request, such as authentication and authorization.
- Accessing and managing model data.
- data validation.
- Handling business processing.
- Managing an appropriate views as per request.
- handling errors.
Advantages -
 - By centralizing controls, the controller helps reduce the amount of Java code.
 - reducing business logic in the view promotes, code reuse across requests.
 - Front Controllers can reduce code duplication in JSP pages, especially in cases where several resources require the same processing.
 - If the behavior of functions which are applied to Front Controller, needs to change, only the Front Controller and its helper classes need   to be changed. They constitute a relatively small portion of the application.
If not using Front Controller -
* view is required to provide its own system services often resulting in duplicate code.
* View navigation is left to the views. This may result in shared code for view content and view navigation.
* Distributed control is more difficult to maintain, since changes will often need to be made in numerous places.
The Front Controller suggests that we only have one Servlet (instead of having specific Servlet for each specific request) centralising the handling of all the requests and delegating the functions like validation, invoking business services etc to a command or a helper component.
Putting this use case in a simple words, we want all the request to go though a single servlet which does all the authentication and other generic operations and then based on what request was made by the user, this serlvet should transfer the request to appropriate Action item on server side.
As a web-application grows, number of controllers grow. Putting all the generic code inside these controllers in single controller, which actually performs those operations and then forwards the same request to appropriate controller is called Front Controller
In case of Struts1.xx this front controller is ActionServlet, all the request made to struts1.xx are passed though ActionServlet.
FrontController implementation examples as below -
* ActionServlet acts as FrontController in Struts 1.xx
 All Request are forwarded to ActionServlet, which in trun performs common functionality then forward request to appropriate Action (Sub-Controller)Class. this is done by using Struts-config.xml file.
* Dispatcher in Struts 2.xx


Example using HttpServlet :
------- Web.xml -------
<web-app>
  <servlet>
    <servlet-name>FrontControllerServlet</servlet-name>
    <servlet-class>com.test.FrontControllerServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>FrontControllerServlet</servlet-name>
    <url-pattern>/*.do</url-pattern>
  </servlet-mapping>
</web-app>
--------------------------------------------------------------------------------------------------
public class FrontController extends HttpServlet {
    // parameters shared with login.jsp.  These must exactly match the
    // property names in the JSP.
    public static final String USERNAME_PARAM = "username";
    public static final String PASSWORD_PARAM = "password";
    public static final String USERBEAN_ATTR = "userbean";
    public static final String CONTROLLER_PREFIX = "/pages";
   
    /**
     * Handle get requests by forwarding to a common processor
     */
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
        throws ServletException, IOException
    {
        process(request, response);
    }
   
    /**
     * Handle post requests by forwarding to a common processor
     */
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
        throws ServletException, IOException
    {
        process(request, response);
    }
   
    /**
     * The common processor method.  Check if this user is logged in or not.
     * If they are not, forward to the login page, otherwise forward to the
     * requested URL.
     */
   protected void process(HttpServletRequest request,
                           HttpServletResponse response)
        throws ServletException, IOException
    {
        // the default next page
        String nextPage = request.getPathInfo();
       
        // find userbean from session
        HttpSession session = request.getSession(true);
        UserBean userBean = (UserBean) session.getAttribute(USERBEAN_ATTR);
       
        if (userBean == null || !userBean.isLoggedIn()) {
            // read request parameters
            String username = request.getParameter(USERNAME_PARAM);
            String password = request.getParameter(PASSWORD_PARAM);
           
            // if the userbean doesn't exists, create it
            if (userBean == null) {
                userBean = UserBeanFactory.newInstance();
                session.setAttribute(USERBEAN_ATTR, userBean);
            }
           
            // record the username and password values
            userBean.setUsername(username);
            userBean.setPassword(password);
           
            // attempt to login
            boolean result = userBean.doLogin();
           
            // if we failed, redirect to the login page
            if (!result) {
                nextPage = "/login.jsp";
            }
        }
       
        // transfer control to the desired view
        RequestDispatcher dispatcher =
            getServletContext().getRequestDispatcher(nextPage);
        dispatcher.forward(request, response); 
    }   
}

No comments:

Post a Comment