There is always time in your Enterprise Application's life when your code base is just to big to remember every class, then you don't remember what some projects do, then some modules... this is the time when you have to sit down and "waste" some time, and by wasting I mean not write some application code ;)
So today I'm starting building a test framework for our EJB3s...
http://jakarta.apache.org/cactus/getting_started.html
I'll try first with cactus... we will see if it's useful.
Thursday, 20 August 2009
Thursday, 13 August 2009
Oracle blobs...
Oracle again...
We have huge amount of data stored on Oracle database in blobs. Data is processed and compressed on middle tier box and then appended to blob. When I need to get the stream back I execute stored procedure looking more or less like that:
For 99% of the data it works perfectly but.... there always have to be some "but"... and Oracle sometimes throws an exception:
Which points to line with Dbms_Lob.READ method.
I logged all parameters for this call and length and offset are definetely in range, they are not null nor invalid....
Sometimes I really hate Oracle ;)
Solution:
Dbms_Lob.READ outputs BLOB chunk into RAW type which can store up to 32767 bytes so we have to put chunks of our BLOB into RAW buffer and append it each time to out param BLOB.
Don't forget to initialize out BLOB before the while loop:
We have huge amount of data stored on Oracle database in blobs. Data is processed and compressed on middle tier box and then appended to blob. When I need to get the stream back I execute stored procedure looking more or less like that:
SELECT [blobtable].blobdata INTO v_blob
FROM [blobtable] WHERE blobId=v_blobId FOR UPDATE;
Dbms_Lob.OPEN(v_blob, dbms_lob.lob_readonly);
Dbms_Lob.READ(v_blob, v_length, v_offset, p_blob);
Dbms_Lob.CLOSE(v_blob);
COMMIT;
FROM [blobtable] WHERE blobId=v_blobId FOR UPDATE;
Dbms_Lob.OPEN(v_blob, dbms_lob.lob_readonly);
Dbms_Lob.READ(v_blob, v_length, v_offset, p_blob);
Dbms_Lob.CLOSE(v_blob);
COMMIT;
For 99% of the data it works perfectly but.... there always have to be some "but"... and Oracle sometimes throws an exception:
ORA-21560: argument 2 is null, invalid, or out of range
ORA-06512: at "SYS.DBMS_LOB", line 751
ORA-06512: at "[dbname].[packagename]", line 5535
ORA-06512: at "SYS.DBMS_LOB", line 751
ORA-06512: at "[dbname].[packagename]", line 5535
Which points to line with Dbms_Lob.READ method.
I logged all parameters for this call and length and offset are definetely in range, they are not null nor invalid....
Sometimes I really hate Oracle ;)
Solution:
Dbms_Lob.READ outputs BLOB chunk into RAW type which can store up to 32767 bytes so we have to put chunks of our BLOB into RAW buffer and append it each time to out param BLOB.
Don't forget to initialize out BLOB before the while loop:
DBMS_LOB.CREATETEMPORARY(p_blob, true);
Tuesday, 4 August 2009
Java reflection joy :)
Today I had to get database credentials to create connection manually. Of course in JBoss you are defining DataSource in default-ds.xml or in our case oracle-ds.xml which is then parsed by JBoss and you can get a Connection from JNDI (if its registered ;).
But if you have to create connection with the same credentials inside the EAR file which means you would have to specify username, password and db URL again the whole idea about keeping one information in one place fall apart and coding and deploying become to be huge pain and its error prone!
So... of course, the easiest way to get those credentials which are kept in private field called mcf in WrappedDataSource is to use reflection. mcf is a LocalManagedConnectionFactory (org.jboss.resource.adapter.jdbc.local) object which exposes all database configuration as properties. But if you think that you can write:
you are wrong ! ;)
Even if getDeclaredField method returns explicitly Field (java.lang.reflection) you still have to cast it to Field!!! So the final code looks like that:
I can enjoy java over and over again ;)
But if you have to create connection with the same credentials inside the EAR file which means you would have to specify username, password and db URL again the whole idea about keeping one information in one place fall apart and coding and deploying become to be huge pain and its error prone!
So... of course, the easiest way to get those credentials which are kept in private field called mcf in WrappedDataSource is to use reflection. mcf is a LocalManagedConnectionFactory (org.jboss.resource.adapter.jdbc.local) object which exposes all database configuration as properties. But if you think that you can write:
Field localManagedConnectionFactory = WrapperDataSource.class.getDeclaredField("mcf");
you are wrong ! ;)
Even if getDeclaredField method returns explicitly Field (java.lang.reflection) you still have to cast it to Field!!! So the final code looks like that:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:OracleDS");
Field localManagedConnectionFactory = (Field)WrapperDataSource.class.getDeclaredField("mcf");
localManagedConnectionFactory.setAccessible(true);
LocalManagedConnectionFactory mcf = (LocalManagedConnectionFactory )localManagedConnectionFactory.get(ds);
String database = mcf.getConnectionURL();
DataSource ds = (DataSource) ctx.lookup("java:OracleDS");
Field localManagedConnectionFactory = (Field)WrapperDataSource.class.getDeclaredField("mcf");
localManagedConnectionFactory.setAccessible(true);
LocalManagedConnectionFactory mcf = (LocalManagedConnectionFactory )localManagedConnectionFactory.get(ds);
String database = mcf.getConnectionURL();
I can enjoy java over and over again ;)
Monday, 3 August 2009
Oracle partitioning pain
I spent pretty much whole day trying to load data to Oracle Database. The problem was that partitions should be created automatically while data is loaded but this code apparently didn't work.
So I was getting:
java.sql.SQLException: ORA-14400: inserted partition key does not map to any partition
ORA-06512: at "####################.#########", line 307
and when I was trying to create partition manually:
java.sql.SQLException: ORA-20000: QEM00000000000000002296-ORA-00936 : Unanticipated error occured in PrepareMsgStream. At RunPoint, Adding a partition to MSGBLOB.
The code to create the partition looks like that:
v_DDL := 'ALTER TABLE '||v_TableName||' ADD PARTITION '||v_PartitionName;
v_DDL := v_DDL ||' VALUES LESS THAN ('||v_HighValue||') TABLESPACE '||v_TableSpace;
v_DDL := v_DDL ||' LOB (BlobData) STORE AS '||v_PartitionName||' (TABLESPACE '||v_TableSpace||')';
EXECUTE IMMEDIATE v_DDL;
The problem was with helper function which gets v_HighValue... so it's good to use Dbms_Output.Put_line(v_DDL); to make sure you are executing the code you think you execute ;)
So I was getting:
java.sql.SQLException: ORA-14400: inserted partition key does not map to any partition
ORA-06512: at "####################.#########", line 307
and when I was trying to create partition manually:
java.sql.SQLException: ORA-20000: QEM00000000000000002296-ORA-00936 : Unanticipated error occured in PrepareMsgStream. At RunPoint, Adding a partition to MSGBLOB.
The code to create the partition looks like that:
v_DDL := 'ALTER TABLE '||v_TableName||' ADD PARTITION '||v_PartitionName;
v_DDL := v_DDL ||' VALUES LESS THAN ('||v_HighValue||') TABLESPACE '||v_TableSpace;
v_DDL := v_DDL ||' LOB (BlobData) STORE AS '||v_PartitionName||' (TABLESPACE '||v_TableSpace||')';
EXECUTE IMMEDIATE v_DDL;
The problem was with helper function which gets v_HighValue... so it's good to use Dbms_Output.Put_line(v_DDL); to make sure you are executing the code you think you execute ;)
Tuesday, 28 July 2009
Help others!
I know that many of us owns really powerful machines (PCs). Many of us use the full power for a fracture of a time they are turned on. We can donate our processing power to help solve global problems like finding cure for cancer, aids and other diseases. Just register for project like WorldCommunityGrid and make a difference!
Start...
Last week, finally, I got my new computer. It was a hard time for me to work on a 5 year old machine which needs an hour to build our application and next 15 minutes to deploy it and start JBoss....
So right now when I have couple of spare minutes I can blog.... :)
I'm sure you are all happy about it...
So right now when I have couple of spare minutes I can blog.... :)
I'm sure you are all happy about it...
Subscribe to:
Posts (Atom)