Java - ObjectInputStream registerValidation(ObjectInputValidation obj, int prio) method



Description

The Java ObjectInputStream registerValidation(ObjectInputValidation obj, int prio) method allows custom validation logic to be executed after deserialization but before the object is returned to the caller. It is useful for checking data integrity, constraints, or post-processing logic.

Declaration

Following is the declaration for java.io.ObjectInputStream.registerValidation(ObjectInputValidation obj, int prio) method.

public void registerValidation(ObjectInputValidation obj, int prio)

Parameters

  • obj − the object to receive the validation callback.

  • prio − controls the order of callbacks;zero is a good default. Use higher numbers to be called back earlier, lower numbers for later callbacks. Within a priority, callbacks are processed in no particular order.

Return Value

NA

Exception

  • NotActiveException − The stream is not currently reading objects so it is invalid to register a callback.

  • InvalidObjectException − The validation object is null.

Example - Validating an Age Field After Deserialization

The following example shows the usage of Java ObjectInputStream registerValidation(ObjectInputValidation obj, int prio) method. In this example, we register a validation check to ensure the age of a deserialized Person object is within a valid range.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectInputValidation;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String filename = "person.ser";

      // Serialize an object
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
         oos.writeObject(new Person(25)); // Valid age
         System.out.println("Person object written to file.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Deserialize with validation
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         Person person = (Person) ois.readObject();

         //ois.registerValidation(person, 0); // Register validation

         System.out.println("Deserialized Person object with age: " + person.getAge());
      } catch (IOException e)   {
         e.printStackTrace();
      }catch(ClassNotFoundException cfe){
         cfe.printStackTrace();
      }
   }
   static class Person implements Serializable, ObjectInputValidation{
      private static final long serialVersionUID = 1L;
      private int age;

      public Person(int age) {
         this.age = age;
      }

      public int getAge() {
         return age;
      }
      // Custom validation logic
      @Override
      public void validateObject() throws InvalidObjectException {
         if (age < 0 || age > 120) {
            throw new InvalidObjectException("Invalid age: " + age);
         }
      }
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject(); // Perform default deserialization
         in.registerValidation(this, 0); // Register validation callback during deserialization
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Person object written to file.
Deserialized Person object with age: 25

Explanation

  • The Person class implements ObjectInputValidation and overrides validateObject().

  • We register this validation method using registerValidation().

  • If age is negative or greater than 120, an InvalidObjectException is thrown before returning the object.

  • In this case, age is 25, so validation passes successfully.

Example - Checking a Product's Price After Deserialization

The following example shows the usage of Java ObjectInputStream registerValidation(ObjectInputValidation obj, int prio) method. This example ensures that a product's price is never negative after deserialization.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectInputValidation;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String filename = "product.ser";

      // Serialize an object
      try (ObjectOutputStream oos = new ObjectOutputStream(new   FileOutputStream(filename))) {
         oos.writeObject(new Product("Laptop", -1000)); // Invalid price
         System.out.println("Product object written to file.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Deserialize with validation
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         Product product = (Product) ois.readObject();
         //ois.registerValidation(product, 1); // Register validation
         System.out.println("Deserialized Product object: " + product.getPrice());
      } catch (IOException ioe) {
         ioe.printStackTrace();
      }catch( ClassNotFoundException cfe){
         cfe.printStackTrace();
      }
   }

   static  class Product implements Serializable, ObjectInputValidation {
      private static final long serialVersionUID = 1L;
      private String name;
      private double price;

      public Product(String name, double price) {
         this.name = name;
         this.price = price;
      }

      public double getPrice() {
         return price;
      }

      // Custom validation logic
      @Override
      public void validateObject() throws InvalidObjectException {
         if (price < 0) {
            throw new InvalidObjectException("Invalid price for product: " + name);
         }
      }

      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject(); // Perform default deserialization
         in.registerValidation(this, 1); // Register validation callback during deserialization
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Product object written to file.
java.io.InvalidObjectException: Invalid price for product: Laptop
	at com.tutorialspoint.ObjectInputStreamDemo$Product.validateObject(ObjectInputStreamDemo.java:54)
	at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2801)
	at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2799)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
	at java.base/java.io.ObjectInputStream$ValidationList.doCallbacks(ObjectInputStream.java:2797)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:547)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:498)
	at com.tutorialspoint.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:26)

Explanation

  • The Product class implements ObjectInputValidation and validates the price.

  • If price is negative, validateObject() throws an InvalidObjectException.

  • Here, the product has -1000 as the price, so the program throws an exception.

Example - Using Different Validation Priorities

The following example shows the usage of Java ObjectInputStream registerValidation(ObjectInputValidation obj, int prio) method. This example demonstrates multiple validation checks with different priorities.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectInputValidation;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String filename = "car.ser";

      // Serialize an object
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
         oos.writeObject(new Car("Tesla Model S", 2030)); // Invalid year
         System.out.println("Car object written to file.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Deserialize with multiple validations
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         Car car = (Car) ois.readObject();

         ois.registerValidation(car, 2); // Priority 2
         ois.registerValidation(new CarValidator(), 1); // Priority 1 (executes first)

         System.out.println("Deserialized Car: " + car.getYear());
      } catch (IOException e){ 
         e.printStackTrace();
      }
      catch(ClassNotFoundException cfe){
         cfe.printStackTrace();
      }
   }
   static class Car implements Serializable, ObjectInputValidation {
      private static final long serialVersionUID = 1L;
      private String model;
      private int year;

      public Car(String model, int year) {
         this.model = model;
         this.year = year;
      }
      public int getYear() {
         return year;
      }
      @Override
      public void validateObject() throws InvalidObjectException {
         if (year < 1886 || year > 2025) {
            throw new InvalidObjectException("Invalid manufacturing year: " + year);
         }
      }
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject(); // Perform default deserialization
         in.registerValidation(this, 2); // Register validation callback during deserialization
      }
   }
   static class CarValidator implements ObjectInputValidation {
      @Override
      public void validateObject() throws InvalidObjectException {
         System.out.println("Additional car validation executed.");
      }
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject(); // Perform default deserialization
         in.registerValidation(this, 1); // Register validation callback during deserialization
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Car object written to file.
java.io.InvalidObjectException: Invalid manufacturing year: 2030
	at com.tutorialspoint.ObjectInputStreamDemo$Car.validateObject(ObjectInputStreamDemo.java:54)
	at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2801)
	at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2799)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
	at java.base/java.io.ObjectInputStream$ValidationList.doCallbacks(ObjectInputStream.java:2797)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:547)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:498)
	at com.tutorialspoint.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:26)

Explanation

  • The Car class validates its manufacturing year (year).

  • Since the year is 2030, which is invalid, an exception is thrown.

java_io_objectinputstream.htm
Advertisements