Serializing a variable with transient modifier or keyword

In this article, we will discuss how can we serialize and de-serialize member variables with transient modifier or keyword

 

In earlier articles, we have seen what happens to member variables when transient modifier applied to it

Revise the following articles, to understand what exactly happens during serialization and de-serialization when transient modifier applied to member variables

 

 

Let us re-phrase what exactly happens during serialization and de-serialization when transient modifier applied to member variables

 

Serialization process

During serialization process i.e.; saving the state of an Object to File, only instance variables will be participated and persisted to file storage or some other storage via network capability

Transient: So, when variable with transient modifier is encountered then that variable’s original value is discarded and instead default value is stored into file storage

 

 

De-Serialization process

During de-serialization process, Object’s state will be restored back from file storage

Transient: Likewise, when variable with transient modifier is encountered during restoring object back to heap memory from file storage then its default value is restored (as this is what stored into file storage)

 

 

So far, we have seen all things related to transient modifier and the next question is,

How can we serialize and de-serialize transient variables?

Well, the answer is programmer has to write some custom logic by overriding below 2 methods i.e.;

  • writeObject();
  • readObject();

Note: this is on top of the default serialization and de-serialization process

 

 

What happens by overriding 2 methods?

  • While serialization, writeObject() method is invoked automatically and all custom logic coded/written by programmer for writing/saving to file storage is executed
  • Similarly while de-serialization, readObject() method is invoked automatically and all custom logic coded/written by programmer for restoring object back into heap memory from file storage is executed

 

Write complete method signature of 2 methods?

private void writeObject(ObjectOutputStream objectOutputStream) 
			throws Exception {}

private void readObject(ObjectInputStream objectInputStream) 
			throws Exception {}

 

 

It’s time to play with Java code

We will write simple program covering how can we serialize and de-serialize objects involving member variables with transient modifier or keyword

 

Class to be serialized:

  • Below Customer class consists of 3 member variables, out of which 2 are transient variable
  • So, while serializing these 2 member variables won’t be serialized and similarly while retrieving/restoring during de-serialization process , their default values will be obtained back
  • To serialize these 2 transient variables, we have to override 2 methods
    writeObject(); –> for saving/writing in serialization process
    readObject(); –> for restoring during de-serialization process

 

Serialization:

During serialization inside writeObject(); method, programmer has to do default serialization for saving actual customer object and then custom logic to write these 2 transient variables in encrypted form

Steps for serialization inside writeObject() method:

  1. Default serialization for saving/writing actual customer object
  2. Add integer ‘333’ to customer Id and use writeInt() method to save customer Id in encrypted form
  3. Similarly, add “Test” string to customer SSN number and use writeObject() method to save customer SSN number in encrypted form

 

De-Serialization:

During de-serialization inside readObject(); method, programmer has to do default de-serialization for restoring actual customer object and then custom logic to read these 2 transient variables in encrypted form (by decrypting)

Steps for de-serialization inside readObject() method:

  1. Default de-serialization for restoring/retrieving actual customer object
  2. Use readInt() method to retrieve customer Id in encrypted form and decrypt by subtracting integer ‘333’ from customer Id
  3. Similarly, use readObject() method to retrieve customer SSN number in encrypted form and decrypt by using String handling functionalities (like substring at index 4)

 

Customer.java

package in.bench.resources.custom.serialization;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Customer implements Serializable {

	// member variables for Customer
	transient int customerId;
	String customerName;
	transient String customerSSN;

	// 3-arg parameterized constructor for Customer
	public Customer(int customerId, String customerName, 
			String customerSSN) {
		super();
		this.customerId = customerId;
		this.customerName = customerName;
		this.customerSSN = customerSSN;
	}

	/**
	 * this method invoked automatically during serialization process
	 * 
	 * @param objectOutputStream
	 * @throws Exception
	 */
	private void writeObject(ObjectOutputStream objectOutputStream)
			throws Exception {

		// 1st do, save using default serialization for all objects
		objectOutputStream.defaultWriteObject();

		// temp variable
		int tempCustId = 333 + customerId;
		String tempCustSSN = "Test" + customerSSN;

		// saving customer Id and SSN, in encrypted version
		objectOutputStream.writeInt(tempCustId);
		objectOutputStream.writeObject(tempCustSSN);
	}

	/**
	 * this method invoked automatically during de-serialization process
	 * 
	 * @param objectInputStream
	 * @throws Exception
	 */
	private void readObject(ObjectInputStream objectInputStream) 
			throws Exception {

		// 1st do, restore using default de-serialization for all objects
		objectInputStream.defaultReadObject();

		// temp variable
		int tempCustId = objectInputStream.readInt();
		String tempCustSSN = objectInputStream.readObject().toString();

		// decrypting and restoring transient variables
		customerId = 123 - tempCustId;
		customerSSN = tempCustSSN.substring(4);
	}

	// to print nicely - customer object
	@Override
	public String toString() {
		return "Customer [customerId=" + customerId 
				+ ", customerName=" + customerName 
				+ ", customerSSN=" + customerSSN + "]";
	}
}

 

Serialization and De-serialization:

This program is the test class to write/save customer object to file storage and then restoring for reading customer object

  • 1st part explains, complete serialization process
  • 2nd explains, complete de-serialization process

CustomerSerialization.java

package in.bench.resources.custom.serialization;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class CustomerSerialization {

	public static void main(String[] args) {

		// create an customer object using 3-arg parametrized constructor
		Customer serializeCustomer = new Customer(102, "NK", "SSN-78087");

		// creating output stream variables
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;

		// creating input stream variables
		FileInputStream fis = null;
		ObjectInputStream ois = null;

		// creating customer object reference 
		// to hold values after de-serialization 
		Customer deSerializeCustomer = null;

		try {
			// for writing or saving binary data
			fos = new FileOutputStream("Customer.ser");

			// converting java-object to binary-format 
			oos = new ObjectOutputStream(fos);

			// writing or saving customer object's value to stream
			oos.writeObject(serializeCustomer);
			oos.flush();
			oos.close();

			System.out.println("Serialization: "
					+ "Customer object saved to Customer.ser file\n");

			// reading binary data
			fis = new FileInputStream("Customer.ser");

			// converting binary-data to java-object
			ois = new ObjectInputStream(fis);

			// reading object's value and casting to Customer class
			deSerializeCustomer = (Customer) ois.readObject();
			ois.close();

			System.out.println("De-Serialization: Customer object "
					+ "de-serialized from Customer.ser file\n");
		} 
		catch (FileNotFoundException fnfex) {
			fnfex.printStackTrace();
		}
		catch (IOException ioex) {
			ioex.printStackTrace();
		}
		catch (ClassNotFoundException ccex) {
			ccex.printStackTrace();
		}

		// printing customer object to console using toString() method
		System.out.println("Printing customer values from "
				+ "de-serialized object... \n" + deSerializeCustomer);
	}
}

Output:

Serialization: Customer object saved to Customer.ser file

De-Serialization: Customer object de-serialized from Customer.ser file

Printing customer values from de-serialized object... 
Customer [customerId=-102, customerName=NK, customerSSN=SSN-78087]

 

 

References:

https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html
https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3

Happy Coding !!
Happy Learning !!