• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Storing serialized objects

 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a requirement to store a serialized object in a database.
I have serialized an object to a byte array. I tried constructing a String from the byte array so I could write the String to my database. However, the character encoding alters some of the values such that I cannot call myString.getBytes() and deserialize the object from the resulting array.
Can anybody suggest a solution?
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Are you using the toString() method of the ByteArrayOutputStream class?
 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes. This is one of the things I have tried.
Sample code:

This is the exception I get:

java.io.InvalidClassException: java.util.Date; Local class not compatible: stream classdesc serialVersionUID=7523895402267505689 local class serialVersionUID=7523967970034938905
java.lang.Throwable(java.lang.String)
java.lang.Exception(java.lang.String)
java.io.IOException(java.lang.String)
java.io.ObjectStreamException(java.lang.String)
java.io.InvalidClassException(java.lang.String, java.lang.String)
void java.io.ObjectStreamClass.validateLocalClass(java.lang.Class)
void java.io.ObjectStreamClass.setClass(java.lang.Class)
java.io.ObjectStreamClass java.io.ObjectInputStream.inputClassDescriptor()
java.lang.Object java.io.ObjectInputStream.readObject(boolean)
java.lang.Object java.io.ObjectInputStream.readObject()
int java.io.ObjectInputStream.inputObject(boolean)
java.lang.Object java.io.ObjectInputStream.readObject(boolean)
java.lang.Object java.io.ObjectInputStream.readObject()
void serialization.Convert.serialize()
void serialization.Convert.main(java.lang.String [])

