mardi 24 mars 2015

Servlet avec JSP et JDBC

We have provided a lot of tutorials on servlets in java, this tutorial is aimed to use all of those information to create a full-fledged web application with database connectivity and log4j integration for logging. I strongly recommend to check out following tutorials if you are not familiar with any of these. All of them contains sample project that you can download and run for understanding the core concepts of Servlet API.

Use Case

Develop a web application that should have following features.
  1. User can register and then login to the application.
  2. The users information should be maintained in database.
  3. Use standard logging framework log4j.
  4. The application should support session management, no JSPs should be visible without session. Users can logout anytime from the application.
  5. We should not show application and server details to user incase of any exception in application or other common errors like 404.
Once we have our basic application ready, we can move on to add other features.

Design Decisions

  1. Since login page is the entry point of application, we will have a simple login.html where user can enter their credentials; email and password. We can’t rely on javascript validations, so we will do server side validation and incase of missing information we will redirect user to login page with error details.
  2. We will have a register.html from where user can register to our application, we will provide it’s link in the login page for new user. User should provide email, password, name and country details for registration. If any information is missing, user will remain on same page with error message. If registration is successful, user will be forwarded to the login page with registration success information and they can use email and password to login.
  3. We will use MySql database for persisting user information. We will create a new database, user and Users table for our application. Since our application totally depends on Database Connection, we will create a servlet context listener to initialize the database connection and set it as context attribute for other servlets. We will keep DB configuration details configurable through deployment descriptor. We will also add MySql Java Connector jar to the application libraries.
  4. Since we want to use log4j and configure it properly before usage, we will utilize servlet context listener to configure log4j and keep the log4j configuration XML file location in web.xml init parameters. We will write our application logs in a separate log file dbexample.log for easier debugging.
  5. Incase of any exceptions like “Database Connection Error” or 404 errors, we want to present a useful page to user. We will utilize servlet exception handling and write our own Exception Handler servlet and configure it in deployment descriptor.
  6. Once the user logins successfully, we will create a session for the user and forward them to home.jsp where we will show basic information of the user. We will have a model class User that will store the user data into session. User home page also provide logout button that will invalidate the session and forward them to login page.
  7. We need to make sure all the JSPs and other resources are accessible only when user has a valid session, rather than keeping session validation login in all the resources, we will create a Servlet Filter for session validation and configure it in deployment descriptor.
  8. We will use Servlet 3.0 features for servlet configuration, listeners and filters rather than keeping all of these in deployment descriptor. We will use Eclipse for development and Tomcat 7 for deployment.
Based on above requirements and design decisions, we will create our dynamic web project whose project structure will look like below image.
servlet-example-project-database-log4j
Let’s understand each one of the components and understand their implementation.

Database Setup

We will use below MySql script for new Database, User and Table setup to be used in our application.
MySql_Setup.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- login with root to create user, DB and table and provide grants
  
