DevOps Zone is brought to you in partnership with:

Programmer, solution architect, user group and conference organizer, conference speaker and traveling fun code evangelist. Johannes tries to apply Agile principles to large software projects, but what he's really passionate about is sharing the experience of more fun programming with other coders around the world. Johannes is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

Loud Failures are Better than Silent, Faulty Behavior

10.22.2012
| 3701 views |
  • submit to reddit

Sometimes, small questions lead to big answers. Sometimes these answers are controversial. One such question is “What does this warning about serialVersionUID mean”? All the advice out there basically is for developers who don’t know what’s going on to write code that will ignore errors when something unexpected happens. In my view – this is exactly the wrong approach. The safe way to act is to make sure that your program crashes if you don’t have control.

Java programmers usually get this warning when they write code that looks like this:

public class MyServlet extends HttpServlet {
 
  public void doGet(HttpRequest req, HttpResponse resp) {
    // Some logic goes here
  }
}

On stackoverflow this question has an answer that is extensive, well-written, accepted and, in my opinion, wrong. In short, the answer just recommends to implement something like the following:

public class MyServlet extends HttpServlet {
 
  private static final long serialVersionUID = 123L;

Let’s dig deeper.

The reason we get this warning is that HttpServlet implements the interface Serializable. This was a design flaw in the first version of the servlet-api, and now we’re stuck with it. A serialized object can be written to and read from byte streams, such as a file. Here is an example:

  ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
        outputStream.writeObject(new Person("Johannes", "Brodwall"));
 
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
        Object object = inputStream.readObject();
        System.out.println(object);

In this case, everything is fine. But let’s imagine that some time passes between the write and the read. For example, what if we try to read the file with the next version of the program. A version in which the Person class is changed? For example, what if we changed the implementation of Person to store the name as a single field fullName, instead of two fields firstName and lastName?

In this case, we would get an error message like the following:

java.io.InvalidClassException: Person; local class incompatible:
                             stream classdesc serialVersionUID = -4897183855179110397,
                             local class serialVersionUID = -1928642322738440913

In other words: If we had set the serialVersionUID, we could still have read the file. Now we’re stuck.

This is why the stackoverflow answer recommends putting a serialVersionUID field in the class.

But wait, there’s another option. Let’s say we found this problem when we tested if our new version was backwards compatible. Now, we could just cut and paste the serialVersionUID from the stack trace. If we do test our software, this is just as easy as putting the serialVersionUID there in the first place. So, let’s fix the Person class:

public class Person implements Serializable {
 
    private static final long serialVersionUID = -4897183855179110397L;
    private final String fullName;
 
    public Person(String firstName, String lastName) {
        this.fullName = firstName + " " + lastName;
    }
 
    @Override
    public String toString() {
        return getClass().getSimpleName() + "[name=" + fullName + "]";
    }
}

Voila! Problem fixed. Our code will run again. Here’s the output of printing the object:

Person[name=null]

Whoops! By forcing different versions of class Person to have the same serialVersionUID, the code now has bug. FullName should never be null (especially since it’s final!). And what’s worse, the bug is a silent one. If we don’t examine the contents of System.out (in this case), we might not catch it before it escapes into the wild.

When you’re not sure, the correct behavior should be to fail, not to silently do the wrong thing.

TL;DR

If you omit a serialVersionUID field from your class, many changes will cause serialized objects to no longer be readable. Even for trivial changes.

Sadly, classes like HttpServlet, AbstractAction and JFrame which are meant to be subclassed implements Serializable, even though they are almost never serialized in practice. Adding serialVersionUID to these classes would only be noise.

The serialVersionUID field can be added to a class afterward if you actually want to read old objects in a new version of the program. This leaves you no worse off than if you added the serialVersionUID field in the first place.

If the old and the new version of the class are deeply incompatible, giving the class a serialVersionUID when you first create it will cause silent faulty behavior.

I prefer loud, failing behavior that is easy to detect during testing to quiet, faulty behavior that may escape into production. I think you do, too.

Published at DZone with permission of Johannes Brodwall, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Krish Kumar replied on Fri, 2012/11/09 - 2:18am

 These java coding is more getting warning in Java programming so developer should refer the many java based websites for more topics.

seo company

Ju Peter replied on Thu, 2012/11/29 - 1:48am

 If program coding is more line of code and can not understand the bug or easy to view with the program flow then given idea is nice and useful for every developer.

Dew point transmitter

Krish Kumar replied on Tue, 2012/12/18 - 8:18am

 Developer are always trying to do best coding which can understand while executing project as well as easy to modify on particular line of code.

hrms saas model

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.