[Peter: I'm editting this post to make it easier to read the code.]
Note that this does work for some classes. Just not for those that generate byte -127, for example, in the ByteArrayOutputStream.
Tim.
[This message has been edited by Peter Tran (edited February 13, 2001).]
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
1. Rather than creating a String object and getting a byte[] from the String object, you should get the byte[] directly from the ByteArrayOutputStream.
2. When you de-serialized the object, you need to cast back to the actual object you wrote out.

-Peter
 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Peter,
I can see this will work as far as Serialization goes. The catch is I have a requirement to persist the byte array in a database. Circumstances beyond my control dictate that the datatype in the database is a DB2 LONGVARCHAR, hence the attempt to convert to a String.
Tim.
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
Unless you can get the datatype changed in the database, I don't think you can do it. The String object will corrupt your byte[].
-Peter
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim,
The reason why is a String object holds an internal char[] buffer. Remember that char is unicode in JAVA which stores it as 2 bytes! There might be a 1 byte -> 2 bytes conversion when you execute a new String(byte[]).
-Peter
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Figured it out...
The problem is that when you create the String, it assumes that it is using ISO-646-US encoding which only uses the first 7 bits. This causes the loss of the first bit of each byte.
Try this:
********************************
byte[] b = { -53, 89, 83, -115};
System.out.println(b[0] + " " + b[1] + " " + b[2] + " " + b[3]);
String s = new String(b);
b = s.getBytes();
System.out.println(b[0] + " " + b[1] + " " + b[2] + " " + b[3]);
*********************************
The output of this code is:
***********
-53 89 83 -115
-53 89 83 63
***********
But there is a solution. You need to tell it to use "ISO-8859-1" to do the encoding! So your code looks like this:

 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Way Thomas!
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The interesting thing would be to see if writing the String object to the DB2 database remains valid on the roundtrip. That would be a major bummer if DB2 corrupts the char[] stream. Okay, Tim it's up to you to validate the roundtrip to the database. Let us know!
-Peter
 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your help everybody!
The code page ISO-8859-1 is the only one that works - I ran them all through.
The DB2 problem is as suspected - it runs its own code page conversion on the string. It comes as no surprise that this code page is not available with my installation of DB2!
I will pursue this further with our DBAs and post an update when I have an answer - I know it's not Java exactly but I thinks it's still relevant here.
Thanks again,
Tim.
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good luck hombre. Come back and let us know if you succeed.
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, absolutely let us know as I am sure this will come up again!
I think I might try this on some other databases to see if it works.

[This message has been edited by Thomas Paul (edited February 13, 2001).]
 
sunil choudhary
Ranch Hand
Posts: 141
Java Redhat Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Like a Great Climax in Action Movie...
Sheer Joy!!!
watching the post
Good work... all of you.
Sunil CHoudhary
[This message has been edited by sunil choudhary (edited February 16, 2001).]
 
Peter Tran
Bartender
Posts: 783
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sunil,
You need to get out more and watch some real action movies.
You are right. This topic was pretty cool. It felt like Thomas, Tim, and I were doing XP pair-programming.
-Peter
 
sunil choudhary
Ranch Hand
Posts: 141
Java Redhat Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Peter I am very happy.. just yesterday I got the first job of my life through Campus interviews (I still have 2 month to finish the course of MIS from DAVV Indore) ( I am a BE Mechanical Engineer passed in 1998.)
They tell me that there is a Training for 6 months and and then I will be ready to Rock and Roll.
I want to thank people at javaranch
also John Coxey... for his replies in posts
watch my inspirational Chicken soup for soul here http://www.javaranch.com/ubb/Forum37/HTML/000286.html http://www.javaranch.com/ubb/Forum37/HTML/000292.html
Once again thanks for the excellent stuff.. on Ranch...I will be contributing to the ranch with more energy now...
Excellent People!!!
Sunil
[This message edited for adding Links by sunil choudhary (edited February 17, 2001).]
[This message has been edited by sunil choudhary (edited February 17, 2001).]
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wonder if Tim ever got this to work.
 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I hadn't forgotten you all!
The short answer is no - but I am still trying. Database Administrators at our company are thin on the ground - to the point of being transparent.
The bottom line at present is I can't make it work, and it doesn't look like I will be able to.
In summary, I can get a valid String but the Database messes it up. I can store it as bit data on a DB2 Varchar field, which means I have no problems getting a String in to the database, but then I can't get it out as a String, it would involve some manual conversion. Not what I wanted.
I still have a couple of irons in the fire (a Java stored procedure maybe), but since we have decided to go with an alternative solution they are not top priority at the moment.
Thank you all for the support,
Tim.
(If I get a solution, and this thread is still up, I will post an answer!!!)
 
T Bush
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm implemented something very similar. First, your serialized objects need to contain something like this....
/** used for serialization compare - use any hex number**/
static private final long serialVersionUID = 0x2b3dBf00F00db2d3L;
This should get rid of you java.io.InvalidClassException: java.util.Date; Local class not compatible: stream classdesc serialVersionUID=7523895402267505689 local class serialVersionUID=7523967970034938905 problems...
As for the database, check out this code...
Connection myConn = aTransaction.getConnection();
StringBuffer myBuffer = new StringBuffer();
// serialize and get a byte array. Make inputstream for object
byte[] myBuf = serializeUserPreference(myClass);
ByteArrayInputStream baiStream = new ByteArrayInputStream(myBuf);
myBuffer.append("INSERT INTO ")
.append(TABLE_NAME)
.append("(")
.append(getInsertColumns())
.append(") ")
.append("VALUES (?, ?, ?, ")
.append(FhcDataManagement.DATE_TIME)
.append(")");
PreparedStatement ps = myConn.prepareStatement(myBuffer.toString());
ps.setLong(1, myClass.getKey());
ps.setLong(2, myClass.getParentKey());
ps.setBinaryStream(3, baiStream, myBuf.length);

ps.execute();
/* serialize obj */
private byte[] serializeUserPreference(UserPreference obj) throws FhcException {
byte[] result;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
result = baos.toByteArray();
oos.flush();
oos.close();
}
catch(Exception e) {
throw new FhcException(e);
}
return result;
}

Let me know if this helps...
------------------
Todd Bush
AIM: RalphWiggam14
[This message has been edited by T Bush (edited April 20, 2001).]
 
Tim Williams
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So what was your database?
And what was your table definition? Can you do a setBinaryStream in to a Varchar column? (Recall I am constrained by an existing DB2 table definition.)
Also, does you mean the characters generated by the SerialUID are the only ones that are giving problems with the code page? I suspect not as adding a java.util.Date property was the one that seemed to start causing me problems, until then it was all just fine....
I also know that a 'database' such as MSAccess will work with no problems as I don't think it does any code page conversions.
Still fighting!!!
Tim.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic