Persistence and Customizer of JavaBeans

1. PERSISTENCE

Sometimes, it is necessary to store the beans for later use. Persistence is a procedure to save a bean in non-volatile storage such as a file. The bean can be reconstructed and used later. The important point is that persistence allows bean developers to save the current state of the bean and retrieve the same at some later point of time.

To understand the importance of persistence, let us understand the life cycle of a bean. A bean is first created (possibly using a builder tool). Then its properties are accessed and/or manipulated by calling its public methods. After a degree of use, the bean is no longer needed, and is destroyed and removed from the memory. This is a typical life cycle of a bean. However, think about a situation where you have decided to complete your application temporarily but use of the bean is not yet over. You want the same bean with the state of the bean unchanged whenever the application is restarted later. Persistence is a procedure that does exactly what we have described here.

Let us consider a simple example. Consider the following Factorial bean.

//Factorial.java import java.io.*;

public class Factorial implements Serializable {

protected int n; public int getN() {

return n;

}

public void setN(int n) {

this.n = n; long prod = 1;

for(int i = 2; i <= n; i++) prod *= i;

fact = prod;

}

protected long fact; public long getFact() {

return fact;

}

}

This bean has two properties, n and fact. The property n has a get method and a set method and fact has only a get method. The getFact() method returns the factorial of n, which can be specified using the setN() method. So, this bean can be used to create a factorial table. Suppose we want to create a table containing factorial of numbers from 2 to 10. So, we can write a code like this:

Factorial f = new Factorial();

for(int i = 2; i <= 10; i++) {

f.setN(i);

System.out.println(i + “! = ” + f.getFact()+ ” “);

}

However, during the calculation, assume that an external interrupt may occur and in such a case, the application must be terminated. Before terminating, we must save the state of the bean so that we can retrieve the value of the integer up to which we calculated the factorial, so as to find the factorial of the rest of the integers. Java’s Serialization procedure may be used to save and retrieve the state of a bean. An object is said to be serializable if its class implements the Serializable interface and all members are serializable. The Serializable interface does not define any method; it merely indicates that the class implementing it can be serialized. The following code shows how to save the state of a bean.

//SaveBean.java import java.io.*; public class SaveBean {

public static void main(String args[]) {

try {

Factorial f = new Factorial();

for(int i = 2; i < 10; i++){

f.setN(i);

System.out.println(i + ”! = ” + f.getFact()+ ” ”);

if(i > Math.random()*10 ) break;

}

//save the state of f now

FileOutputStream fos = new FileOutputStream(“out.dat”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(f);

oos.close();

System.out.println(”Factorial bean saved in file out.dat”);

}catch(Exception e) {e.printStackTrace();}

}

}

The following code demonstrates how to retrieve the bean with its original state.

//RetrieveBean.java

import java.io.*;

public class RetriveBean {

public static void main(String args[]) {

try {

FileInputStream fis = new FileInputStream(“out.dat”);

ObjectInputStream ois = new ObjectInputStream(fis);

Factorial f1 = (Factorial)ois.readObject(); ois.close();

System.out.println(”Factorial bean retrieved from file out.dat”);

for(int i = f1.getN()+1; i <= 10; i++)                    {

f1.setN(i);

System.out.println(i + ”! = ” + f1.getFact()+ ” ”);

}

}catch(Exception e) {e.printStackTrace();}

}

Figure 26.9 shows a sample output that is obtained if you run these two applications.

The JavaBean framework provides a utility class, XMLEncoder, which allows us to save a bean in XML format. The following example shows how to save a bean as an XML file:

XMLEncoder encoder = new XMLEncoder(

new BufferedOutputStream(new FileOutputStream(”fact.xml”)));

encoder.writeObject( f );

encoder.close();

It creates the following XML document:

<?xml version=”1.0” encoding=”UTF-8”?>

<java version=”1.6.0_10-beta” class=”java.beans.XMLDecoder”>

<object class=”Factorial”>

<void property=”n”>

<int>6</int>

</void>

</object>

</java>

The bean can later be retrieved from this XML document using the following code:

XMLDecoder decoder = new XMLDecoder(

new BufferedInputStream(new FileInputStream(”fact.xml”)));

f1 = (Factorial)decoder.readObject();

decoder.close();

The object fi refers to the original bean now.

2. CUSTOMIZER

Bean customization allows us to customize the appearance and behaviour of a bean at design time, within a bean-compliant builder tool. There are two ways to customize a bean:

  • Using a property editor
  • Using Customizers

Property editors are usually supplied by the builder tool, although you can write your own property editor. In this section, we shall discuss how to customize a bean’s appearance and behaviour using customizers.

A property editor usually displays all properties that can be manipulated. Sometimes, it is not a good idea to display a large number of properties, most of which are irrelevant. A Customizer class gives us complete control to configure and edit beans. Customizers are used when a specific instruction is needed and property editors are too primitive for this purpose. A Customizer class must do the following:

  • A Customizer must be some kind of AWT component that is suitable for display in a dialog box created by the BeanBox. So, it must extend awt.component or one of its subclasses. Typically, the Customizer class extends Panel.
  • It must implement the customizer This interface looks like this:

public interface java.beans.Customizer{

public abstract void setObject(java.lang.Object);

public abstract void addPropertyChangeListener(java.beans.PropertyCha ngeListener);

public abstract void removePropertyChangeListener(java.beans.Property ChangeListener);

}

So, the Customizer class must implement those properties. It must also fire PropertyChangeEvent to all registered listeners when a change to the target Bean has occurred.

  • Implement a default constructor
  • Associate the customizer with its target class via getBeanDescriptor

If a Bean that has an associated Customizer is dropped into the BeanBox, a “Customize…” item is added by the BeanBox in the Edit menu.

Source: Uttam Kumar Roy (2015), Advanced Java programming, Oxford University Press.

Leave a Reply

Your email address will not be published. Required fields are marked *