Sunday, February 10, 2008

On Firefox 3 Beta 2

I have been trying out Firefox 3 Beta 2. The first issue I came up against was that most of my extensions simply stopped working. So lets go over the first steps when you want to switch to Firefox 3 Beta 2.
  1. Step 1: Look for updates to your extensions that work with Firefox 3 Beta 2. Visiting the developer's site or support forums can be incredibly useful.
    • Get Mouse Gestures here
    • Get Tab Mix Plus here
  2. Step 2: If no update is available, try adding a boolean field "extensions.checkCompatibility" to about:config. (More info here)
  3. Step 3: Your skin will mostly stop working on installing FX3, so switch to another skin, but hey you can still get Personas for Firefox
  4. Step 4: Install Weave, create an account, setup an encryption password.
  5. Step 5: If you are concerned about <a ping> (I certainly am), know that it is on by default in all Firefox 3 builds before Feb 1 (which includes Beta 2). There are no visual cues or warnings on a ping link being clicked. You can disable it from about:config by the following method:
This whole ping controversy reminds me of the furor when it came out that the default eBay search plugin for Firefox 1.0 (German Version) sent the search first to a "monitoring" site then to eBay itself. This was soon fixed, and the "monitoring" URL for the search was provided by eBay itself, but that did not stop many people (including yours truly) from accusing Firefox of being spyware. See the related article on mozillazine here(via the Wayback Machine). And a translated version of the discussion in the German Firefox forums here.

As for the current ping issue, as per send_pings page, this is disabled by default as of all builds of Firefox post 1st February 2008. (Which means Firefox 3 Beta 2 users still have to turn it off manually, current builds are Beta 4)

Addendum: I looked up the post I made on the German Firefox topic at the time on my (now defunct) Yahoo 360 blog and suddenly came upon this nugget of information: I am a Facts Curator. (Whatever that means).

More interesting stuff: Yahoo 360 will soon be gone forever.

Sunday, February 3, 2008

Serialization in Java - readResolve(), writeReplace() and more

Quite some time since my last post :) A friend at work mentioned that you cannot serialize classes with a non-serializable parent class that does not have an empty constructor. Whew...

That sounds nice and confusing. So lets try to analyze and see how to implement serialization and what effect does each approach have on your class and its children and grandchildren.

First off you have to realize there are two interfaces: Serializable, which ostensibly has no methods, but actually provides four and Externalizable, which provides two.

Secondly the relationship between Externalizable and Serializable has to be made clear.
  • Externalizable ALWAYS supersedes Serializable.
  • Serializable is more of a "marker" interface - If you declare a class Serializable and customize the serialization behavior, usually, the child class will still get serialized properly in a chained fashion: The child class fields then the customized base class behavior.
  • I say usually because readResolve() and writeReplace() change this default behavior and we shall see below how.
  • If you declare a class Externalizable, it and all its child classes are Externalizable. The moment an Externalizable class is encountered, the Serializable optimizations shut down. It doesn't matter if you declare a derived class Serializable or not, the last overriden readExternal() and writeExternal() methods are the ones that will get called.
With that out of the way, lets see how these two are used:

Base Class Base Class
Empty Constructor
Derived Class
Empty Constructor
Derived Class Methods Grandchild
Serializable N/R N/R N/R N/R N/R
N/A Child Visible N/R Serializable readObject/writeObject N/R
N/A N/A Public Externalizable readExternal/writeExternal Public empty constructor needed. On fieldset change, override readExternal / writeExternal to serialize additional fields.
N/A N/A N/A Serializable Create DTO. Implement writeReplace. In DTO implement readResolve Create new DTO.
Override writeReplace. In DTO implement readResolve

Where N/R means Not Required and N/A means Not Available

In a nutshell,
  • If you have a base class which is Serializable, you are home free... No need to do anything
  • If you have a base class which is not Serializable but does have a child visible (public/protected/package) empty constructor then you implement readObject() and writeObject() in your class and you are done.
  • If your non-Serializable base class does not have an empty constructor then readObject() and writeObject() will not work. You will get an Exception on attempting to Serialize
  • In this case, if your class has an empty constructor, it can implement Externalizable and then it will get Serialized.
  • However, any child classes will transparently get serialized without their new fields, so if you want new fields in child classes to get serialized they must override the readExternal() and writeExternal() methods
  • Lastly we come to the most interesting option: readResolve() and writeReplace(): This actually allows you to replace your class with a DTO at Serialization time. Note that both the methods are implemented in different classes. writeReplace() in the DO and readResolve() in the DTO.
  • You can of course implement only one method, this will mean, say if you only implement writeReplace() in a class then every time it gets written, it will be replaced on the stream by an instance of the DTO class, however, without the readResolve(), on reading you will still get a instance of the DTO not the DO
  • writeReplace() and readResolve() will also mean that your class is no longer serializable in the normal way: any child class which tried to get Serialized and does NOT override the writeReplace() method will get an Exception
Now for some example of how readResolve() and writeReplace() can be used:
Lets say we have a base class, Base

public class Base {
private int a;
private int b;

public Base(int a, int b) {
this.a = a;
this.b = b;
}

/*
* Add Getters and Setters...
*/
}


This has a derived class, Derived4

public class Derived4 extends Base implements Serializable {
private int c;

public Derived4(int a, int b, int c) {
super(a,b);
this.c = c;
}

public Derived4(DataToken d) {
super(d.getA(),d.getB());
c = d.getC();
}

/*
* Add Getters and Setters...
*/

private Object writeReplace() throws ObjectStreamException {
Derived4DataToken d = new Derived4DataToken();
d.setA(this.getA());
d.setB(this.getB());
d.setC(this.getC());
return d;
}
}


Note the writeReplace()? Now, lets see the DTO class: Derived4DataToken

public class Derived4DataToken implements Serializable {
private int a;
private int b;
private int c;

private static final long serialVersionUID = -2835599374077375317L;

/*
* Add Getters and Setters...
*/

private Object readResolve() throws ObjectStreamException {
return new Derived4(this);
}
}


So now, we can go ahead and read and write the class, exactly as normal. Note that if Derived4DataToken had not implemented readResolve(), reading the data stream would have resulted in a Derived4DataToken instance, not a Derived4 instance.

ByteArrayOutputStream os = new ByteArrayOutputStream();
Derived4 d1 = new Derived4(10, 20, 30);
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(d1);
oos.flush();
Derived4 d2;
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(os.toByteArray()));
d2 = (Derived4)ois.readObject();
out.println("Derived4=> a : b : c :: " + d2.getA() + " : " + d2.getB() + " : " + d2.getC());


Finally, let me add that even if you are not making your class Serializable, if you want to be safe such that child classes can be Serializable then the cleanest solution is to have a child visible empty constructor, it will save you much heartache later.

As I sign off, let me add that the HTML highlighting of Java code that has been done here has been done using the Java2Html converter applet here.