Java: how to serialize a 3rd party library produced Java Object? - java

So I am using a proprietary java library in a project which I don't have access to source code.
It throws a Message object, and obviously I can't implement Serializable. It's generated throughout runtime.
what are my options? Is there a way to serialize the Message object into a byte array and back into the object?
UPDATE: I was able to serialize the object to JSON (http://code.google.com/p/json-io/) but couldn't convert it back to an object as it returns null. So I am trying to convert it to byte array using the code below. Still not working.
public byte[] toByteArray (Object obj)
{
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
oos.close();
bos.close();
bytes = bos.toByteArray ();
}
catch (IOException ex) {
//TODO: Handle the exception
}
return bytes;
}
public Object toObject (byte[] bytes)
{
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
ObjectInputStream ois = new ObjectInputStream (bis);
obj = ois.readObject();
}
catch (IOException ex) {
//TODO: Handle the exception
}
catch (ClassNotFoundException ex) {
//TODO: Handle the exception
}
return obj;
}

You could write a wrapper that is serializable and stores everything you need to recreate the Message object.

XStream is one way to go.

Sure, you just can't use the java.lang.Serializable mechanism.
Choose any format: XML, JSON, protocol buffer, or something else that might work for you.
Now you're responsible for both ends of the conversation: serialization and deserialization.

If the object is a Java bean, you can use java.beans.XMLEncoder and java.beans.XMLDecoder for serialization.

Related

Is there a way to know which type of java object has been send once it is deserialized?

There are methods to serialize or deserialize java objects...
Prepare bytes to send:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(yourObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
bos.close();
}
catch(Exception ex)
{
}
Create object from bytes:
ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = null;
try
{
in = new ObjectInputStream(bis);
Object o = in.readObject();
if (in != null)
{
in.close();
}
}
catch (Exception ex)
{
}
}
However, if someone wants to send different types of objects over the net is there a way to know which type of object has been sent. I guess there is the option to create a class and then serialize and deserialize it.
class SerialObject
{
String type;
Object object;
}
I think the only way to know the type of object being sent is when you use the InstanceOf keyword in java . The java instanceof operator is used to test whether the object is an instance of the specified type (class or subclass or interface). The instanceof in java is also known as type comparison operator because it compares the instance with type. It returns either true or false.
class Demo{
public static void main(String args[]){
Demo s=new Demo();
System.out.println(s instanceof Demo);//true
}
}
this code return true. just use the InstanceOf keyword .it will really help
When you are Serializing you can store the types somewhere - map or cache or somewhere, but still not sure why you want that?
One option is to check with instanceof operator during deserialized . I am not sure if (why?)should there be more?
Object deserialized = in.readObject();
if (deserialized instanceof TypeAbdClass) {
// do something with ..
} else if (deserialized instanceof SomethingElse) {
...
} else if (...) {
...
}
You can use
Object.getClass()
This will return runtime class of an object
Refer java doc
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

ArrayList to Byte and vice versa

