3

Question says everything. Is there any special event occurs? I have a class which needs to implement Serializable interface. I am developing an application using Wicket. I have implemented a Factory class which will provide some links (to remove the redundancy of same code block written over and over):

public class NavigationLinkFactory implements Serializable {

    private static final long serialVersionUID = 7836960726965363785L;

    private NavigationLinkFactory() {

    }

    private static class SingletonHolder { 
        public static final NavigationLinkFactory instance = new NavigationLinkFactory();
    }

    public static NavigationLinkFactory getFactory() {          
        return SingletonHolder.instance;

    }

    private Object readResolve() throws ObjectStreamException {
        return SingletonHolder.instance;
    }

    public Link<Serializable> getUserHomeLink() {
        return new Link<Serializable>("home", new Model<Serializable>()) {

            private static final long serialVersionUID = -8282608926361995521L;

            @Override
            public void onClick() {
                EMSSession session = (EMSSession) getSession();
                session.setActiveHorizonalMenu(1);
                setResponsePage(HomePage.class);
            }
        };      
    }

    public Link<Serializable> getProfileLink() {
        return getProfileViewLink();
    }

    public Link<Serializable> getProfileViewLink() {
        return new Link<Serializable>("profileView", new Model<Serializable>()) {

            private static final long serialVersionUID = 232185489384306999L;

            @Override
            public void onClick() {
                EMSSession session = (EMSSession) getSession();
                session.setActiveHorizonalMenu(2);
                setResponsePage(ProfileViewPage.class);
            }
        };  
    }
}

If I doesn't implement Serializable then I am getting exception at java.io.ObjectOutputStream.writeObject, which is thrown by the runtime environment of the wicket framework. If I implement it then it is gone.

So what really happens when one calls ObjectInputStream#readobject() method for some object created by Singleton pattern?

I am not adding wicket tag because I don't think this question is related to the Wicket.

Tapas Bose
  • 28,796
  • 74
  • 215
  • 331
  • 1
    you don't need synchronized section in getFactory method. This the purpose of singleton holder (avoiding addition synchronization) – Anton May 05 '12 at 18:24

2 Answers2

5

Unfortunately, what happens by default is you get a second (or third, or thirty-seventh) instance of your singleton -- not good. Luckily there's a way around this: by implementing the readResolve() method, which can return a replacement object -- the proper singleton object, in your case -- instead of the one returned by default serialization. The link describes the particulars, but it's pretty simple -- you just implement this parameterless instance method to return the singleton object.

reevesy
  • 3,452
  • 1
  • 26
  • 23
Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • Thank you very much. I have updated the class given in the question. Is it now okay? – Tapas Bose May 05 '12 at 18:36
  • Thanks. It is written in the link you have provided, that, The "readResolve method is called when ObjectInputStream has read an object from the stream", I don't understand by whom this `readResolve` method will be called? – Tapas Bose May 05 '12 at 18:40
  • 2
    After `ObjectInputStream.readObject()` reads an object, it looks at the object to see if it has a `readResolve()` method. If it does, then it calls that method, and the object returned by `readResolve()` is then returned by `readObject()`, instead of the originally-read object. – Ernest Friedman-Hill May 05 '12 at 18:42
3

Another way to implement a serialization-safe singleton is by using an enum. See this answer and the links from it. Briefly, the idea is that Java already guarantees that there is only one instance of any given enum value in the JVM, even in the face of serialization, so you can use an enum value as a singleton. It's a hack, but it's a fairly clean hack.

Community
  • 1
  • 1
Tom Anderson
  • 46,189
  • 17
  • 92
  • 133