Serialization evolution - java

Serialization evolution - java

In Java, everything is an object, Objects encapsulate data and behaviour, providing a foundation for building complex systems. When it comes to preserving and transporting these objects, serialization and de-serialization plays a crucial role.

Serialization is not dying in Java development but there are some concerns about its security and efficiency. Java Platform Chief Architect Mark Reinhold has described the decision in 1997 to adopt the current serialization feature as a "horrible mistake". Reinhold also claims that as many as half of all Java vulnerabilities are linked to the current serialization approach.

Serialization is still widely used in Java applications and is an important feature for data persistence and communication between distributed systems. However, there are some alternatives to serialization such as JSON, XML, YAML, and Protocol Buffers that are more efficient and secure than Java serialization.

In this blog post, we are going to explore the intricacies of serialization, best practices, and its wider application in the Java ecosystem. Let's embark on the journey of understanding serialization and harness its power in Java development.

Understanding serialization

Serialization is like taking a snapshot of an object and its related objects, capturing their current state and transforming it into a sequence of bytes. It allows objects to be saved to storage, sent over networks, or shared between different parts of an application.

Serialization Process

Imagine objects as interconnected nodes in a graph. When we serialize an object, we follow the connections to include all the related objects in the serialization process. We capture the current state of each object by converting its data values into a format that can be represented as a sequence of bytes.
In Java specifically, there is special treatment is given to some constructs like static during the serialization process which we are going to discuss in further sections of this blog.

Benefits of serializaiton

Data Persistence and Storage: Serialized objects can be stored in databases or files, ensuring long-term data preservation.
Inter-process Communication: Serialization enables objects to be exchanged between different processes or systems, facilitating seamless integration and communication.
Remote Method Invocation: Serialization forms the foundation for remote method invocation (RMI), allowing methods on objects located remotely to be invoked and processed.

Challenges and Considerations

Versioning and Compatibility:
Changes to the structure of serialized objects can impact compatibility between different versions of an application.
Security Concerns: Serialization can introduce security vulnerabilities if not handled carefully, as deserialization can execute malicious code or expose sensitive data. Performance Implications: Serialization can have performance implications due to the overhead of object traversal and byte stream generation. Employing efficient serialization techniques and optimizations can help mitigate these concerns.

Steps to do serialization in java

Using Serializable Interface (OLD technique)

import java.io.*;