Hi I need to store ArrayList in database of my project, for that I need some suggestion to store ArrayList into DB by means of some techniques like ArrayList to Byte[] and store byte[] in DB and retreive my byte[] from DB and convert into my original ArrayList in Java
I assume you're talking about Java's ArrayList (you didn't mention the language you have in mind).
In fact, there was a vary similar question: Serializing Arraylists
Just serialize a list, and insert it to BLOB column. Then you can fetch it from DB and deserialize it.
Edit:
This is a piece of code you can use to serialize your ArrayList:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ObjectOutputStream ooStream = new ObjectOutputStream(baos);
ooStream.writeObject(myList);
ooStream.close();
} catch(IOException e) {
throw new RuntimeException(e);
} finally {
try {
baos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
byte[] serializedData = baos.toByteArray();
Having the data as byte[] you can now store it in bytea / BLOB column.
I hope this helps.

Java Serialization Pains (java.io.StreamCorruptedException)

I'm trying to Serialize an object to a Byte array, for storage in a String. I cannot for the life of me figure out where I'm going wrong here.
String store = null;
// Writing
try {
String hi = "Hi there world!";
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(hi);
oos.close();
store = out.toString("UTF-8");
} catch(Exception e) {
System.out.println(e);
}
// Reading
try {
ByteArrayInputStream in = new ByteArrayInputStream(store.getBytes("UTF-8"));
ObjectInputStream ois = new ObjectInputStream(in);
String data = (String) ois.readObject();
} catch(Exception e) {
System.out.println(e);
}
I keep getting java.io.StreamCorruptedException and I don't know why :(
store = out.toString("UTF-8");
the data in out is not UTF-8 formatted, in fact it's not a String at all. It's a serialized instance of a String. You can call toString on it, just because you can call toString on any object.
you'd want to to
byte[] data = out.toByteArray();
and then pass data into the ByteArrayInputStream constructor
Unfortunatelly, Java strings aren't an array of bytes (as in C), but rather an array of chars (16-bit values). Also, all strings are unicode in Java.
My best advice is: use Base64 encoding/decoding if you need to store binary data into strings. Apache Commons has some great classes for this task, and you can find more info at:
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html
If you want to save the byte array to a string, you need to convert it to a Base64 string, not to a UTF-8 string. For that purpose you can use org.apache.commons.codec.binary.Base64
I would recommend the following code:
Note that the "ISO-8859-1" encoding preserves a byte array, while "UTF-8" does not (some bytes array lead to invalid Strings in this encoding).
/**
* Serialize any object
* #param obj
* #return
*/
public static String serialize(Object obj) {
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(obj);
so.flush();
// This encoding induces a bijection between byte[] and String (unlike UTF-8)
return bo.toString("ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Deserialize any object
* #param str
* #param cls
* #return
*/
public static <T> T deserialize(String str, Class<T> cls) {
// deserialize the object
try {
// This encoding induces a bijection between byte[] and String (unlike UTF-8)
byte b[] = str.getBytes("ISO-8859-1");
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
return cls.cast(si.readObject());
} catch (Exception e) {
e.printStackTrace();
}
}
The problem is that the initial string when serialized is a serialized String. That's not the same as chopping the string into an array of its constituent characters.

Reliably convert any object to String and then back again

Is there a reliable way to convert any object to a String and then back again to the same Object? I've seen some examples of people converting them using toString() and then passing that value into a constructor to reconstruct the object again but not all objects have a constructor like this so that method wont work for all cases. What way will?
Yes, it is called serialization!
String serializedObject = "";
// serialize the object
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(myObject);
so.flush();
serializedObject = bo.toString();
} catch (Exception e) {
System.out.println(e);
}
// deserialize the object
try {
byte b[] = serializedObject.getBytes();
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
MyObject obj = (MyObject) si.readObject();
} catch (Exception e) {
System.out.println(e);
}
This is the code:
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(stringList);
so.flush();
redisString = new String(Base64.encode(bo.toByteArray()));
}
catch (Exception e) {
e.printStackTrace();
}
try {
byte b[] = Base64.decode(redisString.getBytes());
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
List<String> stringList2 = (List<String>)si.readObject();
System.out.println(stringList2.get(1));
}
catch (Exception e) {
e.printStackTrace();
}
Serialize to byte array, convert to Base64. Then decode Base64 back to byte array and deserialize.
None will work in all cases. An object may, e.g., contain references to other JVMs handling their state, and this state may be not available for you to restore.
Additional problems you're going to meet will include open streams, listening sockets, and almost anything else from the outer world.
There's no need to repeat that most at least two of Java core engineers say that serialization was one of the greatest mistakes a single worst feature in Java, that is, after finalization. (I do love serialization nevertheless, it's handy. But it won't always work.)
One way is to use JSON. For implementation specific in Java, the answer might be given in this post:
java code corresponding to Newtonsoft.Json.JsonConvert.SerializeObject(Object source,Newtonsoft.Json.JsonSerializerSettings()) in .net?
Using JSON is reliable enough that it's used for web application development (Ajax).
Yes, it is Serialization You can use, ObjectInputStream.readObject and ObjectOutputStream.writeObject. Please see below example:
MyClass myClass = new MyClass();
FileOutputStream fileStream = new FileOutputStream("myObjectFile.txt");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(os);
os.close();
FileInputStream fileInStream = new FileInputStream("myObjectFile.txt");
ObjectInputStream ois = new ObjectInputStream(fileInStream);
MyClass myClass2 = ois.readObject();
ois.close();
You can use SerializationUtils from org.apache.commons.
It provides the methods serialize and deserialize

Blob object not working properly even though the class is seralized

I have class which is seralized and does convert a very large amount of data object to blob to save it to database.In the same class there is decode method to convert blob to the actual object.Following is the code for encode and decode of the object.
private byte[] encode(ScheduledReport schedSTDReport)
{
byte[] bytes = null;
try
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(schedSTDReport);
oos.flush();
oos.close();
bos.close();
//byte [] data = bos.toByteArray();
//ByteArrayOutputStream baos = new ByteArrayOutputStream();
//GZIPOutputStream out = new GZIPOutputStream(baos);
//XMLEncoder encoder = new XMLEncoder(out);
//encoder.writeObject(schedSTDReport);
//encoder.close();
bytes = bos.toByteArray();
//GZIPOutputStream out = new GZIPOutputStream(bos);
//out.write(bytes);
//bytes = bos.toByteArray();
}
catch (Exception e)
{
_log.error("Exception caught while encoding/zipping Scheduled STDReport", e);
}
decode(bytes);
return bytes;
}
/*
* Decode the report definition blob back to the
* ScheduledReport object.
*/
private ScheduledReport decode(byte[] bytes)
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ScheduledReport sSTDR = null;
try
{
ObjectInputStream ois = new ObjectInputStream(bais);
//GZIPInputStream in = new GZIPInputStream(bais);
//XMLDecoder decoder = new XMLDecoder(in);
sSTDR = (ScheduledReport)ois.readObject();//decoder.readObject();
//decoder.close();
}
catch (Exception e)
{
_log.error("IOException caught while decoding/unzipping Scheduled STDReport", e);
}
return sSTDR;
}
The problem here is whenver I change something else in this class
means any other method,a new class version is created and so the new version the class is unable to decode the originally encoded blob object. The object which I am passing for encode is also seralized object but this problem exists. Any ideas thanks
Yup, Java binary serialization is pretty brittle :(
You can add a static serialVersionUID field to the class so that you can control the version numbers... this should prevent problems due to adding methods. You'll still run into potential issues when fields are added though. See the JavaDocs for Serializable for some more details.
You might want to consider using another serialization format such as Protocol Buffers to give you more control though.
You can implement java.io.Externalizable so that you are able to control what is serialized and expected in deserialization.

Categories