CompSci 307
Spring 2019
Software Design and Implementation

Throwing and Catching Exceptions

The goal of this lab is to practice throwing and catching exceptions as well as creating your own exceptions rather than relying only on Java's built in exceptions. In general in an MVC designed application, the Model is the part that discovers the errors but does not know how to handle them because it does not know what context the View is providing (command-line, desktop, web, mobile, etc.). By throwing an exception when an error is discovered the Model can communicate with the View specifically what error has occurred and give the View a chance to catch the exception and handle it appropriately.

Getting Started

For this lab exercise, it is suggested that you work together with one other person in the class:

Throw Exceptions Instead of Returning Null

In general, returning null is a sure way to cause an error somewhere else in the code! However, the BrowserModel currently returns null whenever an error occurs (e.g., it receives a bad URL, an attempt is made to go outsides the bounds of the history, or a bad favorite is asked for). Sometimes the BrowserView checks for null and sometimes not.

In each public method where the BrowserModel returns null, change the code to throw a newly created standard Java Exception instead, like new IllegalStateException() or new IllegalAccessException(). In the BrowserView class, change the code to surround each call to those Model methods with a try-catch block that catches the exact type of exception thrown (rather than the general class Exception). Handle the thrown exceptions by displaying an alert dialog to the user with a useful error message (i.e., call the method showError() in the catch block).

Test the code by running the Main class and entering a bad URL into the text field.

Once you think you have this part working, use GIT to add and commit the changes you have made.

Create Custom Exception

Instead of repurposing standard Java exceptions to fit your project, you can create your own kind of exception (sometimes it may be appropriate, but often there is not one that quite fits your real issue). In other cases, many Java libraries throw a single general exception type using a message that describes the error rather than the class name (typically branded after their project like SpringException).

Create a custom Exception class, called BrowserException, to be thrown instead of the standard Java exceptions you chose in the previous part. To do this, create a new class just like you would any other and make it extends RuntimeException. Then let IntelliJ help you by generating the standard constructors by highlighting the class name in the BrowserException file, right-clicking and selecting "Generate" and then "Constructor". From the list of possible constructors, select both the second and third ones (String and String, Throwable). That's it — you have now created a class that can be thrown and caught as any other standard Java Exception!

Then replace each throw in the BrowserModel class to throw new BrowserException() with an appropriate error message to explain the issue (take the message from those you displayed in the BrowserView class in the previous part). You will also need to change the catch blocks in the BrowserView to catch a BrowserException instead of the standard Java exception you chose. Then you will need to change the call to showError() to call the BrowserException's getMessage() method instead of using the hard coded string parameter as before.

Finally, it is good practice to declare the exceptions that could possibly be thrown by your method to help communicate your intent to users of your code. To each public method in BrowserModel that may throw a BrowserException, add the code "throws BrowserException" to the end of its signature (between the parameter's end parentheses and the definition's starting curly brace).

Test the code by running the Main class and entering a bad URL into the text field.

Once you think you have this part working, use GIT to add and commit the changes you have made.

Use Resource Files Instead of Hardcoded Strings

Just like button names, error messages should be read in from a Java resource properties file (in general, anything that might need to be translated or changed easily should be in a separate non-Java file). In this part, change any error messages you created in the previous step so that they come from a resource file instead of using hard coded strings.

Create a new properties file, named ErrorsEnglish.properties, that has a key=value format for each error message. In this case, the key will be what you refer to in your code and the value will be the message currently hardcoded in the BrowserModel. Then, in the constructor for the BrowserModel class (like in the constructor for the BrowserView class), create a ResourceBundle from the properties file to use to retrieve the message values. Note, you will need to add a parameter to the BrowserModel constructor that represents the error message's "language" that is passed in when it is constructed in the Main class (again like the BrowserView class).

Then you will need to replace each hardcoded string message used to construct the thrown BrowserException by calling the ResourceBundle's getString() method to get the value from the properties file. Note, when doing this, if you used a dynamic value from the code (like the URL given as a parameter to the go() method), you will need to change your message string to be a single value (not something concatenated together as you might usually write). You can use the String.format() method to accomplish this, substituting a "%s" in the one combined string stored in the properties file where you want the URL's value to appear, like this:

BadURL="Could not load URL %s"

Test the code by running the Main class and entering a bad URL into the text field. Further test this code by creating a second properties file, named ErrorsGibberish.properties, that has a different set of values for the error messages. Change the "language" used in the Main class and verify that the new message is displayed when a bad URL is entered.

Once you think you have this part working, use GIT to add and commit the changes you have made.

Submission

At the end of class, use Gitlab's Merge Request to submit your group's refactored code to the original organization repository. Make sure both people's NetIDs are in the title of your Merge Request.