|
The Java Specialists' Newsletter
Issue 013b 2001-03-15
Category:
GUI
Java version: Follow-upby Dr. Heinz M. Kabutz
Hi again,
Imagine my horror this morning when I tried to run the code from
last nights newsletter and discovered that it generated an
exception! On frantic searching I figured that the JBuilder 3.0
compiler produces a different result to the SUN JDK 1.3 compiler.
I had only run the program from within JBuilder, so I got quite a
surprise that it did not work in SUN. The reason I'm blaming the
compiler is because when I ran the class files generated by
JBuilder 3.0 with the JDK 1.3 VM it works perfectly.
The problem is that if you call out.defaultWriteObject(), the
two compilers have different ideas of which object you are
calling this from, because you are inside an inner class. The
SUN compiler thinks you are calling it from ComponentSerializer
and that is not serializable.
The solution is quite simple, just move the ComponentEncapsulator
class out of the ComponentSerializer class and it should work
with the JDK 1.3 compiler.
We thus end up with ComponentSerializer:
//: ComponentSerializer.java
import java.io.*;
import java.awt.*;
public class ComponentSerializer {
public void write(Component comp, OutputStream out)
throws IOException {
System.out.println("writing " + comp);
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(new ComponentEncapsulator(comp));
oout.reset();
oout.flush();
}
public Component read(InputStream in)
throws IOException, ClassNotFoundException {
System.out.println("reading component");
ObjectInputStream oin = new ObjectInputStream(in);
ComponentEncapsulator enc =
(ComponentEncapsulator)oin.readObject();
return enc.getComponent();
}
}
and ComponentEncapsulator:
//: ComponentEncapsulator.java
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.lang.reflect.*; // wouldn't be right for me to send
// you a newsletter that doesn't use reflection :)
class ComponentEncapsulator implements Serializable {
private final Component comp;
private IOException defaultWriteException;
public ComponentEncapsulator(Component comp) {
this.comp = comp;
}
public Component getComponent() {
return comp;
}
private void writeObject(final ObjectOutputStream out)
throws IOException {
if (SwingUtilities.isEventDispatchThread()) {
// This is all that is necessary if we are already in
// the event dispatch thread, e.g. a user clicked a
// button which caused the object to be written
out.defaultWriteObject();
} else {
try {
// we want to wait until the object has been written
// before continuing. If we called this from the
// event dispatch thread we would get an exception
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
// easiest way to indicate to the enclosing class
// that an exception occurred is to have a member
// which keeps the IOException
defaultWriteException = null;
// we call the actual write object method
out.defaultWriteObject();
} catch(IOException ex) {
// oops, an exception occurred, remember the
// exception object
defaultWriteException = ex;
}
}
});
if (defaultWriteException != null) {
// an exception occurred in the code above, throw it!
throw defaultWriteException;
}
} catch(InterruptedException ex) {
// I'm not quite sure what do here, perhaps:
Thread.currentThread().interrupt();
return;
} catch(InvocationTargetException ex) {
// This can actually only be a RuntimeException or an
// Error - in either case we want to rethrow them
Throwable target = ex.getTargetException();
if (target instanceof RuntimeException) {
throw (RuntimeException)target;
} else if (target instanceof Error) {
throw (Error)target;
}
ex.printStackTrace(); // this should not happen!
throw new RuntimeException(ex.toString());
}
}
}
}
This highlights again that we have to be quite careful with Java.
In the big project that we work on, we have standardized on the
JDK 1.3 compiler and ALL our classes have to be compiled with
that. This happened only after much nailbiting because of slight
compiler differences of various IDEs.
GUI Articles
Related Java Course
Discuss at The Java Specialist Club
|