I am storing an object as a value in LevelDB. Both key and value must be in bytes for LevelDB.
I am receiving an object via a socket and casting it to MyObject:
MyObject myObject = (MyObject) (objectInput.readObject());
Then I am serialising my object when storing the value in LevelDB:
myLevelDb().put(bytes((publicKey)), Serializer.serialize(myObject));
The serializer code is as follows:
public static byte[] serialize(Object object) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(object);
out.flush();
byte[] yourBytes = bos.toByteArray();
return yourBytes;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
Then I am trying to iterate through the LevelDB and store each object into a Map. Here is where I am trying to deserialize the bytes back into MyObject and save them to Map:
private void iterateBytes() {
DBIterator iterator = myLevelDb().iterator();
while (iterator.hasNext()) {
Map.Entry<byte[], byte[]> next = iterator.next();
String keyString = new String(next.getKey());
MyObject myObject = (MyObject) Serializer.deserialize(next.getValue());
Map<String, MyObject> myMap = new HashMap<>();
myMap().put(keyString, myObject);
}
}
However, Java will not let me cast the deserialized bytes back to MyObject after it has been deserialized using the following code:
public static Object deserialize(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
Object o = in.readObject();
return o;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
I don't understand why I cannot convert the object back from a byte[] when I have followed the exact same method of serializing and deserializing. MyObject implements Serializable and the SUID is correct, as it works on API calls between devices. I just cannot add it to a Map as the original object, nor will Java let me cast it.
This is the line where an error is thrown, no matter where I try to cast it back to myObject:
MyObject myObject = (MyObject) Serializer.deserialize(next.getValue());
Error:
class java.lang.String cannot be cast to class myPackage.MyObject (java.lang.String is in module java.base of loader 'bootstrap';
This was solved by casting the generic Object object to MyObject (user defined class object) at serialization and also casting it at deserialization.
Here is the code at serialization:
public static byte[] serialize(MyObject myObject) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(myObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
return yourBytes;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
And here is the code for deserializaion.
public static MyObject deserializeNodeClient(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
MyObject myObject = (MyObject) in.readObject();
return myObject;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
} return null;
}
So although the original OP code works fine is some cases, the original object cannot be derived by using a generic Object object serialization, then casting the output.