Java Basics: Custom Exceptions

How to write your own exception in Java

This is a follow on post to my last post on Exception Handling in Java.  I’m going to cover how to write your own exception in Java.  Why would we do that?  Java has a large variety of exceptions and it’s true that most of the time you can find one that will do what you need it to do.  You should write your own exception when you need an exception that does something the already available exceptions don’t.  It might store extra information, such as an error code.  For a real-world example, I’ve used custom exceptions when I’ve also written my own file format filters, so that I can provide detailed information about what is wrong with a file format.

The example for this post is going to automatically log a security exception.  It’s a best practice for secure development to log all attempts to log in and especially any failed logins.  This exception automatically logs when it’s thrown.

Posts in the Series

  1. Java Basics: Control Flow Statements
  2. Java Basics: Exception Handling
  3. Java Basics: Custom Exceptions (this post)
  4. Java Basics: Arrays and Collections
  5. Java Basics: Maps
  6. Java Basics: File I/O
  7. Java Basics: NIO Files

Extending Exception

In our example, we’re going to create our own checked exception.  To create a checked exception, we’re going to extend the class java.lang.Exception.  To create a runtime exception you extend java.lang.RuntimeException. Technically, you can name your exception class whatever you want, but in Java all checked exceptions end with the word Exception.  Our exception is named AutoLoggingSecurityException.

After naming your exception and extending java.lang.Exception, the other thing to do is override the constructors that you want to use.  In this example, I overrode them all except the default.  As an aside, I am just using standard out for simplicity; an actual application should have a logging framework in place.  An important thing to note is that if your exception might be called as the result of another exception, it’s important to override at least one of the constructors that takes a Throwable parameter.  I strongly advise taking the time to write some Javadoc for your exception too, especially if it’s part of an API.

/**
 * Exception meant for use in security situations that automatically logs
 * when thrown.
 * 
 * @author Amy DeGregorio
 */
public class AutoLoggingSecurityException extends Exception {

   /**
    * Constructs a new AutoLoggingSecurity exception with the message and cause provided.
    * The message is then written to the log.
    * 
    * @param message
    * @param cause
    */
   public AutoLoggingSecurityException(String message, Throwable cause) {
      super(message, cause);
      System.out.println("SECURITY EXCEPTION: " + message);
   }

   /**
    * Constructs a new AutoLoggingSecurity exception with the message provided.
    * The message is then written to the log.
    * 
    * @param message
    */
   public AutoLoggingSecurityException(String message) {
      super(message);
      System.out.println("SECURITY EXCEPTION: " + message);
   }

   /**
    * Constructs a new AutoLoggingSecurity exception with the cause provided.
    * If the cause is not null then it's message is then written to the log.
    * 
    * @param cause
    */
   public AutoLoggingSecurityException(Throwable cause) {
      super(cause);
      if (cause != null) {
         System.out.println("SECURITY EXCEPTION: " + cause.getMessage());
      }
   }

   /**
    * Constructs a new AutoLoggingSecurity exception with the values provided.
    * The message is then written to the log.
    * 
    * @param message
    * @param cause
    * @param enableSuppression
    * @param writableStackTrace
    */
   public AutoLoggingSecurityException(String message, Throwable cause, boolean enableSuppression,
      boolean writableStackTrace) {
      super(message, cause, enableSuppression, writableStackTrace);
      System.out.println("SECURITY EXCEPTION: " + message);
   } 
}

Now that we’ve got our exception, let’s throw it and see what happens.  For the sake of simplicity, I have a method called attemptDummyLogin that just throws our custom exception.  The main method uses a try-catch statement around the method call.

public static void main(String[] args) {
   CustomExceptionExample example = new CustomExceptionExample();
   String username = "admin";
   String password = "I'm a fake password";
   try {
      System.out.println("Attempting login as " + username);
      example.attemptDummyLogin(username, password);
   } catch (AutoLoggingSecurityException e) {
      //This is auto logging exception - so what we'd really like to do here is make sure
      //user is given a message and maybe another chance.
   }
}

public void attemptDummyLogin(String username, String password) throws AutoLoggingSecurityException {
   throw new AutoLoggingSecurityException("Invalid username or password for " + username);
}

When we run our example application, we see the following in the console.

Attempting login as admin
SECURITY EXCEPTION: Invalid username or password for admin

Conclusion

Writing a custom exception is pretty straight forward.  More important than the programming techniques in this case is adherence to convention and documentation.  The example application is available on GitHub.

 

Advertisements

4 thoughts on “Java Basics: Custom Exceptions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s