Download Persistence and using Beans from Applications

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Persistence
COMP434 Software
Design

Serialization - is the ability to save the state
of several objects to a stream

Persistence & using Beans from
applications

The stream is typically associated with a file,
but need not be (eg sending serialized objects
over a network connection)
Deserialization - is the ability to restore the
state of several objects from a stream
2
1
Persistence

Persistence
If an object contains references to other
objects, these are also saved


The process is automatic and recursive
Only nonstatic and nontransient parts of an
object’s state are saved by serialization

Static fields are considered part of the state of a class,
not the state of an object

A
1
2

C
B
4
3
D
5
8
6
7

E
9
Transient fields are not saved, since they contain
temporary data not needed to correctly restore the
object later
Some type info is also saved so the object can be
reconstructed properly
3
4
Persistence

Persistence
When an object is deserialized, none of its
constructors are invoked

Instead, memory is allocated and the
variables are set directly from the data that is
read from the serial stream
 Some extra work needs to be done if
constructors perform actions that are
essential to getting an object running correctly


Static fields are sometimes initialized by static initialization
blocks that are executed when a class is loaded
The Serializable interface in the java.io
package defines no constants or methods
It exists simply to designate that an object
may be saved to and restored from a stream
 An object can only be serialized if its class
implements this interface


Eg. Starting threads

5
A java.io.NotSerializableException is generated
if an attempt is made to serialize any object whose
class has not been defined in this manner
All Beans should implement this interface
6
1
Persistence



A Serializable Bean
Many of the classes provided with the JDK libraries
have been designed to be serializable
Eg. all of the Swing classes are Beans and are therefore
serializable
Objects of type Thread are not serializable


Implementation of threads is tightly coupled with the particular
platform on which the JVM (java virtual machine) is running
Almost none of the classes in java.io are serializable

Graph - shows six nodes positioned at the
corners of a hexagon
Uses a Node class for displaying nodes and a
Link class for drawing edges between nodes
 Graph is serializable because all of its classes
either directly or indirectly implement
Serializable

However, there are many other types in the Java
class libraries that are not serializable


Ridiculous to consider “freezing” info about file handles, read/
write positions etc and expect to use it later - even on the same
machine
7
package graphs;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.JPanel;
public class Graph extends JPanel
implements MouseListener, MouseMotionListener {
private final static int NNODES = 6;
private Vector nodes;
private Vector links;
private transient Node node1, node2;
private transient int x, y;
public Graph() {
Dimension d = new Dimension(200, 200);
setMinimumSize(d); setPreferredSize(d); setMaximumSize(d);
nodes = new Vector();
links = new Vector();
addMouseListener(this);
addMouseMotionListener(this);
makeNodes();
} . . .
9
public void mouseReleased(MouseEvent me) {
// Make a link between node1 and node2
x = me.getX();
y = me.getY();
if(node1 != null) {
Enumeration e = nodes.elements();
while(e.hasMoreElements()) {
node2 = (Node)e.nextElement();
if(node2.contains(x, y)) {
makeLink(node1.getId(), node2.getId());
break;
}
}
node1 = node2 = null;
repaint();
}
}
11
. . .
8
public void mousePressed(MouseEvent me) {
// Check if node1 should be initialized
x = me.getX();
y = me.getY();
Enumeration e = nodes.elements();
while(e.hasMoreElements()) {
node1 = (Node)e.nextElement();
if(node1.contains(x, y)) {
return;
}
}
node1 = null;
}
. . .
10
public void mouseDragged(MouseEvent me) {
x = me.getX();
y = me.getY();
repaint();
}
. . .
12
2
package graphs;
import java.awt.*;
import java.io.*;
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw nodes
for (int i = 0; i < nodes.size(); i++) {
((Node)nodes.elementAt(i)).draw(g);
}
// Draw links
for (int i = 0; i < links.size(); i++) {
((Link)links.elementAt(i)).draw(g);
}
// Draw rubber band line (if any)
if(node1 != null) {
g.drawLine(node1.getX(), node1.getY(), x, y);
}
}
public class Node implements Serializable {
private final static int NODERADIUS = 10;
private static int count = 0;
private int x, y, id;
public Node(int x, int y) {
this.x = x; this.y = y;
id = count++;
}
. . .
public boolean contains(int x, int y) {
int deltax = this.x – x;
int deltay = this.y – y;
int a = deltax * deltax + deltay * deltay;
int b = NODERADIUS * NODERADIUS;
return (a <= b);
}
. . .
} // end Node.java
. . .
// end Graph.java
13
14
Serialization Streams

