Exceptions

In this part of the JEE tutorials we will work with exceptions.

An exception is a condition, often an error that causes a program to call a different routine. Exceptions should be divided in some logical groups. For example, we can divide exceptions into application exceptions and system exceptions. System exceptions react to low level system errors. Like memory shortage, lost connection etc. Application exceptions are higher level errors. They are usually less serious. They occur when some rules in application logic are broken. For example, when a user enters invalid data, an application exception is called.

In our next example, we will work with both kinds of exceptions. We will react to three kind of system exceptions and one kind of application exception. We will have system errors and application warnings. To inform user about exceptions, we will create message windows. This will be created using CSS and JavaScript. The example is quite complicated. Works on Firefox and Opera.

style.css
* { font-size: 12px; font-family: Verdana }

form { margin-top: 5%; }

input, textarea { border: 1px solid #ccc }

.message { 
  position: absolute;
  display: none;
  background: #577580;
  width: 235px;
  height: 150px;
  cursor: move;
  padding: 5px;
  color: white;
}

.header {
  font-weight: bolder;
  margin-bottom: 7px;
}

a#close { 
  position: absolute;
  display: block; 
  border: 1px solid #ccc; 
  padding: 2px;
  width: 60px;
  bottom: 20px;
  left: 88px; 
  text-decoration: none;
  font-weight: bolder;
  color: white;
}

This is a style sheet applied to our example. The .message class creates a message window for us. It is initially not visible. The .header class creates header of the message window. The close selector defines style for an anchor that will serve as our close button.

util.js
var savedTarget = null;
var orgCursor = null;  
var dragOK = false;     
var dragXoffset = 0;   
var dragYoffset = 0;  

function showError() {
    if (msg.style.display == 'block') {
        msg.style.display = 'none';
        msg.innerHTML = ''; 
    } else {
        msg.style.display = 'block';
        msg.innerHTML = '<b>Error</b><p>';
        var string = error + '</p><center>';
        string += '<a id="close" href="javascript:showError()">';
        string += 'close</a></center>';
        msg.innerHTML += string;
    }
}

function showWarning() {
    if (msg.style.display == 'block') {
        msg.style.display = 'none';
        msg.innerHTML = ''; 
    } else {
        msg.style.display = 'block';
        msg.innerHTML = '<b>Warning</b><p>';
        var string = warning + '</p><center>';
        string += '<a id="close" href="javascript:showWarning()">';
        string += 'close</a></center>';
        msg.innerHTML += string;
   }
}

function moveHandler(e){
    if (e == null) { e = window.event } 
    if (e.button <= 1 && dragOK){
        savedTarget.style.left = e.clientX - dragXoffset + 'px';
        savedTarget.style.top = e.clientY - dragYoffset + 'px';
        return false;
    }
}

function cleanup(e) {
    document.onmousemove = null;
    document.onmouseup = null;
    savedTarget.style.cursor = orgCursor;
    dragOK = false;
}

function dragHandler(e){
    var htype='-moz-grabbing';
    if (e == null) { e = window.event; htype = 'move';} 
    var target = e.target != null ? e.target : e.srcElement;
    orgCursor = target.style.cursor;

    if (target.className == "message") {
        savedTarget = target;
        target.style.cursor = htype;
        dragOK = true;
        dragXoffset = e.clientX - parseInt(msg.style.left);
        dragYoffset = e.clientY - parseInt(msg.style.top);
        document.onmousemove = moveHandler;
        document.onmouseup = cleanup;
        return false;
    }
}

document.onmousedown = dragHandler;

The util.js file will have most of the JavaScript code. The showWarning() function displays the application warning message window, the showError() displays the system error message window. The moveHandler(), cleanup() and dragHandler() functions enable to move the window with the mouse pointer. The JavaScript code is adapted from hunlock.com.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Exceptions</title>

<link rel="stylesheet" href="style.css" type="text/css">
<script src="util.js" type="text/javascript" ></script>

<script  type="text/javascript">

<%!
  String error;
  String warning;
  String okm;
%>

<%
  error = (String) request.getAttribute("ErrorMessage");
  warning = (String) request.getAttribute("Warning");
  okm = (String) request.getAttribute("OkMessage");
%>

  var error = "<%=error%>";
  var warning = "<%=warning%>";
  var okm = "<%=okm%>";
</script>

</head>

<body>
  <h2>Exceptions</h2>

  <center>
    <form action="ProcessServlet" >   
      <table>
        <tr>
          <td>From</td>
          <td><input type="text" name="from"></td>
        </tr>
        <tr>
          <td>To</td>
          <td><input type="text" name="to"></td>
        </tr>
        <tr>   
          <td>Subject</td>
          <td><input type="text" name="subject"></td>
        </tr>    
        <tr>
          <td>Message</td>
          <td><textarea cols="25" rows="8" name="message"></textarea></td>
        </tr>
      </table>
     <br>
     <input type="submit" value="submit">
   </form>
  </center>

<div id="messageID" class="message"></div>

<script  type="text/javascript">

  msg = document.getElementById('messageID');
  msg.style.top = (window.innerHeight-235) / 2;
  msg.style.left = (window.innerWidth-150) / 2;

</script>

<%
   if (error != null) {
%>

<script>
   showError();
</script>

<% } else if (warning != null) { %>
    <script  type="text/javascript">
         showWarning();
    </script>

<% } else if (okm != null) {
          out.print(okm);
   } %>

