Saturday, January 10, 2015

Multi-threaded Java Concurrent program in Oracle eBusiness Suite R12

The customer had an existing custom PL/SQL concurrent program that looped through a result set and processed each row sequentially. As volume grew, this sequential processing took longer and longer as some rows that took longer to process held up the remaining rows in the result set.
We needed something to process rows in parallel, 5 or 10 at a time. Using DBMS_PARALLEL_EXECUTE in PL/SQL did not yield good results, so we had to look for something else.
A Google search on "Java Multithreading" got me to this wonderful post  that provided the direction for us to create a Java concurrent program to enable parallel processing.

The Java concurrent program uses the Executor framework - java.util.concurrent.* - as well as the Inner Class pattern so that the threads can access members of the executor as if they are part of the outer executor class.

public class MyParallelConcProg implements JavaConcurrentProgram {

    public class WorkerThread implements Runnable {



Logic:
//1. Define number of parallel threads
String numberOfThreads = parameters.get("p_number_of_threads");
        numberOfThreads = (numberOfThreads == null) ? "5" : numberOfThreads;

//2. Create the parallel thread pool
        ExecutorService executor = Executors.newFixedThreadPool(new Integer(numberOfThreads)); // parameter then profile

//3. Call PL/SQL function that returns a REF CURSOR for the result set to loop through
String sql = "begin ? := MYPKG.get_cursor;end;" ;
               
