|
|
A Brute Force Approach to
Debugging Forms: What to do when you don't know what is happening?
Ryan Gaffuri, Bloodworth Integrated
Technology
Your sitting at your desk and your manager comes over to you hands you an issue that needs to be fixed. The client is complaining because something is not working, let it be a forms crash, triggers acting improperly, or anything else. This is the kind of thing that the Oracle documentation and the books do not discuss. You have no idea what is going on. You scan Metalink and OTN to see if anyone else has had this issue and find nothing. The Oracle representative responds to your post saying that they were unable to recreate the error. You’re under time pressure. The client and your management want this fixed. What do you do?
I start with the methodology that you can do anything with the Oracle toolset. You just have to figure out the best and most cost effective way to do it. I do not accept the concept that this is the cause of some Oracle bug and therefore cannot be done. There is a work around for everything. On my current project, I encountered a significant number of errors that were leading to forms crashing. At first we thought they were problems with the forms server. This turned out to be partially correct. There were several things that seemed to crash on the web that did not crash in client server. However, since I started with the methodology that you can do anything, I formed a specific system for tracking these kinds of bugs down.
Advantages of this system:
Premises of the System:
Case Study Using a Template Form:
Our application is run on the web using the form server tool. I received a write up from test regarding a forms crashing error during a simple process. I immediately went to test and asked them exactly what they did just before the forms crashed. I then went back to my desk and was successfully able to recreate the error. Instead of looking at all the trigger code and the program units and the libraries I made a simple template form that included 3 blocks in a master-detail-detail relationship. I then ran the form and followed our process. The error occurred. At this point, I knew that there was something fundamentally wrong with the form.
I then broke all the relationships between the blocks and ran the form. The error occurred. I then deleted the detail blocks from the form. Error still occurred. I then deleted half my items from my master block. It was at this moment that the error ceased to occur. So I knew that there was something in the item(s) that I took off the screen. From here I was able to determine that one of my text items needed to be flagged as a multi-line item. If forms tried to query a multi-line row from the database and if the multi-line flag in the property palette was not set to yes, the form would crash. It never occurred to me that this simple flag would lead to a forms crashing problem, however, by simply using a template form I was able to find the problem and fix it in about 30 minutes.
Things to identify first:
STEP 1: Your template works, but your bug is not fixed
At this point, I recommend using a forms built in feature to help you track down where the error is occurring. Go to Tools à Preferences. Click the Runtime tab and place a check mark in the debugging messages. This will popup a message and pause the form every time a trigger is fired. Pay particular attention to the last trigger fired before the error occurs. This process can get tiresome if you using a form with a large amount of triggers. There is another downside. In some of the more complex forms the error messages get caught in an infinite loop and the same message will continue to fire. (this also happens when using the forms debugging tool). Let’s your form crashes when it starts up. These messages can identify the last trigger fired before the form crashed. You can then look at the code in the trigger, look at any code that the trigger is calling, and look at the property palette of the object that is firing the trigger. Now you can simply go back and follow Premise #4 and comment out the code (or simplifying it if it’s necessary for the transaction) you can quickly identify what part(s) of the code are not causing the problem. Then you will be left with what is causing the problem.
STEP 2: If it’s Broke… Break it even more
If your template form works properly and you were not able to narrow your search using the debugging messages, its time to literally rip your form apart. You are going to take out objects from your block until it works, then slowly put them back in until it does not work again in order to determine where it is breaking. I also recommend saving your form in various stages of disarray. Whenever objects are eliminated, code referencing those objects needs to be commented out and this can be time consuming. Due to the difficulty with commenting out code, I prefer to move as much logic from triggers to program units, so I simply have to comment out the program unit code and set it to null.
STEP 3: Where to Start Breaking the Form?
I have a process that I like to follow every time I break my form. However, it is not essential to do it my way. What is important is that you develop a system then do it exactly the same way every time. This way you do not have to worry about missing anything and you can focus on the problem at hand. I prefer to do this in a block-by-block format. I like to begin by breaking all the relationships between the data blocks and testing to see if the form works. Even if I’m 99% sure that this will have no effect, it is important to stick with the process. That way I know for certain that I checked everything.
After running the form and testing it without relationships, I then start deleting detail blocks one at a time. Eventually Ill be left with my master block. I then know that the error is taking place somewhere in the master block. So, I will delete 50% of the items in the block and run the form. Does the error still occur? If it does then I know that the items I deleted did not cause the error. I then delete another 50%. Ill do this until the error ceases to occur. If the ceased to occur one of the detail blocks, Ill use the same system of deleting items from the detail block. As soon as I have deleted enough items from the block that the error ceases to occur, I move to step 4.
STEP 4: The bug hunt has been narrowed
Next Ill start adding items to the block a few at a time, until the error occurs again. As soon as the error occurs again, I know that it is related to the items I just re-added. I then pull those out one at a time, until the error ceases. When the error ceases I know that it is related to that item. This does not necessarily mean it is either a property palette issue directly related to the item, a trigger on the item, or a program unit called from a trigger on the item. It could be caused from a form, block level, or a trigger called from a button, radio button, etc… In some circumstances a property palette issue at the block or form level that is conflicting with something to do with the item. The error could also be caused from by a call from to a database object.
The first thing I do at this point is check the property palette if something strikes me as problematic. Then I comment out all the trigger code associated with the item. If the error still occurs I know that it is either being caused from a trigger (or a program unit in the form, attached library, or in the database) or it’s a property palette issue. From here I continue to narrow my search by either commenting out code or placing messages for myself in the code to see where the code fails.
STEP 5: Other things to consider:
In Parting….
In most cases you will have an idea of what is causing the error. Whether it is a specific trigger, a transaction, a call to a database item, etc… However, this method can still be applied. I find that using a simple process of elimination helps organize my thoughts and focus my hunt. By following the same process every time, I am able to focus strictly on the problem at hand without having to worry that I missed something. The material here is hardly revolutionary. It’s simply a matter of being meticulous.