Serialization Streams
Java provides stream classes to aid in the
serialization of Beans


ObjectOutputStream - in the java.io package
provides methods to serialize objects, arrays and
simple types to an output stream

Some methods:




void writeObject(Object o) - writes o to the stream
void defaultWriteObject() - writes the nonstatic and
nontransient fields of the current object to the stream (often
used during custom serialization)
void close() - closes the stream
Also assorted methods to write floats, chars, strings, arrays
etc. to the stream
ObjectStreamClass - in the java.io package
encapsulates information about a serialized
object

Instances of this class are created and stored in the
serial stream

This is the mechanism by which type information is
saved

Contains the name of the class and a long named
serialVersionUID

Unique identifier calculated from the class name and its
members (used for versioning)
15
16
Serialization Examples
Serialization Streams

ObjectInputStream - in the java.io package
provides methods to deserialize objects, arrays and
simple types from an input stream

Some methods:

Object readObject() - reads an object from the stream

void defaultReadObject() - reads the nonstatic and
nontransient fields of the current object from the stream (often
used during custom deserialization)

int available() - returns the number of bytes that are available for
reading

Also assorted methods to read floats, chars, strings, arrays etc.
from the stream
17

Saving and restoring objects

Two classes: one to save a Vector of objects to
a file and the other to read them in
18
3
package serial;
package serial;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.io.*;
public class Save1 {
public static void main(String args[]) {
try {
Vector v = new Vector();
v.addElement(new Integer(-7));
v.addElement(new Rectangle(20, 20, 100, 50));
v.addElement("Hello");
System.out.println(v);
FileOutputStream fos = new FileOutputStream("save1.data");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(v);
oos.flush();
fos.close();
} catch(Exception ex) {
System.out.println("Exception: " + ex);
}
}
}
public class Restore {
public static void main(String args[]) {
try {
FileInputStream fis =
new FileInputStream(“save1.data”);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
fis.close();
System.out.println(obj);
} catch(Exception ex) {
System.out.println("Exception: " + ex);
}
}
}
19
import java.awt.*;
import java.io.*;
Serialization Examples

20
Saving and restoring simple types and
your own objects
21
class Person implements Serializable {
private String name, phone;
public Person(String name, String phone) {
this.name = name;
this.phone = phone;
}
public String toString() {
return "[" + name + "," + phone + "]";
}
}
23
public class Save2 {
public static void main(String args[]) {
try {
FileOutputStream fos;
fos = new FileOutputStream("save2.data");
ObjectOutputStream oos;
oos = new ObjectOutputStream(fos);
oos.writeInt(5);
oos.writeDouble(Math.PI);
oos.writeBoolean(true);
oos.writeObject(Color.blue);
oos.writeChar('a');
oos.writeObject(new Person("Joe", "7834"));
oos.flush();
fos.close();
}
catch(Exception ex) {
System.out.println("Exception: " + ex);
}
}
}
22
package serial;
import java.io.*;
public class Restore2 {
public static void main(String args[]) {
try {
FileInputStream fis =
new FileInputStream("save2.data");
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readBoolean());
System.out.println(ois.readObject());
System.out.println(ois.readChar());
System.out.println(ois.readObject());
fis.close();
}
catch(Exception ex) {
System.out.println("Exception: " + ex);
}
}
24
}
4
Serialization Examples

Serialization Examples
Custom serialization

Sometimes the default serialization is not sufficient to save
and restore the state of an object

There are two methods provided by the Java designers for
this





Thread example:
Clock Bean that displays the current time in
hours, minutes and seconds
 Internally uses a Thread to update the
display every second

Handle Threads, static variables etc.
private void writeObject(ObjectOutputStream oos) throws
IOException
private void readObject(ObjectInputStream ois) throws
IOException

Thread class is not serializable
These methods have two unusual characteristics:


They are not part of any interface to be implemented or class to be
extended
Even though the serialization support calls readObject and
writeObject they must be declared private methods
25
package clock;
import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.JPanel;
import javax.swing.JLabel;
public class Clock extends JPanel implements Runnable {
private JLabel tf;
private transient Thread thread;
public Clock() {
tf = new JLabel("");
add(tf);
startThread();
}
. . .
27
26
private void startThread() {
thread = new Thread(this);
thread.start();
}
// implement the run method from Runnable
public void run() {
try {
SimpleDateFormat sdf;
sdf = new SimpleDateFormat("HH:mm:ss");
while(true) {
Thread.sleep(1000); // sleep for 1 second
tf.setText(sdf.format(new Date()));
}
} catch(Exception ex) { ex.printStackTrace(); }
}
private void readObject(ObjectInputStream ois)
throws IOException {
try {
ois.defaultReadObject();
startThread();
} catch(Exception ex) { ex.printStackTrace(); }
}
} // end Clock.java
Applications


Applications
Applications can dynamically create
instances of Beans

28

Some methods in java.beans.Beans
Object instantiate(ClassLoader clsLoader,
String beanName)
Component software philosophy - an
application need not provide every part of its
functionality, instead it can enlist the aid of
various components as needed
Uses clsLoader to instantiate the component named
beanName. If clsLoader is null, the System Class Loader is used
boolean isDesignTime()

Returns true if the execution environment is provided by a
builder tool
boolean isGuiAvailable()

The Beans class in java.beans has several
static methods to instantiate a Bean or
obtain information about its environment
Returns true if the execution environment supports an
interactive GUI
boolean isInstanceOf(Object bean, Class cls)
 Returns true if bean is an instance of cls

29
30
5
package applications;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import spectrum2.*;
Examples

SpectrumApplication

Creates a JFrame, instantiates a Spectrum2
Bean, modifies its vertical property, adds the
Bean to the JFrame and makes the frame
visible

Requires that spectrum2 is in the
CLASSPATH
public class SpectrumApplication {
public static void main(String args[]) {
try {
final javax.swing.JFrame jf =
new javax.swing.JFrame("Spectrum application");
jf.setSize(200, 200);
jf.getContentPane().setLayout(null);
Spectrum2 spectrum =
(Spectrum2)Beans.instantiate(null, "spectrum2.Spectrum2");
spectrum.setVertical(false);
Dimension d = spectrum.getPreferredSize();
// reposition the Bean at 50, 50 and add to the frame
spectrum.setBounds(50, 50, d.width, d.height);
jf.getContentPane().add(spectrum);
. . .
31
jf.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
jf.dispose();
System.exit(0);
}
});
jf.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
32
Examples

ColourSelectorApplication

Uses Selector and Painter Beans from the
cselector package (lecture 2)

}
} // end SpectrumApplication

Repackaged into cselector2 with a
BeanInfoClass for the Selector Bean that
specifies that Selector generates only one type of
event - a ColorEvent
Requires that cselector2 is in the
CLASSPATH
33
Examples

