Wednesday 23 May 2018

Controller Pattern example in Java

Controller pattern is related to web applications, where a controller is responsible for handling all the requests of a web application. There are many web frameworks like struts2, spring web mvc, yesod (Haskell) etc., are implementing control pattern.

A typical control pattern looks like below.


There is a handler that receives all the web requests. Depends on the request, it redirects the call to the process method of the specific Command class.

You will better understand this with an exampe.

Command.java
package com.sample.app.model;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class Command {
  private ServletContext context;
  private HttpServletRequest request;
  private HttpServletResponse response;

  public void init(ServletContext servletContext, HttpServletRequest servletRequest,
      HttpServletResponse servletResponse) {

    this.context = servletContext;
    this.request = servletRequest;
    this.response = servletResponse;
  }

  public abstract void process() throws ServletException, IOException;

  /**
   * Forward the request to correspondent target.
   * 
   * @param target
   * @throws ServletException
   * @throws IOException
   */
  protected void forward(String target) throws ServletException, IOException {
    target = String.format("/WEB-INF/jsp/%s.jsp", target);
    RequestDispatcher dispatcher = context.getRequestDispatcher(target);
    dispatcher.forward(request, response);
  }

}

DefaultCommand.java
package com.sample.app.model;

import java.io.IOException;

import javax.servlet.ServletException;

public class DefaultCommand extends Command {
  @Override
  public void process() throws ServletException, IOException {
    forward("default");
  }
}

HelloWorldCommand.java
package com.sample.app.model;

import java.io.IOException;

import javax.servlet.ServletException;

public class HelloWorldCommand extends Command {
  @Override
  public void process() throws ServletException, IOException {
    forward("hello");
  }
}

DispatcherServlet.java
package com.sample.app.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sample.app.model.Command;
import com.sample.app.model.DefaultCommand;
import com.sample.app.model.HelloWorldCommand;

/**
 * It is responsible for handling all the requests.
 * 
 * @author Krishna
 *
 */
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    Command command = getCommand(request);
    command.init(getServletContext(), request, response);
    command.process();
  }

  /**
   * Get the command to be executed from the request query parameter
   * <code>command</code>. If the query parameter <code>command</code> is null
   * (or) not match then {@link DefaultCommand} is returned.
   * 
   * @param request
   * @return
   */
  private static Command getCommand(HttpServletRequest request) {
    String command = request.getParameter("command");

    if (command == null) {
      return new DefaultCommand();
    }

    if ("HelloWorld".equals(command)) {
      return new HelloWorldCommand();
    }

    return new DefaultCommand();

  }
}


Create a folder 'jsp' under WEB-INF, create default.jsp, hello.jsp under WEB-INF/jsp folder.

default.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
  <h1>command may be null (or) not matched to one of the predefined commands (or) Welcome Page</h1>
</body>
</html>

hello.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">
  
  <servlet>
    <servlet-name>controllerServlet</servlet-name>
    <servlet-class>com.sample.app.servlet.DispatcherServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>controllerServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
</web-app>

Project structure looks like below.
Run the application on server.


By default, it opens default.jsp file.

Hit the below url.
http://localhost:8080/controllerPatternDemo/?command=HelloWorld

When you hit above url, request is redirected to HelloWorldCommand.java.



You may like

1 comment: