Java Exception Handling

Java Exception Handling – NotSerializableException

Continuing along through our in-depth Java Exception Handling series, today we’ll be looking into the NotSerializableException. The NotSerializableException is thrown when attempting to serialize or deserialize an object that does not implement the java.io.Serializable interface.

Throughout this article we’ll get into the nitty gritty of the NotSerializableException, starting with where it resides in the overall Java Exception Hierarchy. We’ll also dig into a functional code example illustrating how to perform basic serialization on Java objects, and how improperly doing so might lead to NotSerializableExceptions, so let’s get to it!

The Technical Rundown

All Java errors implement the java.lang.Throwable interface, or are extended from another inherited class therein. The full exception hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

This code sample also uses the Logging utility class, the source of which can be found here on GitHub.

When Should You Use It?

Let’s briefly take a moment to review what serialization is, in a general programming sense. Effectively, serialization is the act of transforming a structured piece of data (such as an object) into a format that can be easily stored and transmitted. Typically, a serialized format might be a memory stream, a series of characters (i.e. a string), a local file, and so forth. Additionally, deserialization is the act of reversing a previous serialization process — converting a string, memory stream, file, or what not to the original structured piece of data (object) that the element began as.

There are many advantages to serialization, but this ability to convert complex data structures into a rudimentary form (such as a string) makes it particularly easy to transmit specific objects from one source to another, then re-create the original with no data loss.

As with many other programming languages, Java includes built-in serialization support through the Serializable interface. Implementing this interface within a class definition allows that class to be serialized and deserialized through standard methods. To illustrate, we begin with our custom Book class:

Most importantly, we’ve implemented the Serializable interface for the Book class, which will allow our Book objects to be serialized:

We’ve also added the toFilename() method, which attempts to encode a compatible file name out of the author and title fields of the Book instance. We’ll use this somewhat unique filename to create a local file for serialization purposes:

Speaking of which, let’s look at our Main.Serialize(Object object, String filePath) method:

This method attempts to serialize the passed Object object parameter by passing it to the ObjectOutputStream.writeObject(...) method. Our ObjectOutputStream instance is attempted to write to the FileOutputStream created from the String filePath parameter. If successful, we output a log message, otherwise we catch and log any exceptions.

Conversely, the Deserialize(String filePath) generic type method reverses the process by calling ObjectInputStream.readObject() to deserialize the object found in the passed String filePath location:

To test this out we have the TestBookSerialization(Book book) wrapper method:

As you can see, all we’re doing here is creating a local file name (using the Book.toFilename() method we looked at before), then attempting to first serialize and then deserialize the passed Book book object.

To see if everything works as expected our Main.main(...) method creates two different Book instances and performs our serialization tests:

Executing the Main.main() method produces the following output:

Everything seems to be working just as expected. Our encoded filenames are created, and our Book instances are successfully being serialized and saved to the file, then deserialized. To confirm, if we open up the the+name+of+the+wind-patrick+rothfuss.ser local file the contents look like this:

Looks like a mess to us since it’s not stored in a human-readable format, but this further confirms that our serialization is working properly.

However, let’s pretend we did everything as before, expect for one minor mistake: We forgot to add implements Serializable to our Book class definition:

With all other testing code exactly as it was before, executing our Main.main() method again now produces the following output:

Suddenly we experience our first NotSerializableExceptions, which indicate that the io.airbrake.Book class is not serializable. In this case, we know it’s because we didn’t implement the Serializable interface. However, it’s worth noting that serialization can only work if the entire series of related objects are serializable. This means that, if one of the fields of our Book class was private Publisher publisher, where Publisher was a unique class of its own, we could only serialize a Book instance if both Book and Publisher classes implemented the Serializable interface. Alternatively, we could also serialize a Book instance even if Publisher did not implement Serializable, but only if the private Publisher publisher field was annotated as a transient field. The transient annotation indicates that the field should not be serialized.

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!