By adding serialization to a bean you allow it to save itselfto
persistenteeven after it has been customized in a builder tool.
In this lesson, you will add methods to NervousText03.java to write the beans
state to disk and to read the bean back into memory from its serialized
representation on disk. One of the important tricks involved is knowing what
fields of the bean need to be made transient, in which case their state is not
saved or restored. For example the state of a thread (running, stopped, waiting)
cannot be saved and restored through serialization. Therefore any fields
refering to threads must be marked as transient.
Step 1. Add import
Statment for Serilization
Add the following lines at the end of the existing import statements.
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
to the other import statements in NervousText03.java
It's also a good idea to add support for excptions that can occur while reading
or writing a serialized bean to a file. Add the following import statment after
the two you just added:
import java.io.IOException;
This should take care of any trouble your bean may have when reading the saved
object's state from disk. The beginning of the file should now look like this:
package sun.beanbox.beans;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
public class NervousText03 extends Panel
implements Runnable, MouseListener {
...
Step 2. Make thread
Fields transient
Any thread fields declared inside a class whose instances are to be serialized
must be marked as transient. This is because at the time a serialzed bean is
reinstaniated, the original context under which the program was running no longer
exists. There are other types of objects which can not be serialized. They too
must be marked as transient. Refer to documentation on object serialiazation
for details.
Following this requirement, the killme
in NervousText03
must be marked as transient.
Change the line
Thread killme = null;
to
transient Thread killme = null;
You can't save the context of a thread and reload it in the same state because
the thread's state depends on the runtime environment.
The instance fields declared in NervousText03
now look like this.
public class NervousText03 extends Panel
implements Runnable, MouseListener {
char separated[];
String s = null;
transient Thread killme = null;
int i;
int x_coord = 0, y_coord = 0;
String num;
int speed=35;
int counter =0;
boolean threadSuspended = false; //added by kwalrath
boolean lefttoright = true;
...
Step 3. Add Serialization Methods for Persistence
Now you're ready to add the writeObject
and readObject
serialization methods to NervousText03. When writing the object you can determine
whether the NervousText bean is running or not. When reading the serialized
representation of the bean back into memory you must initialize the thread
again.
Add the following definitions for writeObject
and
readObject
at the end of the class.
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
if(killme == null)
s.writeBoolean(false);
else
s.writeBoolean(true);
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
if(s.readBoolean()==false)
killme=null;
else
start();
}
Step 4. Build the JAR and Install it in the BeanBox
Compile NervousText03.java:
javac -d . NervousText03.java
Create the mainfest:
echo "Manifest-Version: 1.0" > manifest.tmp
echo "" >> manifest.tmp
echo "Name: sun/beanbox/beans/NervousText03.class"
>> manifest.tmp
echo "Java-Bean: True" >> manifest.tmp
The resulting temporary manifest file should look like this:
Manifest-Version: 1.0
Name: sun/beanbox/beans/NervousText03.class
Java-Bean: True
Create the JAR file:
jar cfm NervousText03.jar manifest.tmp
sun/beanbox/beans/NervousText03.class
Remove the temporary manifest and install the JAR in the BeanBox jars directory
(substituting your BDK installation directory for BDK_HOME:
rm manifest.tmp
cp -p NervousText03.jar BDK_HOME/beans/jars
Step 6. Test NervousText03 in the BeanBox
To test that serialziation is working, first build a simple application by
performing the same steps in the BeanBox that you did in the previous lesson.
Run the BeanBox by switching to your BDK_HOME/beans/beanbox directory. Invoke
run.sh
(UNIX) or run.bat
(Window/DOS). Select an
OurButton bean from the menu and place it in the BeanBox. Select a
NervousText03 bean from the menu, placing it in the BeanBox below the button.
Use the Edit menu to choose Edit->Events->action->actionPerformed.
Join the event line to NervousText03 by clicking over the NervousText03
component. When the EventTargetDialog appears, select the changeDirection
method and click on the OK button. Pressing OurButton should now cause the
text displayed by the NervousText03 button to be reversed from right to left.
Change the text property of NervousText03 to read "Anxious Text". Do
this by selecting the Press the OurButton, to reverse the order of the text so
it displays backwards. You're now ready to save the serialized state of all
components displayed in the BeanBox.
Serialize the BeanBox components by choosing the menu item File->Save. A
file dialog box appears to let you specify the file name for the application.
Enter NervousText03.beanbox for the filename and press OK. The BeanBox
application has now been serialzed and saved to disk.
Be aware that this is not a true application since it will run only in the
BeanBox. However the same steps would be performed to create a real application
in a beans-enabled builder tool.
Clear the BeanBox. Choose the menu item File->Clear. All components should
disappear. You're now ready to reload the application. Choose the menu item
File->Load. A Load File dialog appears. Select NervousText03.beanbox from
the Files pane and press OK. The application appears exactly as it did when
you saved it.
Step 7. Reheating Your Flambee
Notice when the saved file is restored, the text is reversed and is set to the
same string you specified in the property sheet editor. Also notice, that the
application comes up in a running state. That's because NervousText03 simulates
the saving of the bean's thread state by appending the value of the boolean
variable, killme
at the end of the serialized output stream when
the bean is serialized to disk. It does this by calling writeBoolean
on the ObjectOutputStream used to serialze the bean
with an
argument of either true or false, depending on the value of killme
:
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
if(killme == null)
s.writeBoolean(false);
else
s.writeBoolean(true);
}
Because the thread was running when you saved the application, the code to
reinstantiate the bean in readObject
gets a value of true when it
calls readBoolean
immediately after reinstantiating the bean with
defaultReadObject
.
Here's the full definition:
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
if(s.readBoolean()==false)
killme=null;
else
start();
}
If killme
was true when the bean was saved, the bean's
start
method is called to reactivate the bean when it is
reinstantiated. Had you saved out the appplication with the thread suspended,
the thread would not run when you reinstantiated the bean. This is what Calvin
is talking about when he says you need to relight the fire get the flambee
heated again. As an exercise, try adding two more OurButtons. Label them
"stop" and "start". First label the existing button
"change direction."
You'll have to figure out how to hook up the action events generated by the
start and stop buttons to the appropriate handlers to start and stop the thread
in the NervousText03 bean. If you need a hint, go back and review how this was
done with the original OurButton used to change the text's direction. Now stop
the application by pressing the stop button, serialize it, clear the bean box
and reload it. Then press the start button and try the exercise again.
Program Source Code
The makefile for this lesson automates
source code compilation, JAR file construction, and copying of JAR files to
the appropriate BeanBox directory. You'll have to edit several of the variables
in the makefile to indicate the location of your JDK 1.1 and BDK installation
directories.
You may want to look at the final source file for
NervousText Bean, Version 03 to
verify the changes you have made to the original NervousText.java file.