</body>
</html>

The index.jsp file creates an HTML form. It is also a place, where message windows will pop up.

var error = "<%=error%>";
var warning = "<%=warning%>";
var okm = "<%=okm%>";

Here we can see, how data from Java code is passed to JavaScript. These JavaScript variables will determine, which message window will appear on the screen.

<div id="messageID" class="message"></div>

The message window is a simple div tag. It is initially not visible. If an exception occurs, the div is made visible by the JavaScript code. The visibility of the tag is changed from none to block.

msg = document.getElementById('messageID');
msg.style.top = (window.innerHeight-235) / 2;
msg.style.left = (window.innerWidth-150) / 2;

This JavaScript code positions the window into the middle of the screen.

<%
   if (error != null) {
%>

<script>
   showError();
</script>

<% } else if (warning != null) { %>
    <script  type="text/javascript">
         showWarning();
    </script>

<% } else if (okm != null) {
          out.print(okm);
   } %>

This embedded Java code decides, which message window to display. If no exception occurs, we simply output All OK message.

Message window
Figure: Message window
Process.java
package com.zetcode;

import java.io.*;
import java.net.*;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.servlet.*;
import javax.servlet.http.*;
import com.mysql.jdbc.CommunicationsException;

public class Process extends HttpServlet {

  protected void processRequest(HttpServletRequest request, 
                                HttpServletResponse response)
          throws ServletException, IOException {

    response.setContentType("text/html;charset=UTF-8");

    Connection con;
    String url = "jdbc:mysql://localhost:3306/";

    try {

        this.testForm(request);
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection(url, "root", "");
        con.close();

    } catch (CommunicationsException ex) {
        request.setAttribute("ErrorMessage", 
                             "Cannot connect to database");

        RequestDispatcher dispatcher = 
                          request.getRequestDispatcher("/index.jsp");

        dispatcher.forward(request, response);

    } catch (SQLException ex) {
        request.setAttribute("ErrorMessage", ex.getMessage());

        RequestDispatcher dispatcher = 
                          request.getRequestDispatcher("/index.jsp");

        dispatcher.forward(request, response);

    } catch (ClassNotFoundException ex) {
        request.setAttribute("ErrorMessage", "MySQL driver not found");

        RequestDispatcher dispatcher = 
                          request.getRequestDispatcher("/index.jsp");

        dispatcher.forward(request, response);

    } catch (UserException ex) {
        request.setAttribute("Warning", ex.getMessage());

        RequestDispatcher dispatcher = 
                          request.getRequestDispatcher("/index.jsp");

        dispatcher.forward(request, response);
    }

    request.setAttribute("OkMessage", "All OK");
    RequestDispatcher dispatcher = 
                      request.getRequestDispatcher("/index.jsp");

    dispatcher.forward(request, response);
  }

  public void testForm(HttpServletRequest request) throws UserException {

    String from = (String) request.getParameter("from");
    String to = (String) request.getParameter("to");
    String subject = (String) request.getParameter("subject");
    String message = (String) request.getParameter("message");

    if (from.isEmpty()  || to.isEmpty() || 
             subject.isEmpty() || message.isEmpty() ) {
        throw new UserException("Form not correctly filled");
    }

  }

  protected void doGet(HttpServletRequest request, 
                       HttpServletResponse response)
          throws ServletException, IOException {
      processRequest(request, response);
  }

  protected void doPost(HttpServletRequest request, 
                        HttpServletResponse response)
          throws ServletException, IOException {
      processRequest(request, response);
  }
}

This is the servlet, where the exceptions arise. It does nothing in particular, only enables us the test various error conditions. The servlet will react to four different exceptions: CommunicationsException, SQLException, ClassNotFoundException and UserException. We can test the CommunicationsException by shutting down the MySQL database. The SQLException will arise, when we e.g. provide invalid password to the database user. If we do not include MySQL driver library, we will have the ClassNotFoundException. Finally, the UserExeption will occur, when at least one of the form parameters is empty.

sudo /etc/init.d/mysql stop

Here we stop the MySQL database server.

} catch (CommunicationsException ex) {
    request.setAttribute("ErrorMessage", 
                         "Cannot connect to database");

     RequestDispatcher dispatcher = 
                      request.getRequestDispatcher("/index.jsp");

    dispatcher.forward(request, response);
} 

This exception will react to the system error, caused by the lost connection. The code sets an attribute to the request and forwards back to the index.jsp page.

public void testForm(HttpServletRequest request) throws UserException {

  String from = (String) request.getParameter("from");
  String to = (String) request.getParameter("to");
  String subject = (String) request.getParameter("subject");
  String message = (String) request.getParameter("message");

  if (from.isEmpty()  || to.isEmpty() || 
           subject.isEmpty() || message.isEmpty() ) {
      throw new UserException("Form not correctly filled");
  }
}

The testForm() method will test if all parameters are set. If not, we throw an UserExeption.

UserException.java
package com.zetcode;


public class UserException extends Exception {

  public UserException(String msg) {
      super(msg);
  }

  public String getMessage() {
      return super.getMessage();
  }
}

The UserException is an application exception. This exception will cause the warning message windows.

In this chapter we have briefly mentioned exceptions.