ColourSelectorApplication
1.
2.
3.
4.
5.
6.
Creates a JFrame, instantiates a Selector Bean and a
Painter Bean
Uses Introspection to obtain a BeanInfo object for the
Selector bean
Obtains the EventSetDescriptor for the first (and only)
event generated by Selector
Obtains the a Class object for the type of the listener
interface for this event and checks to see if Painter
implements this interface
Obtains a Method object representing the registration
method for the event type
Calls the invoke method in the registration method object
to register Painter to receive event notifications from
35
Selector
34
package applications;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import java.beans.*;
import cselector2.*;
public class ColourSelectorApplication {
public static void main(String argv[]) {
try {
final javax.swing.JFrame jf =
new javax.swing.JFrame("Colour selector application");
jf.setSize(270, 250);
jf.getContentPane().setLayout(null);
Painter painter =
(Painter)Beans.instantiate(null, "cselector2.Painter");
Selector selector =
(Selector)Beans.instantiate(null, "cselector2.Selector");
Class selectorClass = selector.getClass();
BeanInfo bi1 = null;
try {
bi1 = Introspector.getBeanInfo(selectorClass);
} catch(Exception ex) {
ex.printStackTrace(); System.exit(1);
36
}
6
// Get the EventSetDescriptor objects selector
EventSetDescriptor [] esds = bi1.getEventSetDescriptors();
// Get the listener class for the first event type
Class listenerType = esds[0].getListenerType();
// Check to see if Painter implements this listener
if (Beans.isInstanceOf(painter, listenerType)) {
// now try to register Painter with Selector to receive
// this type of event.
// First obtain the registration method
Method registerMethod = esds[0].getAddListenerMethod();
// Invoke the registration method of Selector to
// register Painter
Object args[] = new Object[1];
args[0] = painter;
try {
registerMethod.invoke(selector, args);
} catch(Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
Examples

ColourSelectorApplication2
Similar to the first example but uses a
dynamic EventHandler to link the Painter to
the Selector
 Uses introspection to find out about events,
properties and methods

37
. . . // the rest is similar to SpectrumApplication (see source)
38
// Get the EventSetDescriptors for the source bean
EventSetDescriptor [] esds = bi1.getEventSetDescriptors();
// Get the named source and target & instantiate them
String source = argv[0]; String target = argv[1];
Object sourceO = Beans.instantiate(null, source);
Object targetO = Beans.instantiate(null, target);
// Store class objects for the source and target
Class sourceClass = sourceO.getClass();
Class targetClass = targetO.getClass();
System.out.println("Events:");
for (int i = 0; i < esds.length; i++) {
System.out.println("("+i+") "+esds[i].getName());
}
System.out.print("Choose event: ");
char c;
String result = "";
while ((c = (char)System.in.read()) != '\n') {
result += c;
}
// Get the listener class for the chosen event type
Class listenerType =
esds[Integer.parseInt(result)].getListenerType();
// Store the registration method for this listener type
Method registerMethod =
esds[Integer.parseInt(result)].getAddListenerMethod();
BeanInfo bi1 = null;
BeanInfo bi2 = null;
try {
bi1 = Introspector.getBeanInfo(sourceClass);
bi2 = Introspector.getBeanInfo(targetClass);
}…
. . .
. . .
39
// Get the method descriptors from the target
MethodDescriptor [] md = bi2.getMethodDescriptors();
System.out.println("\nTarget methods: ");
for (int i = 0; i < md.length; i++) {
Class [] paramTypes = md[i].getMethod().getParameterTypes();
// Print out only target methods that take a single argument
if (paramTypes.length == 1) {
System.out.print("("+i+") "+md[i].getName()+"( ");
for (int j = 0; j < paramTypes.length; j++) {
System.out.print(paramTypes[j].getName()+" ");
}
System.out.println(")");
}
}
System.out.print("Choose target method: ");
result = "";
while ((c = (char)System.in.read()) != '\n') {
result += c;
}
// Store the parameter type of the chosen method and the method
Class targetArg =
md[Integer.parseInt(result)].getMethod().
getParameterTypes()[0];
41
Method targetMethod = md[Integer.parseInt(result)].getMethod();
40
// Look for source properties that are the same type as
// the targetArg
PropertyDescriptor [] pds = bi1.getPropertyDescriptors();
System.out.println("\nMatching source getter methods: ");
for (int i = 0; i < pds.length; i++) {
// Get the read method of this property
Method rm = pds[i].getReadMethod();
if (rm != null) {
// Find out the return type
Class sourceRRT = rm.getReturnType();
if (sourceRRT.getName().equals(targetArg.getName())) {
System.out.println("("+i+") "+rm.getName());
}
}
}
System.out.print("Choose getter method: ");
result = "";
while ((c = (char)System.in.read()) != '\n') {
result += c;
}
// Store the read method for the source property
Method sourceProperty =
pds[Integer.parseInt(result)].getReadMethod();
42
7
// Make a dynamic handler that implements the listener
// interface for the chosen event type
Object handler =
EventHandler.create(listenerType, targetO,
targetMethod.getName(),
"source."+sourceProperty.getName());
// Invoke the registration method of source to
// register the handler
Object args[] = new Object[1];
args[0] = handler;
try {
registerMethod.invoke(sourceO, args);
} catch(Exception ex) {
ex.printStackTrace(); System.exit(1);
}
43
8