 try {
          stmt = cpContext.getJDBCConnection().prepareCall(sql); // cpContext.getJDBCConnection().prepareStatement(sql);
          i = 1;
          stmt.registerOutParameter(i++, OracleTypes.CURSOR);

           stmt.execute();

          resultSet = ((OracleCallableStatement)stmt).getCursor(1); 

//4. Now loop through the result set and process each row
while (resultSet.next()
{
              Runnable worker = new MyParallelConcProg .WorkerThread( ....
  
             executor.execute(worker);
}


//5. The run() method in the WorkerThread class processes the row from the result set
    public void run() {
            String prefix = Thread.currentThread().getName() + " " + <some identifier from the result set>+ ": ";
        // get connection from the pool
            OracleConnection connection = (OracleConnection)cpContext.getExtraJDBCConnection(this, cpContext.getSessionId());
        OracleCallableStatement stmt = null;
stmt = (OracleCallableStatement)connection.prepareCall(
                " BEGIN MYPKG.process_row(...); end;" 
        

Each thread uses a separate database connection, so there are always n+1 DB connections while the concurrent program runs. While it is tempting to use a large number of threads, there is a practical limit and we have not seen the need to go over 5 threads for our requirement. We did go as high as 20 threads during stress testing and were very satisfied with the results. 

The DB connections for each thread do not inherit the concurrent request settings such as Request Id, Requestor etc. However, since the WorkerThread is an Inner Class, it has access to the cpcontext member of the outer executor class and can get to the concurrent request id by calling cpContext.getReqDetails().getRequestId())

I have skipped details like parameters passed to the PL/SQL statements since your requirements will be different. Also details pertaining to concurrent program log messages can be found in the developer's guide, so I have not mentioned that in this post.



Thursday, January 8, 2015

Descriptive Flexfields in Oracle Application Express

It has been over 2 years since I posted anything on this blog. I have had the good fortune of being on a project where I have been exposed to a variety of technologies - Oracle Fusion Middleware, SOA Suite, Exalogic, Exadata, Oracle DBFS, Oracle Application Express - to name a few.

In this post, I invite you to check out the Oracle APEX application where I have implemented Oracle eBusiness Suite like Descriptive Flexfield functionality.

The solution uses only PL/SQL and APEX - no AJAX or JavaScript.

You can access the application here. Log in using "guest/ myflex_demo".

If you like what you see and would like more information, add a comment with your email address and I will gladly share my code.

Tuesday, January 1, 2013

Happy 2013! A new year , a new blog post - BIP Images, OA_MEDIA and the desktop

Happy New Year! Wow, another eventful year gone by , yet there's so much to do, so much more to learn!

Embedding images within BI Publisher templates is old hat now and very well documented - this blog post is specific to using BIP within eBusiness Suite and accessing images dynamically using $OA_MEDIA (or any other environment variable).

The Oracle XML Publisher Report Designer's Guide has a section on using OA_MEDIA reference to load images dynmically from the application server using the following syntax:

url:{concat('${OA_MEDIA}','/',IMAGE_FILE)}

However the documentation does not mention how to use this reference when previewing the template from the BIP desktop plugin for MS Word. When I asked some developers what they did to preview their images I found that most of them either did not preview images on the desktop or if they did, they would change the Alternative text (Alt-text) region of the dummy image in the RTF template!

A simple configuration allows you to use the OA_MEDIA reference on the desktop to preview your images and to use the same template on all platforms.

XDO.cfg setup to reference $OA_MEDIA on BIP desktop

1.       Copy the LOGO images to a directory on your desktop – say C:\XDO\Images
2.       Look for “xdo example.cfg” under “C:\Program Files (x86)\Oracle\BI Publisher\BI Publisher Desktop\Template Builder for Word\config” or “"C:\Program Files\Oracle\XML Publisher Desktop\Template Builder for Word\config” depending on the BIP desktop version you have installed.
3.       Copy “xdo example.cfg” to “xdo.cfg”
4.       Modify xdo.cfg -(a) Look for system-temp-dir and give it a valid directory name
e.g. <property name="system-temp-dir">c:\temp</property>
(b) Look for </properties>
(c) Add a line above that
<property name="user-variable.OA_MEDIA">file:///C:\XDO\images</property>
Note: The directory name MUST match the location of your images on the desktop
5.       Save xdo.cfg


With this configuration, you have set $OA_MEDIA to C:\XDO\images on your desktop. You can now preview logos in BIP desktop before loading the RTF template into eBusiness Suite.

Tuesday, May 1, 2012

Collaborate 12 Keynote Address by Captain Mark Kelly

Captain Mark Kelly, US Navy captain, astronaut, Commander of Space Shuttle Endeavor's final mission, husband of Congresswoman Gabrielle Giffords delivered the keynote address at Collaborate 12 in Las Vegas on Monday April 23rd, 2012. The address was titled "Leadership, Teamwork, Courage". Simple. 

Captain Kelly is a marvelous orator and knows how to tell a story. He shared his experiences and the lessons he learned along the way and all I could think was "RESPECT Captain!"

Some of the things I came away with after the address - 

1) What you are at the beginning does not define what you become in the end. Hard work and determination play a large part in molding your future.

2) None of us is as dumb as all of us. When decisions are made by a team, it is very rare to hear voices of dissent for several reasons, mainly fear of rejection. So team members choose to remain silent and quite often it results in the wrong decision being made. How many times have you seen the junior most team member being asked for an opinion before a senior member? Something worth considering...

3) There is nothing so important that should prevent you from communicating with your team. Clear and timely communication prevents a lot of issues down the road.

4) There is nothing stronger than the human spirit, as Captain Kelly's wife has shown. You can deny the acceptance of failure. Perseverance, patience and strong will can move mountains.

Thank you Captain Kelly!

Thursday, February 23, 2012

Listagg - or in my case Listagg AAAAARGH!

Oracle 11gR2 introduces a new analytical and reporting function LISTAGG that orders data within each group based on the ORDER BY clause and then concatenates the values of the measure column. See Chapter 22 in the Oracle Data Warehousing Guide 11g Release 2


Why Listagg AAAAARGH!? If I had taken the time 2 weeks ago to familiarize myself with the new features in 11gR2, I wouldn't have written a function to do exactly what LISTAGG does! 



Friday, February 10, 2012

A blast from the (not so distant) past!

Some time last week I got an email from someone who'd googled "extensible attributes" and stumbled upon my presentation at Collaborate '08. It's nice to know that he found this useful. 
I haven't dealt with TCA Extensible attributes since late 2007. 


Here's the link to the presentation - http://cdmsig.oaug.org/file/Collab08SIGTCAEXT1209951946.pdf

Friday, February 3, 2012

Ubuntu - I am because we are

I just installed Ubuntu 10.04 on my 7 year old Dell Inspiron 6000 that was running Windows XP and had become virtually unusable. I am kicking myself for not having gone the Ubuntu route earlier because I am extremely impressed with the ease of installation, setup and running. I feel like a kid with a new toy - one that I "built" myself and the best thing is that it's free!

I now have a LAMP environment - Linux Apache MySQL PHP - that I can play with.

Next - loading some Oracle software !