CSC/ECE 517 Fall 2009/wiki2 18 ee: Difference between revisions
(33 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
==Introduction== | ==Introduction== | ||
When the need to serialize objects in Java arises, the most common tool is the Serializable interface. This interface is simply used to indicate that the object is serializable. | Serialization is the process of converting an object or many objects into a form that can be either written to disk or transmitted across the network. The idea being that these can be read back and loaded as objects within an environment, called de-serialization. Imagine having an application with user objects. When the application is shut down, the objects are written to disk. When the application is started back, the user objects are read from disk and initialized as objects. The objects themselves would be in the exact same state as they were before the system was shut down. [[#ref_3|[3]]] | ||
Immutable objects aid in ensuring thread safety, since they cannot be changed. [[#ref_4|[4]]] | |||
Here is a dipiction of normal serialization. This shows the Person class being serialized and de-serialized: | |||
[[Image:Serial noproxy ee.jpg]] | |||
When the need to serialize objects in Java arises, the most common tool is the Serializable interface. This interface is simply used to indicate that the object is serializable. | |||
Here is a simple example of serialization in java: | |||
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("/tmp/foo")); | |||
stream.writeObject(myObject); | |||
stream.close(); | |||
This would serialize the object "myObject" into the file "/tmp/foo". Here is a simple example of deserialization: | |||
ObjectInputStream stream = new ObjectInputStream(new FileInputStream("/tmp/foo")); | |||
Object myObject = stream.readObject(); | |||
stream.close(); | |||
This would take the data in /tmp/foo and deserialize it into the myObject object. [[#ref_6|[6]]] | |||
==The Problem== | ==The Problem== | ||
One issue with serialization under Java is the need for serialization of immutable classes. Take the following class for example: | One issue with serialization under Java is the need for serialization of immutable classes. These are classes that after creation, cannot be modified. Take the following class for example: | ||
public class Person { | public class Person { | ||
Line 25: | Line 50: | ||
} | } | ||
Once the constructor is called, neither name or age can be changed. This class is immutable. [[#ref_6|[6]]] | |||
The class is easily serializable with no changes, and could be written to disk easily. A problem arises when the object needs to be de-serialized. | |||
Normally when Java is de-serializing an object, it would call the default constructor Person() and then call the setter on each object attribute. With this object there is no default constructor, nor are there setters for the object's attributes. This was done intentionally to keep the object from changing. Serialization Proxy pattern comes into play here. | |||
==The Proxy Object== | |||
To work around the fact that we can't deserialize an immutable class, we use a proxy object that is an inner class of the class we want to serialize. [[#ref_1|[1]]] We could visually represent it as follows: | |||
[[Image:SerialProxy lee.jpg]] | |||
To | To see this in code we would change the Person class as follows: | ||
Line 51: | Line 83: | ||
private static class Proxy | private static class Proxy implements Serializable { | ||
String name; | String name; | ||
Integer age; | Integer age; | ||
public Proxy() { } | public Proxy() { } | ||
public Proxy(Person person) { | public Proxy(Person person) { | ||
Line 60: | Line 92: | ||
age = person.age(); | age = person.age(); | ||
} | } | ||
Object readResolve() { | Object readResolve() { | ||
return new Person(name, age); | return new Person(name, age); | ||
Line 67: | Line 100: | ||
So what changed? A private static class was added that is | So what changed? | ||
* A private static class was added that is Serializable and holds all the same information as the Person class. | |||
* An inner private method called writeReplace() is added to the Parent class. [[#ref_2|[2]]] | |||
=== Serialization === | === Serialization === | ||
Line 81: | Line 117: | ||
During deserialization, the following occurs: | During deserialization, the following occurs: | ||
# The Proxy object is deserialized, resulting in a Proxy object. Since the member variables of the Proxy object are public, it can be deserialized with no issue. | # The stored Proxy object is deserialized, resulting in a Proxy object. Since the member variables of the Proxy object are public, it can be deserialized with no issue. | ||
# The Proxy object is examined to determine if it has a readResolve() method. | # The Proxy object is examined to determine if it has a readResolve() method. | ||
# Since it does, readResolve() is called, returning a new Person immutable object. | # Since it does, readResolve() is called, returning a new Person immutable object. | ||
===Benefits=== | |||
* The ability to serialize immutable objects. | |||
* The interface of the immutable object does not have to be changed | |||
===Drawbacks=== | |||
* Slower than normal serialization | |||
* Cannot handle some objects with circular object graphs. The following is an example of a circular object graph: | |||
public class A { | |||
private B classB; | |||
public A(){} | |||
public getClassB() { return classB }; | |||
} | |||
public class B { | |||
private A classA; | |||
public B(){} | |||
public getClassA() { return classA }; | |||
} | |||
In this example, class A holds an instance to class B and class B holds an instance to class A. | |||
[[#ref_7|[7]]] | |||
==Definitions== | ==Definitions== | ||
* Serialization - The process of converting an object into a form more suitable for storage or transmission. [[#ref_3|[3]]] | |||
* Deserialization - The process of converting data read from disk or received from a transmission into object form. [[#ref_3|[3]]] | |||
* Immutable Object - An object who's attributes cannot be changed after creation. [[#ref_5|[5]]] | |||
* Thread Safety - the ability of a piece of software to be executed by multiple threads at the same time without malfunctioning. [[#ref_4|[4]]] | |||
==References== | ==References== | ||
http://stackoverflow.com/questions/702357/what-is-the-serialization-proxy-pattern | <div id="ref_1" />[1] [http://stackoverflow.com/questions/702357/what-is-the-serialization-proxy-pattern What is the serialization proxy pattern ] | ||
http://lingpipe-blog.com/2009/08/10/serializing-immutable-singletons-serialization-proxy/ | <div id="ref_2" />[2] [http://lingpipe-blog.com/2009/08/10/serializing-immutable-singletons-serialization-proxy/ Serializing Immutable Singletons] | ||
<div id="ref_3" />[3] [http://en.wikipedia.org/wiki/Serialization Serialization ] | |||
<div id="ref_4" />[4] [http://en.wikipedia.org/wiki/Thread_safety Thread Safety] | |||
<div id="ref_5" />[5] [http://www.javaranch.com/journal/2003/04/immutable.htm Mutable and Immutable Objects] | |||
<div id="ref_6" />[6] [http://java.sun.com/developer/technicalArticles/Programming/serialization/ Discover the Secrets of the Java Serialization API] | |||
<div id="ref_7" />[7] [http://books.google.com/books?id=ka2VUBqHiWkC&pg=PA312&lpg=PA312&dq=serialization+proxy&source=bl&ots=yXHkMnp_N1&sig=8sTsZWu1ZOaf-cuozd7eQ60JiP8&hl=en&ei=FErVSpHxGeGJtgeF692pAw&sa=X&oi=book_result&ct=result&resnum=6&ved=0CBwQ6AEwBQ#v=onepage&q=serialization%20proxy&f=false Effective Java 2nd Edition page 312] |
Latest revision as of 03:53, 14 October 2009
Serialization Proxy Design Pattern
During system design, immutable classes are preferred to guarantee thread safety and consistent object state. For instance, serialization of immutable classes could cause issues in Java if immutability must be preserved. The Serialization Proxy Pattern aims to make serialization acceptable in that regard. Discuss serialization proxy pattern with regards to the problem, design, implementation details, and idiomatic usage.
Introduction
Serialization is the process of converting an object or many objects into a form that can be either written to disk or transmitted across the network. The idea being that these can be read back and loaded as objects within an environment, called de-serialization. Imagine having an application with user objects. When the application is shut down, the objects are written to disk. When the application is started back, the user objects are read from disk and initialized as objects. The objects themselves would be in the exact same state as they were before the system was shut down. [3]
Immutable objects aid in ensuring thread safety, since they cannot be changed. [4]
Here is a dipiction of normal serialization. This shows the Person class being serialized and de-serialized:
When the need to serialize objects in Java arises, the most common tool is the Serializable interface. This interface is simply used to indicate that the object is serializable.
Here is a simple example of serialization in java:
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("/tmp/foo")); stream.writeObject(myObject); stream.close();
This would serialize the object "myObject" into the file "/tmp/foo". Here is a simple example of deserialization:
ObjectInputStream stream = new ObjectInputStream(new FileInputStream("/tmp/foo")); Object myObject = stream.readObject(); stream.close();
This would take the data in /tmp/foo and deserialize it into the myObject object. [6]
The Problem
One issue with serialization under Java is the need for serialization of immutable classes. These are classes that after creation, cannot be modified. Take the following class for example:
public class Person { String name; Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public String name() { return name; } public Integer age() { return age; } }
Once the constructor is called, neither name or age can be changed. This class is immutable. [6]
The class is easily serializable with no changes, and could be written to disk easily. A problem arises when the object needs to be de-serialized.
Normally when Java is de-serializing an object, it would call the default constructor Person() and then call the setter on each object attribute. With this object there is no default constructor, nor are there setters for the object's attributes. This was done intentionally to keep the object from changing. Serialization Proxy pattern comes into play here.
The Proxy Object
To work around the fact that we can't deserialize an immutable class, we use a proxy object that is an inner class of the class we want to serialize. [1] We could visually represent it as follows:
To see this in code we would change the Person class as follows:
public class Person { private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public String name() { return name; } public Integer age() { return age; } private Object writeReplace() { return new Proxy(this); } private static class Proxy implements Serializable { String name; Integer age; public Proxy() { } public Proxy(Person person) { name = person.name(); age = person.age(); } Object readResolve() { return new Person(name, age); } } }
So what changed?
- A private static class was added that is Serializable and holds all the same information as the Person class.
- An inner private method called writeReplace() is added to the Parent class. [2]
Serialization
During serialization, the following occurs:
- The object is checked to see if writeReplace() is defined for the Person object.
- The writeReplace() function is called to retrieve the proxy object.
- Serialization takes place on the proxy object instead.
Deserialization
During deserialization, the following occurs:
- The stored Proxy object is deserialized, resulting in a Proxy object. Since the member variables of the Proxy object are public, it can be deserialized with no issue.
- The Proxy object is examined to determine if it has a readResolve() method.
- Since it does, readResolve() is called, returning a new Person immutable object.
Benefits
- The ability to serialize immutable objects.
- The interface of the immutable object does not have to be changed
Drawbacks
- Slower than normal serialization
- Cannot handle some objects with circular object graphs. The following is an example of a circular object graph:
public class A { private B classB; public A(){} public getClassB() { return classB }; } public class B { private A classA; public B(){} public getClassA() { return classA }; }
In this example, class A holds an instance to class B and class B holds an instance to class A.
Definitions
- Serialization - The process of converting an object into a form more suitable for storage or transmission. [3]
- Deserialization - The process of converting data read from disk or received from a transmission into object form. [3]
- Immutable Object - An object who's attributes cannot be changed after creation. [5]
- Thread Safety - the ability of a piece of software to be executed by multiple threads at the same time without malfunctioning. [4]