create user 'pankaj'@'localhost' identified by 'pankaj123';
grant all on *.* to 'pankaj'@'localhost' identified by 'pankaj123';
create database UserDB;
use UserDB;
CREATE TABLE `Users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '',
  `email` varchar(20) NOT NULL DEFAULT '',
  `country` varchar(20) DEFAULT 'USA',
  `password` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Login and Registration HTML Pages

Login and Registration HTML pages are simple pages with form to submit the user information, their code looks like below.
login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="US-ASCII">
<title>Login Page</title>
</head>
<body>
<h3>Login with email and password</h3>
<form action="Login" method="post">
<strong>User Email</strong>:<input type="text" name="email"><br>
<strong>Password</strong>:<input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
<br>
If you are new user, please <a href="register.html">register</a>.
</body>
</html>
register.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<meta charset="US-ASCII">
<title>Register Page</title>
</head>
<body>
<h3>Provide all the fields for registration.</h3>
<form action="Register" method="post">
<strong>Email ID</strong>:<input type="text" name="email"><br>
<strong>Password</strong>:<input type="password" name="password"><br>
<strong>Name</strong>:<input type="text" name="name"><br>
<strong>Country</strong>:<input type="text" name="country"><br>
<input type="submit" value="Register">
</form>
<br>
If you are registered user, please <a href="login.html">login</a>.
</body>
</html>

Deployment Descriptor and log4j configuration

We will have log4j configuration file inside WEB-INF folder and it will be packaged with the application WAR file.
log4j.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
    debug="false">
    <appender name="dbexample" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="${catalina.home}/logs/dbexample.log"/>
        <param name="Append"            value="true" />
        <param name="ImmediateFlush"    value="true" />
        <param name="MaxFileSize"       value="20MB" />
        <param name="MaxBackupIndex"    value="10" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n" />
        </layout>
    </appender>
     
    <logger name="com.journaldev" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="dbexample"/>
    </logger>
     
    <root>
        <level value="debug" />
        <appender-ref ref="dbexample" />
    </root>
     
</log4j:configuration>
Our deployment descriptor (web.xml) looks like below.
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletDBLog4jExample</display-name>
  <welcome-file-list>
    <welcome-file>login.html</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>dbUser</param-name>
    <param-value>pankaj</param-value>
  </context-param>
  <context-param>
    <param-name>dbPassword</param-name>
    <param-value>pankaj123</param-value>
  </context-param>
  <context-param>
    <param-name>dbURL</param-name>
    <param-value>jdbc:mysql://localhost:3306/UserDB</param-value>
  </context-param>
  <context-param>
    <param-name>log4j-config</param-name>
    <param-value>WEB-INF/log4j.xml</param-value>
  </context-param>
   
  <error-page>
    <error-code>404</error-code>
    <location>/AppErrorHandler</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/AppErrorHandler</location>
  </error-page>
   
  <filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>com.journaldev.servlet.filters.AuthenticationFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
   
</web-app>
Notice following points in the web.xml configuration.
  1. login.html is provided welcome file in the welcome files list.
  2. Database connection parameters are made configurable and kept as servlet context init params.
  3. log4j configuration file location is also configurable and relative location is provided as context init param.
  4. Our custom exception handler servlet AppErrorHandler is configured to handle all the exceptions thrown by our application code and 404 errors.
  5. AuthenticationFilter is configured to filter all the incoming requests to the application, this is the place where we will have session validation logic.

Model Classes and Database Connection Manager Class

User.java is a simple java bean that will hold the user information as session attribute.
User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.journaldev.util;
import java.io.Serializable;
public class User implements Serializable{
     
    private static final long serialVersionUID = 6297385302078200511L;
     
    private String name;
    private String email;
    private int id;
    private String country;
     
    public User(String nm, String em, String country, int i){
        this.name=nm;
        this.id=i;
        this.country=country;
        this.email=em;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getName() {
        return name;
    }
    public String getEmail() {
        return email;
    }
    public int getId() {
        return id;
    }
    public String getCountry() {
        return country;
    }
     
    @Override
    public String toString(){
        return "Name="+this.name+", Email="+this.email+", Country="+this.country;
    }
}
DBConnectionManager.java is the utility class for MySql database connection and it has a method that returns the connection object. We will use this class for database connection and then set the connection object to servlet context attribute that other servlets can use.
DBConnectionManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.journaldev.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnectionManager {
    private Connection connection;
     
    public DBConnectionManager(String dbURL, String user, String pwd) throws ClassNotFoundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver");
        this.connection = DriverManager.getConnection(dbURL, user, pwd);
    }
     
    public Connection getConnection(){
        return this.connection;
    }
}

Servlet Context Listener

AppContextListener.java is the servlet context listener implementation that will initialize the Database connection when application context is initialized and it also configures the log4j using it’s configuration xml file. Notice the use of context init params for DB connection and log4j configuration.
When context will be destroyed, we are closing database connection in contextDestroyed() method.
Since we are using Servlet 3, we don’t need to configure it in web.xml and we just need to annotate it with @WebListener annotation.
AppContextListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.journaldev.servlet.listeners;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
import com.journaldev.util.DBConnectionManager;
@WebListener
public class AppContextListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext ctx = servletContextEvent.getServletContext();
         
        //initialize DB Connection
        String dbURL = ctx.getInitParameter("dbURL");
        String user = ctx.getInitParameter("dbUser");
        String pwd = ctx.getInitParameter("dbPassword");
         
        try {
            DBConnectionManager connectionManager = new DBConnectionManager(dbURL, user, pwd);
            ctx.setAttribute("DBConnection", connectionManager.getConnection());
            System.out.println("DB Connection initialized successfully.");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
         
        //initialize log4j
        String log4jConfig = ctx.getInitParameter("log4j-config");
        if(log4jConfig == null){
            System.err.println("No log4j-config init param, initializing log4j with BasicConfigurator");
            BasicConfigurator.configure();
        }else {
            String webAppPath = ctx.getRealPath("/");
            String log4jProp = webAppPath + log4jConfig;
            File log4jConfigFile = new File(log4jProp);
            if (log4jConfigFile.exists()) {
                System.out.println("Initializing log4j with: " + log4jProp);
                DOMConfigurator.configure(log4jProp);
            } else {
                System.err.println(log4jProp + " file not found, initializing log4j with BasicConfigurator");
                BasicConfigurator.configure();
            }
        }
        System.out.println("log4j configured properly");
    }
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        Connection con = (Connection) servletContextEvent.getServletContext().getAttribute("DBConnection");
        try {
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
     
}

Exception and Error Handler

AppErrorHandler.java is our application exception handler servlet configured in deployment descriptor, it provides useful information to the user incase of 404 errors or application level exceptions and provide them hyperlink to go to login page of application.
AppErrorHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.journaldev.servlet.errorhandler;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/AppErrorHandler")
public class AppErrorHandler extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processError(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processError(request, response);
    }
     
    private void processError(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        // Analyze the servlet exception
        Throwable throwable = (Throwable) request
                .getAttribute("javax.servlet.error.exception");
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        String servletName = (String) request
                .getAttribute("javax.servlet.error.servlet_name");
        if (servletName == null) {
            servletName = "Unknown";
        }
        String requestUri = (String) request
                .getAttribute("javax.servlet.error.request_uri");
        if (requestUri == null) {
            requestUri = "Unknown";
        }
         
        // Set response content type
          response.setContentType("text/html");
      
          PrintWriter out = response.getWriter();
          out.write("<html><head><title>Exception/Error Details</title></head><body>");
          if(statusCode != 500){
              out.write("<h3>Error Details</h3>");
              out.write("<strong>Status Code</strong>:"+statusCode+"<br>");
              out.write("<strong>Requested URI</strong>:"+requestUri);
          }else{
              out.write("<h3>Exception Details</h3>");
              out.write("<ul><li>Servlet Name:"+servletName+"</li>");
              out.write("<li>Exception Name:"+throwable.getClass().getName()+"</li>");
              out.write("<li>Requested URI:"+requestUri+"</li>");
              out.write("<li>Exception Message:"+throwable.getMessage()+"</li>");
              out.write("</ul>");
          }
           
          out.write("<br><br>");
          out.write("<a href=\"login.html\">Login Page</a>");
          out.write("</body></html>");
    }
}

Servlet Filter

AuthenticationFilter.java is our Filter implementation and we are validating user session here.
AuthenticationFilter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.journaldev.servlet.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
@WebFilter("/AuthenticationFilter")
public class AuthenticationFilter implements Filter {
    private Logger logger = Logger.getLogger(AuthenticationFilter.class);
     
    public void init(FilterConfig fConfig) throws ServletException {
        logger.info("AuthenticationFilter initialized");
    }
     
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
         
        String uri = req.getRequestURI();
        logger.info("Requested Resource::"+uri);
         
        HttpSession session = req.getSession(false);
         
        if(session == null && !(uri.endsWith("html") || uri.endsWith("Login") || uri.endsWith("Register"))){
            logger.error("Unauthorized access request");
            res.sendRedirect("login.html");
        }else{
            // pass the request along the filter chain
            chain.doFilter(request, response);
        }
         
         
    }
    public void destroy() {
        //close any resources here
    }
}
Notice the use of @WebFilter annotation, we can also provide URL Patterns for filter here but sometimes it’s good to have in web.xml to easily disable the filters.

Servlet Classes

LoginServlet resource is used to validate the user input for login and forward them to home page or incase of missing data, provide useful information to user.
LoginServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.journaldev.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import com.journaldev.util.User;
@WebServlet(name = "Login", urlPatterns = { "/Login" })
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    static Logger logger = Logger.getLogger(LoginServlet.class);
     
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        String errorMsg = null;
        if(email == null || email.equals("")){
            errorMsg ="User Email can't be null or empty";
        }
        if(password == null || password.equals("")){
            errorMsg = "Password can't be null or empty";
        }
         
        if(errorMsg != null){
            RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
            PrintWriter out= response.getWriter();
            out.println("<font color=red>"+errorMsg+"</font>");
            rd.include(request, response);
        }else{
         
        Connection con = (Connection) getServletContext().getAttribute("DBConnection");
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement("select id, name, email,country from Users where email=? and password=? limit 1");
            ps.setString(1, email);
            ps.setString(2, password);
            rs = ps.executeQuery();
             
            if(rs != null && rs.next()){
                 
                User user = new User(rs.getString("name"), rs.getString("email"), rs.getString("country"), rs.getInt("id"));
                logger.info("User found with details="+user);
                HttpSession session = request.getSession();
                session.setAttribute("User", user);
                response.sendRedirect("home.jsp");;
            }else{
                RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
                PrintWriter out= response.getWriter();
                logger.error("User not found with email="+email);
                out.println("<font color=red>No user found with given email id, please register first.</font>");
                rd.include(request, response);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            logger.error("Database connection problem");
            throw new ServletException("DB Connection problem.");
        }finally{
            try {
                rs.close();
                ps.close();
            } catch (SQLException e) {
                logger.error("SQLException in closing PreparedStatement or ResultSet");;
            }
             
        }
        }
    }
}
LogoutServlet is simple and invalidates the user session and forward them to login page.
LogoutServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.journaldev.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
@WebServlet(name = "Logout", urlPatterns = { "/Logout" })
public class LogoutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    static Logger logger = Logger.getLogger(LogoutServlet.class);
        
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
        for(Cookie cookie : cookies){
            if(cookie.getName().equals("JSESSIONID")){
                logger.info("JSESSIONID="+cookie.getValue());
                break;
            }
        }
        }
        //invalidate the session if exists
        HttpSession session = request.getSession(false);
        logger.info("User="+session.getAttribute("User"));
        if(session != null){
            session.invalidate();
        }
        response.sendRedirect("login.html");
    }
}
RegisterServlet is used by users to register to the application and then forward them to login page with registration success message.
RegisterServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.journaldev.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
@WebServlet(name = "Register", urlPatterns = { "/Register" })
public class RegisterServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    static Logger logger = Logger.getLogger(RegisterServlet.class);
     
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        String name = request.getParameter("name");
        String country = request.getParameter("country");
        String errorMsg = null;
        if(email == null || email.equals("")){
            errorMsg = "Email ID can't be null or empty.";
        }
        if(password == null || password.equals("")){
            errorMsg = "Password can't be null or empty.";
        }
        if(name == null || name.equals("")){
            errorMsg = "Name can't be null or empty.";
        }
        if(country == null || country.equals("")){
            errorMsg = "Country can't be null or empty.";
        }
         
        if(errorMsg != null){
            RequestDispatcher rd = getServletContext().getRequestDispatcher("/register.html");
            PrintWriter out= response.getWriter();
            out.println("<font color=red>"+errorMsg+"</font>");
            rd.include(request, response);
        }else{
         
        Connection con = (Connection) getServletContext().getAttribute("DBConnection");
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement("insert into Users(name,email,country, password) values (?,?,?,?)");
            ps.setString(1, name);
            ps.setString(2, email);
            ps.setString(3, country);
            ps.setString(4, password);
             
            ps.execute();
             
            logger.info("User registered with email="+email);
             
            //forward to login page to login
            RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
            PrintWriter out= response.getWriter();
            out.println("<font color=green>Registration successful, please login below.</font>");
            rd.include(request, response);
        } catch (SQLException e) {
            e.printStackTrace();
            logger.error("Database connection problem");
            throw new ServletException("DB Connection problem.");
        }finally{
            try {
                ps.close();
            } catch (SQLException e) {
                logger.error("SQLException in closing PreparedStatement");
            }
        }
        }
         
    }
}

Home JSP Page

home.jsp is the home page for user after successful login, we are just showing some user information here and providing them option to logout.
home.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@page import="com.journaldev.util.User"%>
<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<!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=US-ASCII">
<title>Home Page</title>
</head>
<body>
<%User user = (User) session.getAttribute("User"); %>
<h3>Hi <%=user.getName() %></h3>
<strong>Your Email</strong>: <%=user.getEmail() %><br>
<strong>Your Country</strong>: <%=user.getCountry() %><br>
<br>
<form action="Logout" method="post">
<input type="submit" value="Logout" >
</form>
</body>
</html>
The JSP page still contains a lot of java code because we are not using JSP tags, we will look into this in JSP tutorials. As of now please bear with this.

Run the Application

Our application is ready for execution, I would suggest to export it as WAR file and then deploy to tomcat rather than deploying it directly to Tomcat server from Eclipse so that you can easily look into the log4j log file for debugging.
Some sample execution pages are shown in below images.
User Registration Page:
registration-page
Registration Success Page:
registration-success
Login Page:
login-page
User Home Page:
home-page
404 Error Page:
404-error-page
Input Validation Error Page:
input-validation-error-page
log4j Log File:
dbexample.log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0    [localhost-startStop-1] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - AuthenticationFilter initialized
1    [localhost-startStop-1] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - AuthenticationFilter initialized
37689 [http-bio-8080-exec-3] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/
37689 [http-bio-8080-exec-3] ERROR com.journaldev.servlet.filters.AuthenticationFilter  - Unauthorized access request
37693 [http-bio-8080-exec-4] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/login.html
51844 [http-bio-8080-exec-5] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/register.html
77818 [http-bio-8080-exec-7] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/Login
77835 [http-bio-8080-exec-7] INFO  com.journaldev.servlet.LoginServlet  - User found with details=Name=Pankaj Kumar, Email=pankaj@apple.com, Country=India
77840 [http-bio-8080-exec-8] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/home.jsp
98251 [http-bio-8080-exec-9] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/Logout
98251 [http-bio-8080-exec-9] INFO  com.journaldev.servlet.LogoutServlet  - JSESSIONID=367DE255789AC02F7C0E0298B825877C
98251 [http-bio-8080-exec-9] INFO  com.journaldev.servlet.LogoutServlet  - User=Name=Pankaj Kumar, Email=pankaj@apple.com, Country=India
98254 [http-bio-8080-exec-10] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/login.html
109516 [http-bio-8080-exec-10] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/Register
109517 [http-bio-8080-exec-10] INFO  com.journaldev.servlet.RegisterServlet  - User registered with email=abc@abc.com
127848 [http-bio-8080-exec-10] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/Login
223055 [http-bio-8080-exec-2] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/Login
223056 [http-bio-8080-exec-2] INFO  com.journaldev.servlet.LoginServlet  - User found with details=Name=Pankaj Kumar, Email=pankaj@apple.com, Country=India
223059 [http-bio-8080-exec-2] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/home.jsp
231931 [http-bio-8080-exec-2] INFO  com.journaldev.servlet.filters.AuthenticationFilter  - Requested Resource::/ServletDBLog4jExample/invalidurl.jsp

Download Resources

implementer JSP Servlet MVC code Project


Create a dynamic web project
For that go to
FileànewàDynamic web project
Fill project details and say next .next and finish and make sure generate web.xml is checked
Now time to create a servlet
For that right click on create project “SeverletJSPExapmle” ànewèservlet and give entries
Now in next we need to edit the URL mapping to make it more convenient because we are going to use this to access our servlet so I made them all small letter
Now say next and next and check the option  . Here we removed the dopost and doget and selected services. As they do same job
And say finish
Now eclipse has created  ServletExample.java file for us in source directory and added following entry in web.xml  (WebContentàWEB-INFàweb.xml)
<servlet>
    <description></description>
    <display-name>ServletExample</display-name>
    <servlet-name>ServletExample</servlet-name>
    <servlet-class>com.example.tutorial.ServletExample</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletExample</servlet-name>
    <url-pattern>/servletexample</url-pattern>
  </servlet-mapping>
Now we will do some coding to interact our servlet with web browser
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // it will get object to write string in browser
            PrintWriter out = response.getWriter();
            out.println("hello Java!!!");
      }
Now run this code by doing right click in ServletExample.Java file and select run AsàRun On Server
You will see your string in URL
You might need to restart once that tomcat server
Now time to some more advance programming by capturing request from JSP (xhtml) pages and sending response back
To create jsp page browse to webcontent folder  and select newà Jsp page
Now give JSP page name say index.jsp and click next and in next screen select  “New JSP file (xhtml)” as JSP template and say Finish
Now index.jsp page get created. To deploy the jsp page you need to right click on page and say new->run as-> on application sever
Here we will create a jsp page having a form with 2 input field firstname and lastname with a submit button
We will fill jsp form and capture that request in serverlet and display in web browser
We already created index.jsp page now time to add some code
<body>
<form action="servletexample" method="post" >
       <table border="0" >
             <tr>
                    <td>First Name: </td> <td><input type="text" name="firstname"/></td>
             </tr>
             <tr>
                    <td>Last Name: </td> <td><input type="text" name ="lastname"/></td>
             </tr>
             <tr>
                    <td colspan="2"><input type = "submit" value = "Submit"/></td>
             </tr>
       </table>
</form>
Here <form> to is to create a form
action= <give your servlet name (Not serverlet class name)> this is the place which setup binding between servlet and jsp
method = post means user will post below information as request from browse
<table> tag use to give good look and provide formatting
<tr> tag is to separate rows in table
<td> tag is for column
<td colspan="2"> means we are combining two column into one
Earlier we added very simple out put string in our ServletExample.java class here we are going to add some more code to capture JSP from request and display them in browser
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             // Get servlet object which will display any string in browser
             PrintWriter out = response.getWriter();
             // Capture request from JSP page where input field name ="firstname"
             String fname = request.getParameter("firstname");
             // Capture request from JSP page where input field name ="lastname"
             String lname = request.getParameter("lastname");
             // Display string in web browser
             out.println(fname+" "+lname);
             //out.println("hello Java!!!");
            
       }
As JSP page should not be directly accessible to user so we will use  RequestDispatcher to hide our jsp page.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//it will hide the jsp page link in URL and just show servlet URL it will use MVC model
//here we have add if condition so that jsp form will show if any input is null
 if(request.getParameter("firstname")==null || request.getParameter("lastname")==null ){
getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
}
// Capture request from JSP page where input field name ="firstname"
String fname = request.getParameter("firstname");
// Capture request from JSP page where input field name ="lastname"
String lname = request.getParameter("lastname");
// Display string in web browser
out.println(fname+" "+lname);
}
Now you can see index.jsp page from URL:
Now we will create one more jsp page output.jsp which will capture input entered in earlier created page  index.jsp . This page will display  the output in web. Again we will hind both JSP pages from user using   RequestDispatcher . Actually it will provide MVC model where web page will be display as per input . Like if any input first name or last name will be null then always index.jsp page will populate and once both entries will be there then output.jsp page will display first name and last name
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//it will hide the jsp page link in URL and just show servlet URL it will use MVC model
//here we have add if condition so that jsp form will show if any input is null
//we will create one more jsp page to show the output called output.jsp
if(request.getParameter("firstname")==null || request.getParameter("lastname")==null ){
getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
}
// Capture request from JSP page where input field name ="firstname"
String fname = request.getParameter("firstname");
// Capture request from JSP page where input field name ="lastname"
String lname = request.getParameter("lastname");
// Display string in web browser
out.println(fname+" "+lname);
//code to display output in output.jsp page
//Here we are setting attribute in request which is output.jsp page is fetching
request.setAttribute("firstname", fname);
request.setAttribute("lastname", lname);
//Get output.jsp page using request dispatcher
getServletContext().getRequestDispatcher("/output.jsp").forward(request, response);
}
Output.jsp:
<title>JSP Output</title>
</head>
<body>
      <h1>Your First and Last name is:</h1>
      <%
      String ffname= (String)request.getAttribute("firstname");
      String llname = (String)request.getAttribute("lastname");
      out.print(ffname+" "+llname);
      %>
</body>
<h1> tag we use for heading as it is in normal html
<% %> this tag use to write java scriptlet
Here you will notice we are getting both string from request.getAttribute which is set by servlet code. So servlet java code is working as mediocre which pop up and took input from index.jsp  after that set value to request object which is accessed by output.jsp and use in Java script and again servlet java code invoke the output.jsp
Now if you will say run as server from ServletExample.java then first index.jsp page will display but you will notice URL is :
You will give first name and last name and again output.jsp page URL will be : http://localhost:8081/ServerletsJSPExample/servletexample instead of http://localhost:8081/ServerletsJSPExample/output.jsp
It is because of request dispatcher you can see MVC model here.
The other way is capturing request in servlet by directly passing the value through URL like:
  
Complete working code:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // it will get object to write string in browser
            PrintWriter out = response.getWriter();
            if(request.getParameter("firstname") == null || request.getParameter("lastname")==null)
            {
                  getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
                  return;
            }
            String fname = request.getParameter("firstname");
            String lname = request.getParameter("lastname");
           
            request.setAttribute("firstname", fname);
            request.setAttribute( "lastname",lname);
           
            getServletContext().getRequestDispatcher("/output.jsp").forward(request, response);
           
            }
We can also use variable define in  java scriptlet in HTML tag to do more formatting and in our example we will print first name and lastname in HTML table in output.jsp using below code in body
<body>
      <h1>Your First and Last name is:</h1>
      <%
      String ffname= (String)request.getAttribute("firstname");
      String llname = (String)request.getAttribute("lastname");
      %>
     
      <table>
            <tr>
                  <td>First Name:</td><td><%=ffname %></td>
            </tr>
            <tr>
                  <td>Last Name:</td><td><%= llname%></td>
            </tr>
      </table>
</body>
Now the output will look like