| Bug #59977 | ResultSet.getObject(String columnLabel) returns corrupted object when casting | ||
|---|---|---|---|
| Submitted: | 7 Feb 2011 3:54 | Modified: | 26 Feb 2011 14:09 |
| Reporter: | Anthony Cosgrove | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / J | Severity: | S3 (Non-critical) |
| Version: | 5.1.14 | OS: | MacOS (10.6.6) |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | ResultSet.getObect() | ||
[7 Feb 2011 15:50]
Mark Matthews
The driver hasn't automatically deserialized objects since 3.1.5, are you using "autoDeserialize=true" in your JDBC URL?
[7 Feb 2011 18:23]
Anthony Cosgrove
I have not... I wasn't even aware of that fact. Will try adding the suggesting phrase into the url and report back.
[7 Feb 2011 19:23]
Anthony Cosgrove
I added the suggested phrase to the URL. A different exception is thrown now. SQLException: Class not found: java.lang.ClassNotFoundException: IVR while reading serialized object SQLState: null VendorError: 0 I would expect this to not be thrown as a SQLException. Still makes me think the object is not being read back in by getObject() properly. I'm pretty sure the data is correct on the insert as using the streams method (in and out) everything is fine.
[7 Feb 2011 19:32]
Mark Matthews
JDBC drivers are expected to throw checked exceptions, namely SQLExceptions, so this is following the API. The CNFE, is probably due to the JDBC driver being in a different class loader than the class in question? All the JDBC driver is doing is creating a binary input stream and pulling that through an ObjectInputStream.
[7 Feb 2011 22:34]
Anthony Cosgrove
I figured getObject/setObject were wrappers... Still not quite sure why when I use the byte stream process for deserialization my class is deserialized properly. Are there any other tests I can do and attach to this report? There was something else I was reading when doing serialization, it was recommended for maximum portability to provide a SQLType INT when calling PreparedStatement.setObject(int parameter, Object obj, int SQLType).
[11 Feb 2011 3:56]
Bogdan Degtyariov
Anthony, Can you attach a complete java test case, which first serializes and then de-serializes the object from BLOB field in IVR table? Thanks.
[13 Feb 2011 2:27]
Anthony Cosgrove
Java test case - serialize with setObject() and byte stream comparison
Attachment: 59977-serializer-testcase.zip (application/zip, text), 1.45 KiB.
[13 Feb 2011 2:37]
Anthony Cosgrove
Ok I just uploaded a zip file containing to .java src files that will do the testcase. I have zero experience with JUnit so this was my only recourse (I'm a hobbyist programmer :P) IVR table schema: mysql> desc ivr; +---------+-----------+------+-----+-------------------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-----------+------+-----+-------------------+-------+ | uuid | char(36) | NO | PRI | NULL | | | data | blob | YES | | NULL | | | updated | timestamp | NO | | CURRENT_TIMESTAMP | | +---------+-----------+------+-----+-------------------+-------+ 3 rows in set (0.00 sec)
[25 Feb 2011 5:27]
Bogdan Degtyariov
Hi Anthony, Thank you for the test case. I tried running it in my environment and here is the output I initially received: IVR@59a34 Yup! [B@1cef4f7 The first time object de-serialized correctly through the ByteArrayInputStream class. Then de-serializing it from rs.getObject() gives just the byte array. Next, I enabled autoDeserialize=true and here is the output: IVR@21e554 Yup! IVR@b30913 As you see, both times the object was de-serialized into IVR. I did not get any exceptions when enabling automatic deserialization. Probably you should try never version of Connector/J, which is 5.1.15. Thanks.
[26 Feb 2011 14:09]
Anthony Cosgrove
Bogdan, Confirmed. I upgraded to 5.1.15 and I am able to successfully deserialize objects. Looks like whatever it was was fixed in the new minor release. Thanks!

Description: I serialized a number of classes which appear to write correctly to the designated blob field of my db using either PreparedStatement.setObject() or a combination of ObjectOutputStream and PreparedStatement.setBytes(). However when calling the getObject() method the returned de-serialized object is corrupted. The weird thing is ClassNotFoundException is not thrown but ClassCastException is. If I use the old method of using an ObjectInputStream with a ByteArrayInputStream then I get the correct results. expected results: de-serialization of a Class type object actual results: java.lang.ClassCastException: [B cannot be cast to IVR How to repeat: ResultSet rs; ivrsql = "select * from ivr"; ps = conn.prepareStatement(ivrsql); rs = ps.executeQuery(); rs.next(); j = (IVR)rs.getObject("data"); // java.lang.ClassCastException thrown here rs.close(); ps.close(); conn.close(); --- ivr table: uuid - char(36) data - blob ---------> Reading object from this field updated - timestamp Suggested fix: Not qualified to suggest :)