<?xml version="1.0" encoding="UTF-8"?>
<chapter annotations="slide" version="5.1" xml:id="sw1ChapterErrorHandling"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:svg="http://www.w3.org/2000/svg"
         xmlns:ns="http://docbook.org/ns/transclusion"
         xmlns:m="http://www.w3.org/1998/Math/MathML"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:db="http://docbook.org/ns/docbook">
  <title>Error Handling</title>

  <figure xml:id="sd1_fig_compileRuntime">
    <title>Compile- and runtime errors</title>

    <programlisting language="java">final int public <co
        linkends="sd1_fig_compileRuntime-1"
        xml:id="sd1_fig_compileRuntime-1-co"/> = 33;

final String s = null;
System.out.println(s.length())<co linkends="sd1_fig_compileRuntime-2"
        xml:id="sd1_fig_compileRuntime-2-co"/> ;</programlisting>

    <calloutlist>
      <callout arearefs="sd1_fig_compileRuntime-1-co"
               xml:id="sd1_fig_compileRuntime-1">
        <para>Compile time error: public is a <xref linkend="glo_Java"/>
        keyword not to be used as variable's name.</para>
      </callout>

      <callout arearefs="sd1_fig_compileRuntime-2-co"
               xml:id="sd1_fig_compileRuntime-2">
        <para>Run time error: De-referencing <code language="java">null</code>
        yields a <classname
        xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>.</para>
      </callout>
    </calloutlist>
  </figure>

  <figure xml:id="sd1_fig_npe">
    <title><classname
    xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>
    (<acronym>NPE</acronym> for short)</title>

    <programlisting language="java">final String s = null;
System.out.println(s.length());</programlisting>

    <screen>Exception in thread "main" java.lang.NullPointerException
  at exceptionhandling.Npe.main(Npe.java:7)</screen>
  </figure>

  <figure xml:id="sd1_fig_npe_is_a_class">
    <title><classname
    xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>
    is a class</title>

    <mediaobject>
      <imageobject>
        <imagedata fileref="Ref/ErrorHandling/npe.multi.svg"/>
      </imageobject>
    </mediaobject>
  </figure>

  <figure xml:id="sd1_fig_exceptionsAreBeingThrown">
    <title>Throwing an exception</title>

    <programlisting language="java">...
if (somethingBadHappens) {
  throw new <link
        xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html#%3Cinit%3E()">NullPointerException()</link>;
}
...</programlisting>

    <note>
      <para>Without countermeasures your program will terminate</para>
    </note>
  </figure>

  <figure xml:id="sd1_fig_npeErrorMessage">
    <title>Catching an exception by <code language="java">try {...} catch
    {...}</code></title>

    <programlisting language="java">final String s = null;
try {
  System.out.println(s.length()) ;
} catch (final <link
        xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</link> e) {
  System.out.println("Dear user, something bad just happened");
}
System.out.println("Business as usual ...");</programlisting>

    <screen>Dear user, something bad just happened
Business as usual ...</screen>
  </figure>

  <qandaset defaultlabel="qanda"
            xml:id="sd1_errorhandling_qanda_CatchingWrongException">
    <title>Mind your prey</title>

    <qandadiv>
      <qandaentry>
        <question>
          <para>We reconsider:</para>

          <programlisting language="java">final String s = null;
try {
  System.out.println(s.length()) ;
} catch (final NullPointerException e) {
  System.out.println("Dear user, something bad just happened");
}
System.out.println("Business as usual ...");</programlisting>

          <para>What happens if <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>
          is being replaced by <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/OutOfMemoryError.html">OutOfMemoryError</classname>?</para>

          <para>Is there a way to catch all possible exceptions?</para>
        </question>

        <answer>
          <para>We have:</para>

          <programlisting language="java">final String s = null;
