Java – Serializing a variable with transient 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. Read below articles to get more insights,

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

1. Serialization process:

  • During serialization process i.e.; saving state of an Object to File, only instance variables will be participated and persisted to file storage or some other storage via network capability
  • 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

2. De-Serialization process:

  • During de-serialization process, Object’s state will be restored back from file storage
  • 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,

Q) How can we serialize and de-serialize transient variables ?

  • Well, answer is programmer has to write some custom logic by overriding below 2 methods i.e.;
    1. writeObject();
    2. readObject();
  • Note : this is on top of default serialization and de-serialization process

Q) 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

Q) Write complete method signature of 2 methods ?

  • The complete signature of writeObject() and readObject() methods is described below,
  • Method signature :
private void writeObject(ObjectOutputStream objectOutputStream) throws Exception {
} 

private void readObject(ObjectInputStream objectInputStream) throws Exception {
}

It’s time to play with Java code

3. Example for Serializing a variable with transient keyword:

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

3.1 Customer POJO i.e.; 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

3.2 Custom Serialization:

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

3.2.1 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

3.3 Custom De-Serialization:

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

3.3.1 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;
	}

	// to print nicely - customer object
	@Override
	public String toString() {
		return "Customer ["
				+ "customerId=" + customerId
				+ ", customerName=" + customerName
				+ ", 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 = tempCustId - 333;
		customerSSN = tempCustSSN.substring(4);
	}
}

3.4 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]

Related Articles:

References:

Happy Coding !!
Happy Learning !!

Java - Order of Serialization and De-Serialization
Java - Transient keyword with final variable in Serialization