public class SerializationDemo {
    public static void main(String[] args) {
        // Create an object
        Student student = new Student("John", 20);

        // Serialize the object
        try {
            FileOutputStream fileOut = new FileOutputStream("student.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(student);
            out.close();
            fileOut.close();
            System.out.println("Serialized data is saved in student.ser");
        } catch (IOException i) {
            i.printStackTrace();
        }

        // Deserialize the object
        try {
            FileInputStream fileIn = new FileInputStream("student.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            Student deserializedStudent = (Student) in.readObject();
            in.close();
            fileIn.close();
            System.out.println("Deserialized data:");
            System.out.println("Name: " + deserializedStudent.getName());
            System.out.println("Age: " + deserializedStudent.getAge());
            System.out.println("Roll No: " + deserializedStudent.getRollNo());
        } catch (IOException i) {
            i.printStackTrace();
        } catch (ClassNotFoundException c) {
            System.out.println("Student class not found");
            c.printStackTrace();
        }
    }
}

class Student implements Serializable {
    private String name;
    private int age;
    private transient int rollNo;
    private static String schoolName;

    static {
        schoolName = "XYZ School";
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        this.rollNo = 1;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getRollNo() {
        return rollNo;
    }

    public static String getSchoolName() {
        return schoolName;
    }
}

// OUTPUT 
Serialized data is saved in student.ser
Deserialized data:
Name: John
Age: 20
Roll No: 0

In the code above, we have added a static block that initializes a schoolName variable We have also added a transient keyword to the rollNo variable to indicate that it should not be serialized .

When we deserialize the object, we can see that the rollNo variable is not restored because it was marked as transient. However, the schoolName variable is restored because we implemented the Serializable interface in the Student class.

Serialize and deserialize using Jackson library

Using jackson (This is preferred in spring framework ecosystem, there are many other libraries as well)

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;

public class SerializationDemo {
    public static void main(String[] args) {
        // Create an object
        Student student = new Student("John", 20);

        // Serialize the object
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(new File("student.json"), student);
            System.out.println("Serialized data is saved in student.json");
        } catch (IOException i) {
            i.printStackTrace();
        }

        // Deserialize the object
        try {
            ObjectMapper mapper = new ObjectMapper();
            Student deserializedStudent = mapper.readValue(new File("student.json"), Student.class);
            System.out.println("Deserialized data:");
            System.out.println("Name: " + deserializedStudent.getName());
            System.out.println("Age: " + deserializedStudent.getAge());
            System.out.println("Roll No: " + deserializedStudent.getRollNo());
        } catch (IOException i) {
            i.printStackTrace();
        }
    }
}

In this example, we use the ObjectMapper class from Jackson to serialize and deserialize the Student object. We call the writeValue() method to serialize the object to a JSON file and the readValue() method to deserialize the JSON file back into a Student object.

There are other great libraries which are popular to do serialization in java, example Gson,YAML, Apache Thrift.
This blog post [blog post] is a good place to know about them in short.

Advantages of using JSON over Java serialization

Json serialization technique is preferred in modern java development because it is simple, readable, works across different languages, and is widely used in web applications. Below are some important reasons to choose JSON for serialization.

Simplicity: JSON is easy to read, write, parse, and generate by machines. It simplifies data handling and manipulation, making it developer-friendly.

Human-readable: JSON's structure is clear and self-explanatory, aiding in troubleshooting and debugging processes.

Language-agnostic: JSON is compatible with any programming language, facilitating data exchange between different systems regardless of the languages used.

Lightweight: JSON has a compact format, making it efficient for transmitting data over the network. It reduces bandwidth consumption and improves network efficiency.

Backward compatibility: JSON supports seamless updates and expansions of data structures. New fields can be added to the JSON object without breaking existing code.

The use cases for serialization in modern Java applications.

Serialization can be used in a variety of situations in Java programming. Here are some examples of when to use serialization :

  1. Data persistence: If you need to save the state of an object to a file or a database, serialization can be a convenient way to do so.

  2. Network communication: Serialization can be used to send objects over a network.

  3. Caching: Serialization can be used to cache objects in memory.

  4. Deep copying: Serialization can be used to create a deep copy of an object. This can be useful when you want to create a new object with the same state as an existing object.

Serialization is also useful when you want to store data in a format that can be easily read by other applications or programming languages. For example, JSON and XML are popular formats for storing data that can be easily read by other applications.

Use of Serialization in spring and spring boot framework

Serialization plays a crucial role in Spring and Spring Boot applications. Here are some important uses of serialization in these frameworks:

1. Stateful session replication:
Serialization allows Spring applications to replicate and distribute session state across multiple servers in a clustered environment. This ensures high availability and fault tolerance by allowing sessions to be seamlessly ransferred between different instances. By configuring a session store that supports serialization, such as Redis or Hazelcast, Spring Session can automatically serialize session objects and distribute them across a cluster of servers.

2 . Caching :
Serialization is used in Spring's caching framework to store objects in a cache. Serialized objects can be stored in a distributed cache or a local cache, allowing for efficient retrieval and sharing of data between application instances.
spring's caching abstraction, combined with a cache implementation like Ehcache or Redis, uses serialization to store and retrieve cached objects.
By annotating methods with @Cacheable or other cache-related annotations, Spring serializes the return values of those methods and stores them in the cache for subsequent fast retrieval.

3. Messaging and remote communication:
Spring Integration, a module for building enterprise integration solutions, uses serialization to exchange messages between different components or systems. Messages can be serialized using various message formats such as JSON, XML, or Java objects and sent over message channels or messaging systems like JMS or AMQP.

4 . Web session management:
In Spring Web applications, the HttpSession object is serialized and persisted between requests. This allows session data to be maintained across multiple requests and is managed by the servlet container or external session stores like Redis. Also serialized session objects can be stored in various locations such as cookies, databases, or distributed caches, ensuring session continuity and maintaining user-specific state.

5. RESTful APIs and JSON/XML conversion:
Spring MVC, the web framework in Spring, automatically serializes Java objects to JSON or XML format for RESTful API responses. By using appropriate annotations such as @RestController and @ResponseBody, Spring handles the serialization and deserialization of objects as part of request processing.

6 . Application state persistence:
Spring Data, a module that simplifies data access and persistence, often relies on serialization to store application-specific state in databases. For example, when using Spring Data JPA, entities are serialized and persisted to the underlying database tables.

7 . Integration with external systems:
When integrating Spring applications with external systems like message brokers (e.g., Apache Kafka) or databases, serialization is used to exchange data between systems. For instance, when publishing or consuming messages with Spring Kafka, objects are serialized and deserialized to be sent or received over Kafka topics.

The future of serialization in java

Serialization is still an important part of Java programming and is used for various purposes such as data persistence, network communication, caching, and deep copying. However, there are some concerns about the security of serialization in Java.

JDK 11 improves serialization security with a new filter API and removes deprecated APIs to enhance security and simplicity.

Don't forget to explore libraries available for serialization in Java. Some popular ones include:

Gson: This library is used for serializing and deserializing Java objects to and from JSON representation.
Jackson: This library is used for JSON processing and is known for its high performance.
Fastjson: This library is used for serializing and deserializing Java objects to and from JSON representation .
Moshi: This library is used for serializing and deserializing Java objects to and from JSON representation.
Jsoniter: This library is used for high-performance JSON parsing and generation.

It’s important to note that each library has its own strengths and weaknesses, so it’s important to choose the right one for your specific use case.

Summary

Serialization in Java has evolved to meet the needs of modern applications. We explored traditional Java serialization and discovered newer techniques like JSON. There are other approaches which are not explored in this post which are Protocol Buffers, Apache Avro, and BSON.

We also examined the extensive usage of serialization in Spring Boot. By following best practices and considering versioning, security, and performance, developers can leverage serialization to build robust and efficient Java applications.

references :
(1) https://dzone.com/articles/serialization-is-dead-long-live-serialization.

(2) https://www.geeksforgeeks.org/serialization-in-java/.

(3) https://www.baeldung.com/java-serialization.

(4) https://www.baeldung.com/java-serialization-approaches.

(5) https://www.javatpoint.com/serialization-in-java.

(6) Image credit : https://www.scaler.com