Exercism v3 launches on Sept 1st 2021. Learn more! ๐Ÿš€๐Ÿš€๐Ÿš€
Avatar of rootulp

rootulp's solution

to Error Handling in the Java Track

Published at May 24 2020 · 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

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 static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Ignore;
import org.junit.Test;

import java.util.Optional;

public class ErrorHandlingTest {

    private ErrorHandling errorHandling = new ErrorHandling();

    @Test
    public void testThrowIllegalArgumentException() {
        assertThrows(
            IllegalArgumentException.class,
            errorHandling::handleErrorByThrowingIllegalArgumentException);
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowIllegalArgumentExceptionWithDetailMessage() {
        IllegalArgumentException expected =
            assertThrows(
                IllegalArgumentException.class,
                () -> errorHandling
                    .handleErrorByThrowingIllegalArgumentExceptionWithDetailMessage(
                        "This is the detail message."));

        assertThat(expected).hasMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyCheckedException() {
        Exception expected =
            assertThrows(
                Exception.class,
                errorHandling::handleErrorByThrowingAnyCheckedException);
        assertThat(expected).isNotInstanceOf(RuntimeException.class);
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyCheckedExceptionWithDetailMessage() {
        Exception expected =
            assertThrows(
                Exception.class,
                () -> errorHandling
                    .handleErrorByThrowingAnyCheckedExceptionWithDetailMessage(
                        "This is the detail message."));
        assertThat(expected).isNotInstanceOf(RuntimeException.class);
        assertThat(expected).hasMessage("This is the detail message.");
    }

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

    @Ignore("Remove to run test")
    @Test
    public void testThrowAnyUncheckedExceptionWithDetailMessage() {
        RuntimeException expected =
            assertThrows(
                RuntimeException.class,
                () -> errorHandling
                    .handleErrorByThrowingAnyUncheckedExceptionWithDetailMessage(
                        "This is the detail message."));
        assertThat(expected).hasMessage("This is the detail message.");
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomCheckedException() {
        assertThrows(
            CustomCheckedException.class,
            errorHandling::handleErrorByThrowingCustomCheckedException);
    }

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomCheckedExceptionWithDetailMessage() {
        CustomCheckedException expected =
            assertThrows(
                CustomCheckedException.class,
                () -> errorHandling
                    .handleErrorByThrowingCustomCheckedExceptionWithDetailMessage(
                        "This is the detail message."));
        assertThat(expected).hasMessage("This is the detail message.");
    }

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

    @Ignore("Remove to run test")
    @Test
    public void testThrowCustomUncheckedExceptionWithDetailMessage() {
        CustomUncheckedException expected =
            assertThrows(
                CustomUncheckedException.class,
                () -> errorHandling
                    .handleErrorByThrowingCustomUncheckedExceptionWithDetailMessage(
                        "This is the detail message."));
        assertThat(expected).hasMessage("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());
    }

}
import java.util.Optional;

class ErrorHandling {

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

    void handleErrorByThrowingIllegalArgumentExceptionWithDetailMessage(String message) {
		throw new IllegalArgumentException("This is the detail 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 e) {
				return Optional.empty();
			}
    }

}

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?