try {
  System.out.println(s.length()) ;
} catch (final OutOfMemoryError e) {
  System.out.println("Dear user, something bad just happened");
}
System.out.println("Business as usual ...");</programlisting>

          <para>The runtime system throws a <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>
          which is no subclass of <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/OutOfMemoryError.html">OutOfMemoryError</classname>:</para>

          <mediaobject>
            <imageobject>
              <imagedata fileref="Ref/ErrorHandling/qandaNpeMemory.svg"/>
            </imageobject>
          </mediaobject>

          <para>If <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">NullPointerException</classname>
          was a subclass of <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/OutOfMemoryError.html">OutOfMemoryError</classname>
          it would still be caught. But lacking an (upcast) inheritance
          relationship we are being left with the runtimes default terminating
          behaviour:</para>

          <screen>Exception in thread "main" <link
              xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">java.lang.NullPointerException</link>
  at exceptionhandling.NpeMsg.main(NpeMsg.java:8)</screen>
        </answer>
      </qandaentry>
    </qandadiv>
  </qandaset>

  <figure xml:id="sd1_fig_tryCatchSyntax">
    <title><code language="java">try {...} catch {...}</code> syntax</title>

    <programlisting language="java">try {
 [code that may throw an exception]
}[catch (ExceptionType-1 e) {
 [code that is executed when ExceptionType-1 is thrown]
}] [catch (ExceptionType-2 e) {
 [code that is executed when ExceptionType-2 is thrown]
}]
  ...
} [catch (ExceptionType-n e) {
  [code that is executed when ExceptionType-n is thrown]
}]
[finally {
  [code that runs regardless of whether an exception was thrown]]
}]</programlisting>
  </figure>

  <section xml:id="sd1_errorhandling_sect_checkedVsUnchecked">
    <title>Checked vs unchecked exceptions</title>

    <figure xml:id="sd1_errorhandling_fig_checkedVsUnchecked">
      <title>Checked and unchecked exceptions</title>

      <informaltable border="0">
        <tr>
          <td valign="top"><programlisting language="none">public static void main(String[] args) {
  final Path
    sourcePath = Paths.get("/tmp/test.txt"),
    destPath = Paths.get("/tmp/copy.java");

  // Compile time error:
  // <emphasis role="red"
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/IOException.html">Unhandled exception:
      java.io.IOException</emphasis>
  Files.copy(sourcePath, destPath);
...</programlisting></td>

          <td valign="top"><programlisting language="none">public static void
  main(String[] args) {

final String s = null;

// <emphasis role="red">No problem</emphasis>
System.out.println(s.length());</programlisting></td>
        </tr>
      </informaltable>
    </figure>

    <figure xml:id="sd1FigExceptionBasics">
      <title>Checked and unchecked exceptions</title>

      <mediaobject>
        <imageobject>
          <imagedata fileref="Ref/ErrorHandling/exception.multi.svg"/>
        </imageobject>
      </mediaobject>
    </figure>
  </section>

  <section xml:id="sd1_errorhandling_exceptionsAndJunit">
    <title>Exceptions and <xref linkend="glo_Junit"/></title>

    <figure xml:id="sd1_errorHandling_fig_junitExpectedException">
      <title>Expected exceptions in <xref linkend="glo_Junit"/></title>

      <programlisting language="java"><link
          xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html">@Test</link>(<link
          xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html#expected()">expected</link> = <link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</link>.class)
public void copyFile() throws IOException {
  final Path
    source = Paths.get("/tmp/source.txt"),
    dest   = Paths.get("/tmp/dest.txt");

  <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // May work.
  <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // Failure: <link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</link>
}</programlisting>
    </figure>

    <qandaset defaultlabel="qanda"
              xml:id="sd1_errorhandling_qanda_junitExpectedException">
      <title>Expected exception test failure</title>

      <qandadiv>
        <qandaentry>
          <question>
            <para>We reconsider:</para>

            <programlisting language="java">@Test(expected = FileAlreadyExistsException.class)
public void copyFile() throws IOException {
  final <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Path.html">Path</link>
    source = <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Paths.html#get(java.lang.String,java.lang.String...)">Paths.get</link>("/tmp/source.txt"),
    dest   = <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Paths.html#get(java.lang.String,java.lang.String...)">Paths.get</link>("/tmp/dest.txt");

  <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // May work.
  <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // Failure: <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</link>
}</programlisting>

            <para>Modify this code by catching the exception inside
            <methodname>copyFile()</methodname> using <code
            language="java">try {...} catch {...}</code>. Then execute the
            test. What do you observe?</para>
          </question>

          <answer>
            <para>We catch the exception in question:</para>

            <programlisting language="java"><link
                xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html">@Test</link>(<link
                xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html#expected()">expected</link> = <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</link>.class)
public void copyFile() throws IOException {
  final Path
    source = Paths.get("/tmp/source.txt"),
    dest   = Paths.get("/tmp/dest.txt");
  try {
    <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // May work.
    <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)">Files.copy</link>(source, dest);  // Failure: FileAlreadyExistsException
  } catch (final <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</link> e) {
    System.out.println("Destination file already exists");
  }
}</programlisting>

            <para>Since we swallow the <classname
            xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">FileAlreadyExistsException</classname>
            ourselves it is no longer being thrown. Due to the
            <code>@Test(expected = FileAlreadyExistsException.class)</code>
            annotation test execution now fails:</para>

            <screen>Destination file already exists

java.lang.AssertionError: Expected exception: <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/nio/file/FileAlreadyExistsException.html">java.nio.file.FileAlreadyExistsException</link></screen>
          </answer>
        </qandaentry>
      </qandadiv>
    </qandaset>
  </section>

  <section xml:id="sd1_errorhandling_sect_variants">
    <title>Variants</title>

    <figure xml:id="sd1_errorHandling_fig_justFinally_">
      <title>Just <code language="java">finally</code>, no <code
      language="java">catch</code></title>

      <programlisting language="java"><link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/util/Scanner.html">Scanner</link> scanner = null;
try {
  scanner = new <link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/InputStream.html">Scanner(</link>System.in);
   ... // Something may fail
} finally {
  if (null != scanner) {
    scanner.<link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/util/Scanner.html#close()">close()</link>; // Clean up, save resources!
  }
}</programlisting>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_tryWithResources">
      <title><code language="java">try-with-resources</code> (<xref
      linkend="glo_Java"/> 7)</title>

      <programlisting language="java">try (final <link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/util/Scanner.html">Scanner</link><co
          linkends="sd1_errorHandling_fig_tryWithResources-1"
          xml:id="sd1_errorHandling_fig_tryWithResources-1-co"/>  scanner<co
          linkends="sd1_errorHandling_fig_tryWithResources-2"
          xml:id="sd1_errorHandling_fig_tryWithResources-2-co"/> = new Scanner(System.in)) {
   ... // Something may fail
}<co linkends="sd1_errorHandling_fig_tryWithResources-3"
          xml:id="sd1_errorHandling_fig_tryWithResources-3-co"/></programlisting>

      <calloutlist>
        <callout arearefs="sd1_errorHandling_fig_tryWithResources-1-co"
                 xml:id="sd1_errorHandling_fig_tryWithResources-1">
          <para>Class must implement interface <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/AutoCloseable.html">AutoCloseable</classname>.</para>
        </callout>

        <callout arearefs="sd1_errorHandling_fig_tryWithResources-2-co"
                 xml:id="sd1_errorHandling_fig_tryWithResources-2">
          <para>Variable <code language="java">scanner</code>'s scope limited
          to block.</para>
        </callout>

        <callout arearefs="sd1_errorHandling_fig_tryWithResources-3-co"
                 xml:id="sd1_errorHandling_fig_tryWithResources-3">
          <para><methodname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/util/Scanner.html#close()">close()</methodname>
          method will be called automatically before leaving block
          scope.</para>
        </callout>
      </calloutlist>
    </figure>
  </section>

  <section xml:id="sd1_errorhandling_sect_classException">
    <title>Class <classname
    xlink:href="https://docs.oracle.com/javase/10/docs/api/index.html?java/io/File.html">java.lang.Exception</classname></title>

    <figure xml:id="sd1_errorHandling_fig_stackTrace">
      <title>Method <methodname
      xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Throwable.html#printStackTrace()">printStackTrace()</methodname></title>

      <informaltable border="0">
        <tr>
          <td valign="top"><programlisting language="java"
          linenumbering="numbered">package exceptionhandling;
public class StackTrace {
  public static void main(
       String[] args){
    a();
  }
  static void a() { b();}
  static void b() { c();}
  static void c() {
    String s = null;
    s.length();
  }
}</programlisting></td>

          <td valign="top"><screen>Exception in thread "main"
   <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/NullPointerException.html">java.lang.NullPointerException</link>
 at ex.Trace.c(Trace.java:10)
 at ex.Trace.b(Trace.java:7)
 at ex.Trace.a(Trace.java:6)
 at ex.Trace.main(Trace.java:4)</screen></td>
        </tr>
      </informaltable>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_ascendingInheritOrder">
      <title>Ascending inheritance ordering</title>

      <informaltable border="0">
        <tr>
          <td valign="top"><programlisting language="java">try {
  <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/FileInputStream.html">FileInputStream</link> f = new <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/FileInputStream.html#%3Cinit%3E(java.io.File)">FileInputStream(
     new File("test.txt"))</link>;
} catch(final <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/FileNotFoundException.html">FileNotFoundException</link> e) {
  System.err.println( "File not found");
} catch (final <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/IOException.html">IOException</link> e) {
  System.err.println( "IO error");
} catch(final <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Exception.html">Exception</link> e) {
  System.err.println("General error");
}</programlisting></td>

          <td valign="top"><mediaobject>
              <imageobject>
                <imagedata fileref="Ref/ErrorHandling/fileNotFoundHierarchy.svg"/>
              </imageobject>
            </mediaobject></td>
        </tr>
      </informaltable>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_descendingInheritOrder">
      <title>Descending inheritance ordering</title>

      <informaltable border="0">
        <tr>
          <td valign="top"><programlisting language="none">try {
  FileInputStream f = new <link
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/FileInputStream.html">FileInputStream</link>(
     new <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/File.html#%3Cinit%3E(java.lang.String)">File("test.txt"))</link>;
} catch(Exception e) {
      System.err.println("General error");
} catch (<emphasis role="red"
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/IOException.html">IOException e</emphasis>) {
      System.err.println( "IO error");
} catch(<emphasis role="red"
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/io/FileNotFoundException.html">FileNotFoundException e</emphasis>) {
      System.err.println("File not found");
}</programlisting></td>

          <td valign="top"><mediaobject>
              <imageobject>
                <imagedata fileref="Ref/ErrorHandling/fileNotFoundHierarchy.svg"/>
              </imageobject>
            </mediaobject></td>
        </tr>
      </informaltable>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_implementCardinalSimple">
      <title>Implementing <methodname>convert</methodname></title>

      <programlisting language="java">/**
 * Translate {"one", "two", "three"} to {"first", "second", "third"}
 * @param input The input String to be translated.
 * @return See above explanation.
 */
static public String convert(final String input) {
 switch (input) {
   case "one": return "first";
   case "two": return "second";
   case "three": return "third";
  default: return "no idea for " + input;
  }
}</programlisting>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_cardinalThrowError">
      <title>Problem: <quote>Silent</quote> errors</title>

      <itemizedlist>
        <listitem>
          <para>Return false result, application continues.</para>
        </listitem>

        <listitem>
          <para>Solution: Throw an exception. Steps:</para>

          <orderedlist>
            <listitem>
              <para>Find a suitable exception base class.</para>
            </listitem>

            <listitem>
              <para>Derive a corresponding exception class</para>
            </listitem>

            <listitem>
              <para>Throw the exception accordingly.</para>
            </listitem>

            <listitem>
              <para>Test correct behaviour.</para>
            </listitem>
          </orderedlist>
        </listitem>
      </itemizedlist>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_cardinalThrowErrorStep1">
      <title>Step 1: Find exception base class</title>

      <itemizedlist>
        <listitem>
          <para>Problem happens on wrong argument to
          <methodname>convert(...)</methodname>.</para>
        </listitem>

        <listitem>
          <para>Use <classname
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/IllegalArgumentException.html">IllegalArgumentException</classname>.</para>
        </listitem>
      </itemizedlist>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_cardinalThrowErrorStep2">
      <title>Step 2: Derive <classname>CardinalException</classname></title>

      <programlisting language="java">public class CardinalException
  extends <link
          xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/IllegalArgumentException.html">IllegalArgumentException</link> {

  public CardinalException(final String msg) {
    <link xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/IllegalArgumentException.html#%3Cinit%3E(java.lang.String)">super(msg)</link>;
  }
}</programlisting>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_cardinalThrowErrorStep3">
      <title>Step 3: Throwing <classname>CardinalException</classname></title>

      <programlisting language="java">/**
 * Translate {"one", "two", "three"} to {"first", "second", "third"}
 * @param input The input String to be translated.
 * @return See above explanation.
 * @throws CardinalException If input not from list.
 */
static public String convert(final String input)
  throws CardinalException {

  switch (input) {
    case "one": return "first";
    case "two": return "second";
    case "three": return "third";
  }
  throw new CardinalException(
            "Sorry, no translation for '" + input + "' on offer");
}</programlisting>
    </figure>

    <figure xml:id="sd1_errorHandling_fig_cardinalThrowErrorStep4">
      <title>Step 4: Unit test throwing
      <classname>CardinalException</classname></title>

      <programlisting language="java"><link
          xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html">@Test</link> public void testRegular() {
  Assert.<link
          xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertEquals(java.lang.Object,%20java.lang.Object)">assertEquals</link>("second", Cardinal.convert("two"));
}

<link xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html">@Test</link>(<link
          xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Test.html#expected()">expected</link> = CardinalException.class)
public void testException() {
  Assert.assertEquals("X", Cardinal.convert("four"));
}</programlisting>
    </figure>
  </section>
</chapter>