Avatar of artemkorsakov

artemkorsakov's solution

to Error Handling in the Java Track

Published at Jun 23 2019 · 0 comments
Instructions
Test suite
Solution

Implement various kinds of error handling and resource management.

An important point of programming is how to handle errors and close resources even if errors occur.

This exercise requires you to handle various errors. Because error handling is rather programming language specific you'll have to refer to the tests for your track to see what's exactly required.

Tips

This exercise requires you to handle exceptions. An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

In Java, there are two types of exceptions: checked and unchecked exceptions.

Checked exceptions

Checked exceptions are the exceptions that are checked at compile time.

Practical implications

You have to declare them in the method signature of any method that can throw a checked exception and handle or rethrow them when calling any method that can throw a checked exception.

This is because checked exceptions are meant to be handled at runtime, i.e. they are errors you can recover from.

Examples of where they are used

They're often used when a method can't return any valid result, for example a search method which hasn't found the item it was searching for.

It's an alternative to returning null or a error code. A checked exception is better than those alternatives because it forces the user of the method to consider the error case.

Unchecked exceptions

Unchecked exceptions are the exceptions that are not checked at compile time.

Practical implications

You don't have to declare them in the method signature of methods that can throw an unchecked exception and handle or rethrow them when calling any method that can throw an unchecked exception.

Examples of where they are used

Unchecked exceptions are mean to be used for any error than can't be handled at runtime, e.g. running out of memory.

Setup

Go through the setup instructions for Java to install the necessary dependencies:

https://exercism.io/tracks/java/installation

Running the tests

You can run all the tests for an exercise by entering the following in your terminal:

$ gradle test

Use gradlew.bat if you're on Windows

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by removing the @Ignore("Remove to run test") annotation.

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

ErrorHandlingTest.java

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Optional;

public class ErrorHandlingTest {

    private ErrorHandling errorHandling;

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Before
    public void setUp() {
        errorHandling = new ErrorHandling();
    }

    @Test
    public void testThrowIllegalArgumentException() {
        thrown.expect(IllegalArgumentException.class);
        errorHandling.handleErrorByThrowingIllegalArgumentException();
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowIllegalArgumentExceptionWithDetailMessage() {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("This is the detail message.");
        errorHandling.handleErrorByThrowingIllegalArgumentExceptionWithDetailMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyCheckedException() {
        try {
            errorHandling.handleErrorByThrowingAnyCheckedException();
        } catch (Exception e) {
            assertFalse(e instanceof RuntimeException);
        }
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyCheckedExceptionWithDetailMessage() {
        try {
            errorHandling.handleErrorByThrowingAnyCheckedExceptionWithDetailMessage("This is the detail message.");
        } catch (Exception e) {
            assertFalse(e instanceof RuntimeException);
            assertEquals("This is the detail message.", e.getMessage());
        }
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyUncheckedException() {
        thrown.expect(RuntimeException.class);
        errorHandling.handleErrorByThrowingAnyUncheckedException();
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyUncheckedExceptionWithDetailMessage() {
        thrown.expect(RuntimeException.class);
        thrown.expectMessage("This is the detail message.");
        errorHandling.handleErrorByThrowingAnyUncheckedExceptionWithDetailMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomCheckedException() throws CustomCheckedException {
        thrown.expect(CustomCheckedException.class);
        errorHandling.handleErrorByThrowingCustomCheckedException();
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomCheckedExceptionWithDetailMessage() throws CustomCheckedException {
        thrown.expect(CustomCheckedException.class);
        thrown.expectMessage("This is the detail message.");
        errorHandling.handleErrorByThrowingCustomCheckedExceptionWithDetailMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomUncheckedException() {
        thrown.expect(CustomUncheckedException.class);
        errorHandling.handleErrorByThrowingCustomUncheckedException();
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomUncheckedExceptionWithDetailMessage() {
        thrown.expect(CustomUncheckedException.class);
        thrown.expectMessage("This is the detail message.");
        errorHandling.handleErrorByThrowingCustomUncheckedExceptionWithDetailMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testReturnOptionalInstance() {
        Optional<Integer> successfulResult = errorHandling.handleErrorByReturningOptionalInstance("1");
        assertTrue(successfulResult.isPresent());
        assertEquals(1, (int) successfulResult.get());

        Optional<Integer> failureResult = errorHandling.handleErrorByReturningOptionalInstance("a");
        assertFalse(failureResult.isPresent());
    }

}

src/main/java/ErrorHandling.java

import java.util.Optional;

class ErrorHandling {

    void handleErrorByThrowingIllegalArgumentException() {
        throw new IllegalArgumentException("");
    }

    void handleErrorByThrowingIllegalArgumentExceptionWithDetailMessage(String message) {
        throw new IllegalArgumentException(message);
    }

    void handleErrorByThrowingAnyCheckedException() throws CustomCheckedException {
        throw new CustomCheckedException();
    }

    void handleErrorByThrowingAnyCheckedExceptionWithDetailMessage(String message) throws CustomCheckedException {
        throw new CustomCheckedException(message);
    }

    void handleErrorByThrowingAnyUncheckedException() {
        throw new CustomUncheckedException();
    }

    void handleErrorByThrowingAnyUncheckedExceptionWithDetailMessage(String message) {
        throw new CustomUncheckedException(message);
    }

    void handleErrorByThrowingCustomCheckedException() throws CustomCheckedException {
        throw new CustomCheckedException();
    }

    void handleErrorByThrowingCustomCheckedExceptionWithDetailMessage(String message) throws CustomCheckedException {
        throw new CustomCheckedException(message);
    }

    void handleErrorByThrowingCustomUncheckedException() {
        throw new CustomUncheckedException();
    }

    void handleErrorByThrowingCustomUncheckedExceptionWithDetailMessage(String message) {
        throw new CustomUncheckedException(message);
    }

    Optional<Integer> handleErrorByReturningOptionalInstance(String integer) {
        try {
            return Optional.of(Integer.parseInt(integer));
        } catch (NumberFormatException ignore) {
            return Optional.empty();
        }
    }

}

src/main/java/CustomCheckedException.java

class CustomCheckedException extends Exception {

    private static final long serialVersionUID = -7974699643024452706L;

    CustomCheckedException() {
        super();
    }

    CustomCheckedException(String message) {
        super(message);
    }

}

src/main/java/CustomUncheckedException.java

class CustomUncheckedException extends RuntimeException {

    private static final long serialVersionUID = -4414219281389811351L;

    CustomUncheckedException() {
        super();
    }

    CustomUncheckedException(String message) {
        super(message);
    }

}

Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?