• 9.0 Exceptions

    Exceptions (named from the term 'exceptional event') are event that occur during the execution of a program that interrupt the flow of the programs normal operation, i.e. when a serious problem occurs, the program will throw an exception. Throwing an exception creates an exception object which is handed over to the runtime system. Exception objects details the type of error, location and state of the program. Runtime system attempts to handle exception by looking in the call stack and searching through the ordered list of methods invoked prior to exception the being thrown in order to get to the method where the error occurs. The is achieved by sreaching the methods for a block of code that can handle the exception, known as the exception handler. When the appropriate exception handler has been found and object is passed to the exception handling block.

    java.io.FileNotFoundException: modulesa.txt (The system cannot find the file specified)
            at java.io.FileInputStream.open0(Native Method)
            at java.io.FileInputStream.open(FileInputStream.java:195)
            at java.io.FileInputStream.<init>(FileInputStream.java:138)
            at java.io.FileInputStream.<init>(FileInputStream.java:93)
            at java.io.FileReader.<init>(FileReader.java:58)
            at students.dao.textdao.textModuleDAO.loadModules(TextModuleDAO.java:32)
            at students.Students.loadModules(Students.java:99)
            at students.Students.main(Students.java:31)
    
    
    exception Diagram

    The exception handler catches the exception and provides code to resolve error or provides a graceful way for the program to stop execution. If no exception handler is found then runtime system terminates the execution with a generic error message.

    🔗 Class Exception
    🔗 Class FileNotFoundException

    Kinds Of Exceptions

    Checked exception
    Conditions that the application should detect and be able to recover from
    e.g. attempting to open a non-existent file
    Error exception
    Circumstances external to program which program is not expected to recover from
    e.g. disk fault
    Runtime exception (unchecked)
    Internal to application but program not expected to recover from
    e.g. logic errors
    Not checked at compile time

    Throw statements

    Single Throwable object
    throw someThrowableObject;
    Error class:
    Java virtual machine throws an error
    typically programs do not catch or throw Errors
    Exception class:
    Problem has occurred which can be recovered from
    Also for actions to allow a program to die gracefully
    Runtime exceptions reserved for misuse of APIs

    The Throwable Class

    The Throwable Class

    public static int readInt(String prompt, int max, int min) {
       if (min > max)
          throw
            new IllegalArgumentException(
                   String.format("min (%d) should be <= max (%", min, max)
     );                 
    
  • 9.1 Try & Catch

    Code which may throw an exception should be placed in a "try" block and exception handling code in a "catch" block. A try block contains blocks of code in which an exception might occur, a catch block handles any exceptions that occur. Catch blocks are identified with one or more exceptions and try blocks can have more than one catch block if different exceptions have different error handling codes.

    try { … }
    catch (ExceptionType name) { … }
    catch (ExceptionType name) { … }
    

    "ExceptionType" must be a class that descends from "Throwable". Handler code is executed when the runtime system detects an exception is thrown and the exception object is passed into the catch argument. A match is made if the thrown object can legally be assigned to the exception handler's argument. Exception handlers can provide a variety of code including logging exception details, prompting the user to re-enter input, undo set of actions. From Java 7 onwards a catch block can be associated with more than one exception, e.g. catch (IOException|SQLException ex).

    Finally block

    A "finally" statement must be associated with a try statement, i.e. if you want to use a finally there has to be a try statement. The finally statement will execute whether exception occurs or not unless program is terminated during exception handling. Finally statements are used to provide actions that need to take place whether an exception has occurred or not, e.g. closing a stream.

    } finally { 
       if (br != null)
           // might throw exception
           br.close(); 
    }
    

    Try-with-resources

    Try with resources can be used when a resource is being created which must be released after an action has taken place, e.g. java.lang.AutoCloseable. They ensures the resource is released once try block has finished executing.

    static String readFirstLineFromFile(String path)
                                 throws IOException {
       try (BufferedReader br = new 
              BufferedReader(new FileReader(path))) {
          return br.readLine(); 
       }
    } 
    

    Try catch statements allow us to separate error handling code and classifying error types into groups. They also let us propagate errors up the call stack which is the best place to handle errors in the chain of method calls.
  • 9.2 Examples

    NumberFormatException

    try {
       inputNumber = Integer.parseInt(input.nextLine());
       if (inputNumber < min || inputNumber > max) {
          inputError = true;
          System.out.println("Number out of range");                        
       } 
    } catch (NumberFormatException e) {
        inputError = true;
        System.out.println("Not a valid number"); 
    } 
    

    FileNotFoundException - Text

    public List<Student> loadStudents(Path path)
                                       throws FileNotFoundException {
       List<Student> students = new ArrayList<>();
       BufferedReader br =
                 new BufferedReader(new FileReader(path.toString()));
       
       String line = br.readLine(); 
       while(line!=null){
          String str = line.replaceAll("\"", "");
          temp=str.split(Character.toString(DELIMITER));
                    
          student = new Student(studentID, …, programmeCode);
          students.add(student);
          line = br.readLine();
       } 
       br.close();
    

    FileNotFoundException - Cont

    public static List<Student> loadStudents() {
       List<Student> students=null;
       Path path=Paths.get("studentsa.txt");
       try {
         TextDAOFactory daoFactory = 
             (TextDAOFactory) DAOFactory.getDAOFactory(1);
         TextStudentDAO dao = (TextStudentDAO) 
              daoFactory.getStudentDAO();
         students = dao.loadStudents(path);   
       } 
       catch (FileNotFoundException e) {
         System.out.println("Students File Not Found");
       }
    

    FileNotFoundException - Cont

    public List<Module> loadModules(Path path) {
       List<Module> modules = new ArrayList<>();   
       try (BufferedReader br =
            new BufferedReader(
                new FileReader(path.toString())
                )
            ) {
          … 
          br.close();
       } catch (FileNotFoundException ex) {
         … 
       } catch (IOException ex) {
         … 
       } 
    

    run:
    Students File No Found
    
    1. List Students  2. List Modules  3. Quit
    Nov 18, 2015 1:44:46 PM students.dao.textdao.textModuleDAO loadModules
    SEVERE: null
    java.io.FileNotFoundException: modulesa.txt (The system cannot find the file specified)
            at java.io.FileInputStream.open0(native Method)
            at java.io.FileInputStream.open(FileInputStream.java:195)
            at java.io.FileInputStream.<init>(FileInputStream.java:138)
            at java.io.FileInputStream.<init>(FileInputStream.java:93)
            at java.io.FileReader.<init>(FileReader.java:58)
            at students.dao.textdao.TextModuleDAO.loadModules(TextModuleDAO.java:32)
            at students.Students.loadModules(Students.java:99)
            at students.Students.main(Students.java:31)   
    
    Enter choice: 3
    Quitting
    BUILD SUCCESSFUL (total time: 16 seconds)
    

    “Throw early, catch late” - In the Students case, the exception is bubbled up the call stack until it reaches the application allowing the user to re-enter the file name. In the Modules case, the exception is caught in the DAO load method which can do nothing but log the error.

    Note the stack trace of method calls
  • 9.3 Assertions

    Assertions are statements that let you test something you know about your program. For example if you write a method that calculates speed of a car then you might want to assert that the speed is not greater than the top speed of the car. Assertions allow us to program defensively and they aid debugging. Document things you know (believe) to be true at a point in the code, things that if they are not true then there is something is wrong with the program. Assertions are errors not exceptions, i.e. the code will still work but can produce incorrect outcomes. As such there are no throws or try-catch statement. Assertions statement asserts a condition is true, if the condition is false the an AssertionError object is created and program terminates. Assertion checking is turned on through enabling assertions: –enableassertions or –ea. Assertions take two forms:

    Form 1:
    assert condition;
    Boolean expression
    If false AssertionError thrown
    No detail message

    Form 2:
    assert expression1:expression2
    expression1 is boolean
    expression2 produces a value (not void)
    System passes value to AssertionError constructor which uses it in creating a message detail string

    Screenshot

    Example

    while(line!=null){
       String str = line.replaceAll("\"", "");
       temp=str.split(Character.toString(DELIMITER));            
       try {
          studentID = Integer.parseInt(temp[0]);
       } catch (NumberFormatException e) {
         System.out.println(e);
         studentID = 0;
       } 
       assert studentID>0;
    

    Screenshot of students.txt file Example 1
    run:
    java.lang.NumberFormatException: For input string: "2a"
    Exception in thread "main" java.lang.AssertionError
            at students.dao.textdao.TextStudentsDAO.loadStudents(TextStudentDAO.java:50)
            at students.Students.loadStudents(Students.java:64)
            at students.Students.main(Students.java:30)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)
    
    Screenshot of students.txt file Example 2
    run:
    Exception in thread "main" java.lang.AssertionError
            at students.dao.textdao.TextStudentsDAO.loadStudents(TextStudentDAO.java:50)
            at students.Students.loadStudents(Students.java:64)
            at students.Students.main(Students.java:30)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)
    
  • 9.4 Internal Invariants

    An invariant is something that should always be true, i.e. the properties and relationships (Internal Invariants) that remain stable though the life-span of a class. Assertion can be used to check condition has been met correctly and check a value is correct at a specified point in the execution, e.g. assert studentID>0;

    run:
    Exception in thread "main" java.lang.AssertionError
            at students.dao.textdao.TextStudentsDAO.loadStudents(TextStudentDAO.java:50)
            at students.Students.loadStudents(Students.java:64)
            at students.Students.main(Students.java:30)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)
    

    Control Flow Invariants

    Control Flow Invariants are used to mark code that should never be reached, i.e. previous options should cover all cases. e.g. default option in switch

    public static DAOFactory getDAOFactory(int whichFactory) {
       switch (whichFactory) {
          case TEXT:
             return new TextDAOFactory();
             // case OBJECT:
             //    return new ObjectDAOFactory();
          default: 
             assert false : "DAO Type: " + whichFactory;
             return null;
       } 
    } 
    

    run:
    Exception in thread "main" java.lang.AssertionError DAO Type: 2
            at students.dao.DAOFactory.getDAOFactory(DAOFactory.java:39)
            at students.Students.loadModules(Students.java:97)
            at students.Students.main(Students.java:31)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)
    

    Class Invariants

    An object must satisfy a condition in order to be a valid member.

    public boolean equals(Object o) {
      assert ((o instanceof Student) && (o != null));
      if (o instanceof Student) {
         Student s = (Student)o;
         return  
           s.getStudentId() == getStudentId() &&
           s.getStudentName().equals(getStudentName()) &&
           s.getProgrammeCode().equals(getProgrammeCode());
      } else {
         return false;
      } 
    }
    

    Example:

    Student student1 = students.get(0);
    Student student2 = null;
    if (student1.equals(student2)) …
    
    Student student1 = students.get(0);
    Object module = modules.get(0);
    if (student1 == module) …
    

    run:
    Exception in thread "main" java.lang.AssertionError
            at students.Student.equals(Student.java:91)
            at students.Students.main(Students.java:59)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 3 seconds)
    

    Preconditions and Postconditions

    The assert construct is not a full-blown design-by-contract (assure every component of a system lives up to its expectations) facility. However they can support an informal design-by-contract style of programming as the assert construct allows us to validate preconditions (something that must be true when a method is called) and postconditions (something that must be true after a method finishes successfully).

    Preconditions on a public method should be explicitly checked, however, do not use assertions for parameters of a public method. A private method can use assert to confirm valid parameters:

    private void setInterval(int interval) { 
      assert interval > 0 && interval <= 100; 
      ... 
      // Set the interval 
    }
    

    We can test postcondition with assertions in both public and nonpublic methods:

    public int generateRandomValue) {
      ... // generate random value
      assert num > 0 && num <=10;
      return num; 
    }
    

    Assertions vs Exceptions Overview

    Exception
    tells user something wrong
    deal with problems
    Assertion
    documents something about program
    state true things
    documentation not just error checking
  • 9.5 Logging

    One of the most common debugging aids is the ordinary print statement, System.out.println. This is used to output values of variables & messages indicating which code is being executed. Logging facilities are intended to formalize this by directing debugging information to a stream typically: System.err (can save to file). The main logging API is java.util.logging however other logging APIs are available.

    Features
    Framework Supported log levels Standard appenders Popularity Cost / licence
    Log4J FATAL ERROR WARN INFO DEBUG TRACE AsyncAppender, JDBCAppender, JMSAppender, LF5Appender, NTEventLogAppender, NullAppender, SMTPAppender, SocketAppender, SocketHubAppender, SyslogAppender, TelnetAppender, WriterAppender Widely used in many projects and platforms Apache License, Version 2.0
    Java Logging API SEVERE WARNING INFO CONFIG FINE FINER FINEST Sun's default Java Virtual Machine (JVM) has the following: ConsoleHandler, FileHandler, SocketHandler, MemoryHandler Comes with the JRE
    Apache Commons Logging FATAL ERROR WARN INFO DEBUG TRACE Depends on the underlying framework Widely used, in conjunction with log4j Apache License, Version 2.0
    SLF4J ERROR WARN INFO DEBUG TRACE Depends on the underlying framework, which is pluggable MIT License
    tinylog ERROR WARNING INFO DEBUG TRACE ConsoleWriter, FileWriter, LogcatWriter, JdbcWriter, RollingFileWriter, SharedFileWriter and null (discards all log entries) Apache License, Version 2.0
    Logback ERROR WARN INFO DEBUG TRACE Too many to list: see Appender JavaDoc Used in many projects like Akka, Apache Camel, Apache Cocoon, Artifactory, Gradle, Lift Framework, Play Framework, Scalatra, SonarQube, etc... LGPL, Version 2.1

    Logger Class Overview

    Logger object used to log messages
    Obtained by calling getLogger factory method
    Logger.getGlobal()
    Logger.getLogger(“logger name”)
    Methods:
    entering(String sourceClass, String sourceMethod)
    log a method entry
    exiting(String sourceClass, String sourceMethod)
    log a method return
    info(String msg)
    log an INFO message
    log(Level level, String msg, Throwable thrown)
    log a message with associated Throwable information

    Logging Levels

    Logging Screenshot

    Example

    private static final logger = Logger.getLogger(Students.class.getName());
    
    run:
    Nov 19, 2015 11:42:20 AM students.Students main
    INFO: Main
    Nov 19, 2015 11:42:20 AM students.Students loadStudents
    FINER: ENTRY
    Nov 19, 2015 11:42:20 AM students.Students loadStudents: number of students:
    FINER: RETURN 5
    Nov 19, 2015 11:42:20 AM students.Students loadModules
    FINER ENTRY
    Nov 19, 2015 11:42:20 AM students.dao.textdao.TextModuleDAO loadModules
    
    java.io.FileNotFoundException: modulesa.txt (The system cannot find the file specified)
    1.  List Students  2. List Modules  3. Quit
             at java.io.FileInputStream.open)(native Method)
             at java.io.FileInputStream.open(FileInputStream.java:195)
             at java.io.FileInputStream.<init>(FileInputStream.java:138)
             at java.io.FileInputStream.<init>(FileInputStream.java:93)
             at java.io.FileReader.<init>(FileReader.java:58)
             at students.dao.textdao.TextModuleDAO.loadModules(TextModuleDAO.java:32)
             at students.Students.loadModules(Students.java:140)
             at students.Students.main(Students.java:64)
    Nov 19, 2015 11:42:20 AM students.Students loadModules: number of modules: 
    FINER: RETURN 0
    Enter Choice:
    
    logger.info("Main");
    
    Nov 19, 2015 11:42:20 AM students.Students main
    INFO: Main
    
    logger.entering(Students.class.getName(), "loadStudents");
    
    Nov 19, 2015 11:42:20 AM students.Students loadStudents
    FINER: Entry
    
    logger.exiting(Students.class.getName(), "loadStudents", "loadStudents: number of students: ", students.size());
    
    Nov 19, 2015 11:42:20 AM students.Students loadStudents: number of students:
    FINER: RETURN 5
    
    Logger.getLogger(TextModuleDAO.class.getName()) .log(level.SEVERE, null, ex);
    
    Nov 19, 2015 11:42:20 AM students.dao.textdao.TextModuleDAO loadModules
    SEVERE: null
    
    java.io.FileNotFoundException: modulesa.txt (The system cannot find the file specified)
    1.  List Students  2. List Modules  3. Quit
             at java.io.FileInputStream.open)(native Method)
             at java.io.FileInputStream.open(FileInputStream.java:195)
             at java.io.FileInputStream.<init>(FileInputStream.java:138)
             at java.io.FileInputStream.<init>(FileInputStream.java:93)
             at java.io.FileReader.<init>(FileReader.java:58)
             at students.dao.textdao.TextModuleDAO.loadModules(TextModuleDAO.java:32)
             at students.Students.loadModules(Students.java:140)
             at students.Students.main(Students.java:64)
    

    Logging to a file (XML – default)

    FileHandler handler = new FileHandler("students.log");
    logger.addHandler(handler);
    
    Logging Screenshot

    Logging to a file (Formatted Text)

    SimpleFormatter formatter = new SimpleFormatter();
    handler.setFormatter(formatter);
    
    Logging Screenshot

  • 9.6 Javadoc

    API documentation from Java source files in HTML format:

    Javadocs parses declarations and documentation comments and produces a set of HTML pages that describe (by default):
    Public and protected classes
    Nested classes
    but not anonymous inner classes
    Interfaces
    Constructors, methods, and fields

    Javadoc commands parses special tags when they are embedded within a Java documentation comments. They autogenerate a complete, well-formatted API from source code. Tags start with an at sign (@) and are case-sensitive. They must start at the beginning of a line (after any leading spaces and an optional asterisk). Tags with the same name are grouped together, types:
    Block tags:
    place block tags only in the tag section that follows the description
    @tag
    Inline tags:
    place inline tags anywhere in main description or in comments for block tags
    {@tag}
    @author name-text
    adds an Author entry with specified name text to generated documents when -author option used
    can contain multiple @author tags
    @param parameter-name description
    adds a parameter with specified parameter-name followed by specified description to Parameters section
    valid only in a documentation comment for a method, constructor, or class
    use angle brackets around parameter name to specify use of a type parameter
    @return description
    adds a Returns section with description text.
    text should describe return type and permissible range of values
    valid only in a documentation comment for a method
    @throws/@exception class-name description
    identical
    adds a Throws subheading to generated documentation, with class-name and description text
    class-name is name of exception that might be thrown by method.
    valid only in documentation comment for a method or constructor
    @version version-text
    adds a Version subheading with specified version-text value to generated documents when -version option used
    intended to hold current release number of software that this code is part of, as opposed to @since tag, which holds release number where this code was introduced
  • 1.7 Javadoc example

    Student Class Screenshot

    /** 
     * A constructor used when a student id has already been 
     * allocated e.g. creating student object after loading 
     * details from a file.
     * 
     * @param studentId     the student id
     * @param studentName   the student name
     * @param programmeCode the programme code
     */ 
    public Student(int studentId, String studentName,
                   String programmeCode) {
       this.studentId = studentId;
       this.studentName = studentName;
       this.programmeCode = programmeCode;
       this.registeredModules = new HashSet<>();
       noStudents++;
    } 
    /**
     * A getter method for student id.
     * 
     * @return  the student id
     */
    public int getStudentId() {
      return this.studentId;
    }
    /**
     *
     * @param path  the location of the file
     * @return      the students collection
     * @throws      FileNotFoundException
     */
    public abstract List<Student>
      loadStudents(Path path)
         throws FileNotFoundException;
    
    

    Student Class Screenshot

    Student Class Screenshot

    Student Class Screenshot

    Student Class Screenshot

    Student Class Screenshot