2

I am trying to save the entire TreeMap object into a file and load it back as a TreeMap again.

The key of the treeMap is an object whose class has comparable interface implemented. Though I implement Serializable interface, I cannot save the object to a file.

//This class object is used as key in the TreeMap
public class FourTuple<K1,K2,K3,K4> implements Comparable<FourTuple>, java.io.Serializable  {
    public final K1 rk;
    public final K2 cf;
    public final K3 cn;
    public final K4 timestamp;
    public FourTuple(K1 rk, K2 cf, K3 cn, K4 timestamp) {
        this.rk=rk;
        this.cf=cf;
        this.cn=cn;
        this.timestamp=timestamp;
    }

    public boolean equals(FourTuple ft) {
        return ((this.rk==ft.rk)&&this.cf==ft.cf && this.cn==ft.cn && this.timestamp==ft.timestamp);

    }

    public int compareTo( FourTuple ft) {
        if(this.rk==ft.rk) {
            return this.timestamp.toString().compareTo(ft.timestamp.toString());
        }
        else
        return this.rk.toString().compareTo(ft.rk.toString());

    }

    public String toString() {
        return (rk + "=>" + cf + "=>" + cn + "=>" + timestamp);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((cf == null) ? 0 : cf.hashCode());
        result = prime * result + ((cn == null) ? 0 : cn.hashCode());
        result = prime * result + ((rk == null) ? 0 : rk.hashCode());
        result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        FourTuple other = (FourTuple) obj;
        if (cf == null) {
            if (other.cf != null)
                return false;
        } else if (!cf.equals(other.cf))
            return false;
        if (cn == null) {
            if (other.cn != null)
                return false;
        } else if (!cn.equals(other.cn))
            return false;
        if (rk == null) {
            if (other.rk != null)
                return false;
        } else if (!rk.equals(other.rk))
            return false;
        if (timestamp == null) {
            if (other.timestamp != null)
                return false;
        } else if (!timestamp.equals(other.timestamp))
            return false;
        return true;
    }




}

Getting the error log as shown below. The FourTuple Class (in hbaseTest project) is not Serializable.

Exception in thread "main" java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: hbasetest.FourTuple
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1577)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at java.util.TreeMap.buildFromSorted(TreeMap.java:2567)
    at java.util.TreeMap.buildFromSorted(TreeMap.java:2508)
    at java.util.TreeMap.readObject(TreeMap.java:2454)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at hbasetest.DB.load(DB.java:83)
    at hbasetest.DB.commit(DB.java:64)
    at hbasetest.Driver.main(Driver.java:23)
Caused by: java.io.NotSerializableException: hbasetest.FourTuple
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at java.util.TreeMap.writeObject(TreeMap.java:2437)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at hbasetest.DB.save(DB.java:77)
    at hbasetest.DB.commit(DB.java:63)
    ... 1 more

As per documentation Comparable class, by default is not Serializable. But after going through other posts in the community, I tried to implement in the above manner. Can you please point out where I am making a mistake?

For reference posting the code for saving and retreiving the object below

public static void save(Object obj, File file) throws Exception{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file, true));
            oos.writeObject(obj);
            oos.flush();
            oos.close();
}
public static Object load(File file) throws Exception{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            Object result = ois.readObject();
            ois.close();
            return result;
}
HackChamp
  • 65
  • 8
  • This stack trace looks a bit suspicious. First you call `load()` which then tries to read a `TreeMap` object, which then throws an exception with a stack trace that shows that you've called `save()` at some point during the call to `load()`. What exactly is going on? – DodgyCodeException Jan 18 '19 at 09:55
  • Also, you are opening a new ObjectOutputSream on a FileOutputStream that has been opened in append mode. This is tricky. See https://stackoverflow.com/questions/1194656/appending-to-an-objectoutputstream – DodgyCodeException Jan 18 '19 at 10:40

1 Answers1

3

If you want an serializable instance of FourTuple<K1,K2,K3,K4> :

  • The class FourTuple must be serializable => it's OK
  • all attributes K1,K2,K3,K4 must be serializable too => here it's not garantee

Change the definition to get an compiler check :

FourTuple <
    K1 extends Serializable,
    K2 extends Serializable,
    K3 extends Serializable,
    K4 extends Serializable
> implements Comparable<FourTuple>, Serializable 

see this SO raw-type

Change :

public boolean equals(FourTuple ft)
...
public int compareTo( FourTuple ft) 
...
FourTuple other = (FourTuple) obj;

by :

public boolean equals(FourTuple<K1,K2,K3,K4> ft)
...
public int compareTo( FourTuple<K1,K2,K3,K4> ft) 
...
FourTuple<K1,K2,K3,K4> other = (FourTuple<>) obj;
Indent
  • 4,465
  • 1
  • 13
  • 30
  • 4
    You can have the compiler check this (as best it can) by changing the class definition to `public class FourTuple implements Comparable, Serializable { ... }` – Michael Jan 17 '19 at 13:38
  • As mentioned I extended serializable but it is still throwing error. K1,K2,K3,K4 represent strings and long values in my code. – HackChamp Jan 18 '19 at 06:06
  • I checked with removing K1, K2, K3 and K4. It works. – HackChamp Jan 18 '19 at 07:23
  • Have you just remove K1,K2,K3 and K4 or replace by strings and long ? – Indent Jan 18 '19 at 07:44
  • I want to know why class being generic where Strings and Long being variable types, I was not able to save the object . Can you please provide any suggestion why is this happening? – HackChamp Jan 18 '19 at 07:56
  • Removing k1,K2... Solved it. But gonna try to change methods as mentioned above and will let you know – HackChamp Jan 18 '19 at 11:05
  • Hi, have you try to remove raw-type ? if it's work can you accept the answer ? Have a good day. – Indent Jan 25 '19 at 08:38