Nothing else was changed in the code, other than updating the JDK on the database server (dbm cfg parm jdk_path) and recompiling/executing the code with 1.4.1 (deploying the newly compiled stored procedure code as well).
This is the original exception that I got before I tried any code modifications:
java.io.IOException: invalid offset/length
at COM.ibm.db2.app.BlobOutputStream.write(Lob.java:33 7)
at java.io.ObjectOutputStream$BlockDataOutputStream.w rite(ObjectOutputStream.java:1698)
at java.io.ObjectOutputStream.defaultWriteFields(Obje ctOutputStream.java:1416)
at java.io.ObjectOutputStream.defaultWriteObject(Obje ctOutputStream.java:398)
at java.lang.Throwable.writeObject(Throwable.java:679 )
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:58)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:60)
at java.lang.reflect.Method.invoke(Method.java:391)
at java.io.ObjectStreamClass.invokeWriteObject(Object StreamClass.java:967)
at java.io.ObjectOutputStream.writeSerialData(ObjectO utputStream.java:1387)
at java.io.ObjectOutputStream.writeOrdinaryObject(Obj ectOutputStream.java:1338)
at java.io.ObjectOutputStream.writeObject0(ObjectOutp utStream.java:1083)
at java.io.ObjectOutputStream.writeFatalException(Obj ectOutputStream.java:1449)
at java.io.ObjectOutputStream.writeObject(ObjectOutpu tStream.java:312)
at com.ibm.nzna.projects.common.storedProc.StoredProc Util.setObjectInBlob(StoredProcUtil.java:54)
at com.ibm.nzna.projects.common.storedProc.typeListRe ader.TypeListReader.readLists(TypeListReader.java: 166)
I get this exception when calling the stored procedure from within my java application. If I call the procedure from a DB2 command line (db2 call procedure QUEST.TypeListReader (1, 1, ?, ?)), the procedure executes properly. This leads me to believe that the problem therefore lies in trying to get the Blob object from the stored procedure return record. Here are snippets of the code used to call the procedure:
This is the method that calls the procedure:
Expand|Select|Wrap|Line Numbers
- private boolean readTypeListUsingStoredProcedure ( TypeListRec typeListRec, SQLMethod sqlMethod ) {
- boolean rc = false ;
- try {
- CallableStatement stmt = sqlMethod.createStoredProc ( "QUEST.TypeListReader", 4 ) ;
- TypeListReaderRec typeListReaderRec = null ;
- /*-----------------------------------------------------------*/
- /* */
- /* Set up our parameters */
- /* */
- /*-----------------------------------------------------------*/
- stmt.setInt ( 1, languageInd ) ; // Our Language Indicator
- stmt.setInt ( 2, typeListRec.getTypeListInd() ) ; // Our Type List to read
- stmt.registerOutParameter ( 3, Types.LONGVARBINARY ) ; // The return Lob for TypeListReaderRec
- stmt.registerOutParameter ( 4, Types.LONGVARBINARY ) ; // The return Lob for StoredProcRetRec
- /*-----------------------------------------------------------*/
- /* */
- /* Execute */
- /* */
- /*-----------------------------------------------------------*/
- stmt.execute() ; // make the call to the stored procedure
- /*-----------------------------------------------------------*/
- /* */
- /* Get the StoredProcRec from the Lob */
- /* */
- /*-----------------------------------------------------------*/
- StoredProcRec retRec = (StoredProcRec)StoredProcUtil.getObjectFromStatement ( stmt, 4 ) ;
- if ( ( retRec != null ) && ( retRec.error ) ) {
- LogSystem.log ( 1, retRec.errorStr ) ;
- }
- /*-----------------------------------------------------------*/
- /* */
- /* Otherwise continue */
- /* */
- /*-----------------------------------------------------------*/
- else {
- /*-----------------------------------------------------------*/
- /* */
- /* Get our return object */
- /* */
- /*-----------------------------------------------------------*/
- typeListReaderRec = (TypeListReaderRec) StoredProcUtil.getObjectFromStatement ( stmt, 3 ) ;
- getInstance().setTypeList ( typeListRec.getTypeListInd(), typeListReaderRec.retVec ) ;
- rc = true ;
- }
- } catch ( Exception e ) {
- sqlMethod.rollBack() ;
- LogSystem.log ( 1, e, false ) ;
- }
- return ( rc ) ;
- }
- This is the method that is defined as the procedure's external name (TypeListReader!readlists (...):
- public void readLists ( int languageInd, int typeListInd, Blob retTypeListReaderRec, Blob storedProcRetRec ) throws Exception {
- try {
- /*-----------------------------------------------------------*/
- /* */
- /* Get our connection to DB/2 */
- /* */
- /*-----------------------------------------------------------*/
- con = getConnection() ;
- /*-----------------------------------------------------------*/
- /* */
- /* Initialize our Type List Reader Record */
- /* */
- /*-----------------------------------------------------------*/
- typeListReaderRec = new TypeListReaderRec () ;
- readLists ( languageInd, typeListInd, con, typeListReaderRec) ;
- /*-----------------------------------------------------------*/
- /* */
- /* Write out our TypeListReaderRec */
- /* */
- /*-----------------------------------------------------------*/
- *** I create a new Blob object from COM.ibm.db2.app.Lob, then pass it to my setObjectInBlob method along with typeListReaderRec, which contains the data I want to pass back to the client ***
- retTypeListReaderRec = Lob.newBlob() ;
- StoredProcUtil.setObjectInBlob ( retTypeListReaderRec, typeListReaderRec ); //This is the method call that fails
- set ( 3, retTypeListReaderRec ) ;
- } catch ( Exception e ) {
- StoredProcUtil.writeException ( e, returnRec ) ;
- }
- /*-----------------------------------------------------------*/
- /* */
- /* Commit */
- /* */
- /*-----------------------------------------------------------*/
- con.commit() ;
- con.close() ;
- /*-----------------------------------------------------------*/
- /* */
- /* Write out our return information */
- /* */
- /*-----------------------------------------------------------*/
- storedProcRetRec = Lob.newBlob() ;
- StoredProcUtil.setObjectInBlob ( storedProcRetRec, returnRec ) ;
- set ( 4, storedProcRetRec ) ;
- }
- This is the method that places the return object into the blob:
- public static void setObjectInBlob ( Blob blob, Object object ) throws Exception {
- ObjectOutputStream s = new ObjectOutputStream ( blob.getOutputStream() ) ;
- s.writeObject ( object ) ; // This is the line that actually fails
- s.flush() ;
- s.close() ;
- }
- This is how TypeListReaderRec is defined (the object I am passing back to the client). It is just a collection of Vector objects:
- package com.ibm.nzna.projects.common.storedProc.typeListReader ;
- import java.util.* ;
- public class TypeListReaderRec implements java.io.Serializable {
- public Vector retVec = null ;
- public Vector countryCodeVec = null ;
- public Vector geographyVec = null ;
- public Vector docTypeVec = null ;
- public Vector docClassVec = null ;
- public Vector customViewVec = null ;
- public Vector workVec = null ;
- public Vector authVec = null ;
- public Vector metricVec = null ;
- public Vector languageVec = null ;
- public Vector fsVec = null ;
- } /* TypeListReaderRec */