You are on page 1of 20

Overview

1
Overview
Here, you'll learn how to investigate and resolve typical OA Framework problems using the
debugger. For additional information about this subject, see Debugging OA Framework
Applications in the Developer's Guide.

Debugging Lab Goals


After completing this exercise, you should have learned how to:
• Use source, method and class breakpoints in local project code, and in the underlying
technology stack (OA Framework classes).
• Debug three common exceptions: java.lang.NullpointerException,
java.lang.ClassCastException and oracle.jbo.SQLStmtException.
• Extract salient information from a stack trace.
• Read and use the call stack.
• Explore application module retention behavior using the debugger.
• Navigate the data structures of key OA Framework and BC4J classes using the
debugger.

Debug Lab Application Introduction


Here, you'll be working with a special "debug application" that was built to include errors for you
to find.
Note: This application is optimized for the purposes of this lab. It does not fully comply with
BLAF UI Guidelines or the OA Framework coding standards. For example, you'll see some
controller code that sets a web bean property that should be set declaratively. The code is
included specifically so we can introduce exceptions. This code should not be used as a model
for production code.
The debug lab "application" is included in the LabSolutions project, and it includes the following
components:
File Descriptio
n
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugLabSearchPG Search for
employees
page.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugSearchCO Controller
for search
region.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugSearchResults Controller
CO for results
region.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugLabCreatePG Create
employee
page.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugLabCreateCO Controller
for create
page.

2
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugLabAM Application
module for
debug
search
and create
pages.
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugEmpFullVO View
object
used in
debug
create
page.
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugEmpSummary View
VO object
used in
debug
search
page.
oracle.apps.fnd.framework.toolbox.schema.server.EmployeeEOImpl (and its Employee
associated expert, validation application module and validation view objects) entity
object.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugAPG Page used
in state
managem
ent debug
task.
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugBPG Page used
in state
managem
ent debug
task.
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugALabAM Application
module for
state
managem
ent debug
task.
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugBLabAM Application
module for
state
managem
ent debug
task.

3
Prerequisite
Here, ensure that your OADeveloperMode project option is enabled as described in Step 2 of
the Hello, World! lab.
If this is not enabled, you will not be able to access the error stack as intended in this lab.

4
Task 1: Investigate Unexpected Code Execution (Part 1)
Throughout this lab we ask that you run the test_fwklabsolutions.jsp instead of running the
lab pages directly. When you debug your product code, you should do the same because of
subtle runtime differences between these methods (launching from a test JSP more closely
approximates production deployment). Furthermore, running the test JSP gives you a
convenient stopping point for setting breakpoints before accessing "broken" pages, and it lets
you navigate more freely around your application with the menu present.
• In the LabSolutions project, run test_fwklabsolutions.jsp in debug mode.
• Select the Debug Lab link when the test page renders.
• When the Search page renders, select the Go button to perform a blind query (this page
does not comply with the coding standards that prohibit blind queries!). Note that no
results are displayed in the table.
• Add breakpoints to the following source code (use the instructions provided in the Hello,
World! lab if you need them).
o In oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugSearchCO,
add a breakpoint inside the processFormRequest method at this line of code:
super.processFormRequest(pageContext, webBean);
o In
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugLabAMImpl,
add a breakpoint inside the initQuery method at this line of code:
DebugLabEmpSummaryVOImpl vo = getDebugLabEmpSummaryVO1();
o In
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugEmpSummar
yVOImpl, add a breakpoint inside the initQuery method at this line of code:
StringBuffer whereClause = new StringBuffer(100);
• Select the Go button again.
At this point, you'll notice that your processFormRequest method isn't called at all. Can you
figure out why this isn't happening and fix it? See the corresponding Task 1 solution if you need
help. Note that you cannot test your fix (you'll encounter the NullPointerException planned
for Task 2). For now, simply make the required change and terminate your OC4J process.
Tip: You must fix each error in sequence before moving on to the next task.

5
Task 2: Resolve a NullPointerException (NPE)
In this task, you'll resolve one of the most common exceptions that you'll encounter: a
java.lang.NullPointerException. This means you tried to invoke a method on a
variable that has not been initialized.
• Run test_fwklabsolutions.jsp in debug mode.
• Select the Debug Lab link when the test page renders. Note that a standard OA
Framework error page displays as shown in Figure 1.
Figure 1: Example of an OA Framework Error Page

This generic error page renders whenever an unexpected exception is thrown. To access
additional information about the error so you can debug it, select the here link. The OA
Framework then displays the complete stack trace associated with the uncaught exception (a
"stack trace" is a snapshot of the code execution path at the point where the exception is
raised).
Don't be daunted by the size of the stack trace; most of the content is superfluous for your
debugging purposes. To find the nugget of information that you need to proceed, look for the
text ## Detail 0 ## in the stack trace and read the exception data that immediately follows it.
For this particular error, Figure 2 shows that a NullPointerException was raised in the
processRequest method at line 38 in the
oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugSearchCO class.
Figure 2: ## Detail 0 ## Stack Trace Information for a NullPointerException

Tip: Fortunately, when using the JDeveloper packaged for Oracle Applications, debug
information is compiled into the code so line numbers are provided in the stack trace. If you
work with a stack trace that doesn't contain explicit line numbers, you need to create an
exception breakpoint as shown in Task 4 below.
Since we know exactly what the source of the NullPointerException is, we don't need to
bother creating an exception breakpoint (you can always create one later if you need it).
Instead, we can go right to the broken source code as shown in Figure 3 below. In most cases,
you can simply glance at your code and figure out why the object you expected to be
instantiated (in this case, an OAMessageTextInputBean) is null.
Figure 3: Source of the NullPointerException

6
Try to figure out what is wrong with this code so you can fix it. If you need help so you can
proceed, see the corresponding Task 2 solution.
Proceed to Task 3 before testing your fix.

7
Task 3: Resolve a ClassCastException
In this task, you'll resolve another common exception: a java.lang.ClassCastException.
This means you tried to perform an invalid cast from one object type to another.
Tip: If you're relatively new to Java and need additional information about class casting, please
check the following for tutorials, documentation and book suggestions:
• Oracle Technology Network
• JavaSoft Java Developer Connection
To proceed:
• Run test_fwklabsolutions.jsp in debug mode.
• Select the Debug Lab link when the test page renders. Note that a standard OA
Framework error page displays as shown in Figure 1 above. Select the here link to
access the stack trace, and look for ## Detail 0 ## as shown in Figure 4 below.
Figure 4: ## Detail 0 ## Stack Trace Information for a ClassCastException

This tells us that we have a ClassCastException at line 37 in the processRequest


method of the oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugSearchCO
class. It also tells us that the class that we're incorrectly casting is
oracle.apps.fnd.framework.webui.beans.message.OAMessageLovInputBean (this is the
"message" part of the exception). In other words, we have an OAMessageLovInputBean that
we're trying to cast to something else, and it's not working.
Figure 5 shows the code at line 37 that is causing the exception. Try to figure out what is wrong
with this code so you can fix it. If you need help so you can proceed, see the corresponding
Task 3 solution.
Figure 5: Source of the ClassCastException

8
Task 4: Resolve a SQLStmtException
In this task, you'll resolve a problem with the SQL statement that you try to execute when
searching for employees.
• Run test_fwklabsolutions.jsp in debug mode.
• Select the Debug Lab link when the test page renders.
• Select the Go button to perform a blind query. Note that query results are properly
displayed.
• Enter the value "1" in the Employee Number field, and select the Go button. The error
message shown in Figure 6 displays at the top of your page. This tells you that there is
"something" wrong with the SQL statement you tried to execute, but it doesn't give you
enough information about what you need to fix. For this, we need an exception
breakpoint so we can dig a little deeper into the problem (exception breakpoints are
essential if you need more information about the code that was executed before the
exception is thrown, and you want to explore code state at the point where the exception
is thrown).
Tip: The generic OA Framework error page doesn't display in this case because the underlying
exception is caught and "packaged" by BC4J as a user-friendly error message to be displayed
at the top of the page.
Figure 6: SQLStmtException Displayed in an Error Message Box

To create an exception breakpoint:


• Place your cursor in the JDeveloper Breakpoints tab shown in Figure 7 below (note that
this tab generally displays only when you run in debug mode, however you can also add
a breakpoint when you are not in debug mode by choosing View > Debug Windows >
Breakpoints from the main menu).
• Right-click and select New Breakpoint... from the context menu.
• In the New Breakpoint window, set the Breakpoint Type to Exception and set the
Exception Class to the fully qualified name of the exception (in this case,

9
oracle.jbo.SQLStmtException).
• Select OK to save your breakpoint.
Figure 7: JDeveloper Breakpoints Tab

To proceed, select the Go button again (with your Employee Number search criteria).
Assuming JDeveloper has access to the source code, it stops execution at the point where the
exception is thrown as shown in Figure 8 below. Specifically, execution halts just before the
highlighted line of code.
Figure 8: Exception Breakpoint for SQLStmtException

In this case, the exception is being thrown in the executeQuery method in the
QueryCollection class. This is reflected in the source code above, and in the call stack (the
Stack tab) as shown in Figure 9.
The call stack is a useful tool that reflects the code execution path in relation to the current
breakpoint (it changes as you step through your code using the debugger). It is particularly
helpful if you want to access code that was executed before your breakpoint was reached. So,
for example, you might read the following and decide that you want to add a breakpoint in the
OAViewObjectImpl's executeQuery method so you can step through the code from this
point until you reach the exception. To quickly access the executeQuery method, simply
double-click that line in the Stack window to open the corresponding source.
Tip: Try right-clicking on the class or method names in the call stack. You'll see several other
options that you might want to explore. For example, you can choose Export... to save a copy of
the call stack.
Figure 9: Call Stack State When the SQLStmtException is Thrown

10
For this particular error, we really don't need to navigate the call stack and add breakpoints at
earlier processing points. Instead, we need to examine the exception state to see if it includes
additional information that is not included in the message BC4J presents to the user. Figure 10
shows the Smart Data debugging window contents when the SQLStmtException breakpoint
is reached. At this level, the exception includes the underlying ORA error, which is much more
specific about the root cause of the problem. Now, instead of just knowing that we have a bad
SQL statement, we know what to look for: our SQL statement includes the identifier
EMPLOYEE_NUMBER, and this is invalid.
Try to figure out what is wrong with this code so you can fix it. If you need help so you can
proceed, see the corresponding Task 4 solution.
Note: When you know your code well, you can often solve these problems by simply reading
your SQL statement as shown in the original error message in Figure 6 above. It's worth getting
in the habit of looking at this quickly before bothering to debug the code since the problem may
be obvious to you.

11
Figure 10: Smart Data Window Showing Code State

Tip: When execution stops on the initial exception throw, and you select the Resume debugging
action, JDeveloper halts each time this exception is rethrown in the call stack. If you don't need
additional information about how this exception is handled throughout the call stack, you can
always disable the breakpoint after the initial exception is thrown to save yourself some time.
Select the breakpoint in the Breakpoints window, right-click and select Disable Breakpoint. You
can toggle this as needed.
Tip: When you create NullPointerException breakpoints, you'll notice that you encounter
at least one in the course of normal page processing (for example, AppsConnectionManager
throws and handles an NPE). You should simply select the Resume debugging option when you
encounter these; the first relevant NPE is likely to be in your code.

12
Task 5: Use a Class Breakpoint
In this task, you'll use a class breakpoint to investigate all calls to a single class. This is very
useful when trying to learn how an unfamiliar class is used, and is more efficient than setting
multiple breakpoints if you have heavy interaction with a given class and want to verify
numerous method calls.
Tip: If you have problems with view object row initialization when creating new entity object
based rows, you might want to use a class method on your entity objects to examine its
initialization and data access.
To create a class breakpoint:
• Place your cursor in the JDeveloper Breakpoints tab.
• Right-click and select New Breakpoint... from the context menu.
• In the New Breakpoint window, set the Breakpoint Type to Class and select the
Browse... button next to the Class name field.
• In the Class Browser window, navigate through the packages and classes until you can
select the target class (in this case, you need to select
oracle.apps.fnd.framework.toolbox.schema.server.EmployeeEOImpl). Note that you
can also type your class name in directly without having to browse first.
• Select OK to save your breakpoint.
To execute your class breakpoint:
• In the LabSolutions project, run test_fwklabsolutions.jsp in debug mode.
• Select the Debug Lab link when the test page renders.
• When the Search page renders, select the Create button.
You'll notice that JDeveloper halts execution every single time a method is called in
EmployeeEOImpl and in any of its superclasses so you have a complete picture of how this
object behaves (feel free to disable the class breakpoint before stepping through all the method
calls!).
Please proceed directly to Task 6, but delete or disable your class breakpoint and select the
Resume debugging option first.

13
Task 6: Investigate Unexpected Code Execution (Part 2)
In the previous task, we used a class breakpoint for a fine-grained look at class usage. While
this can be very helpful in some situations, if you're experiencing a failure at a specific point in
your code, the class breakpoint provides far more information than you need. In this task, we'll
investigate an unexpected validation failure in an entity object.
To proceed:
• Select the Cancel button in the Create page to return to the Search page.
• Select the Create button again to return to the Create page.
• Enter all the required information for creating an employee (don't change the Position
poplist value from President since the page isn't coded to let you enter the Manager
value required for the other positions), and select the Apply button. Note that the
attribute-level validation error shown in Figure 11 displays.
Figure 11: PositionCode Validation Error

Whenever entity object validation fails at the attribute level, the first thing you should do is set a
breakpoint on the corresponding "setter" (in this case, setPositionCode). While you're in the
entity object, it's often helpful to put a break point on another "setter" for a value that isn't having
problems. Given this, please add breakpoints to the following methods:
• oracle.apps.fnd.framework.toolbox.schema.server.EmployeeEOImpl.setPositio
nCode
• oracle.apps.fnd.framework.toolbox.schema.server.EmployeeEOImpl.setLastName
(any other setter in the entity object would work just as well)
Tip: You could also define method breakpoints without opening the source code in your project.
For example, you could:
• Place your cursor in the JDeveloper Breakpoints tab.
• Right-click and select New Breakpoint... from the context menu.
• In the New Breakpoint window, set the Breakpoint Type to Method and enter the fully
qualified method name. For example:
oracle.apps.fnd.framework.toolbox.schema.server.EmployeeEOImpl.setLastName
• Select OK to save your breakpoint.
Remember that the OA Framework steps through a data "post back" phase when an HTTP

14
POST request is issued (the OA Framework calls the processFormData method for all items
in the web bean hierarchy). All the data on the page is written to the underlying view object(s),
which in turn write data to the underlying entity object(s). When you select the Apply submit
button, all the entity object setters corresponding to the data you enter on the page should be
called.
Tip: You might also want to add a breakpoint in the entity object's validateEntity method.
After calling all the setters in processFormData, the OA Framework valides each row in the
view object that it "dirtied" by setting values. If you add this breakpoint, you'll see when the
entity-level validation is performed.
For additional infromation about how and when data is read from and written to the server from
the UI, please see Implementing the View: Model Interaction in the OA Framework Developer's
Guide.
To execute your breakpoints:
• Select the Cancel button in the Create page to return to the Search page.
• Select the Create button again to return to the Create page.
• Enter all the required information for creating an employee (don't change the Position
poplist value from President since the page isn't coded to let you enter the Manager
value required for the other positions), and select the Apply button.
You'll notice that the setPositionCode method is NOT being called -- even though a value is
clearly selected in the poplist -- while the setSalary method is being called correctly.
Think about what might be wrong here so you can fix it. Start with your page definition, and
consider what must be defined correctly for the position value to be written to the entity object
attribute. If you need help, see the corresponding Task 6 solution.
Tip: When you've been debugging for a while, you often accumulate many breakpoints. When
you're ready to move on, you might want to use the Breakpoints window context menus option
Disable All or Remove All to quickly disable or delete your breakpoints.

15
Task 7: Explore Application Module Retention Behavior
In this simple exercise you'll use the debugger to explore application module retention behavior
while navigating between two pages. For additional information about this, see OA Framework
State Management in the Developer's Guide.

Step 7.1 Create Breakpoints


• Open oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugAPageCO and
add a breakpoint at the following line of code in processRequest: boolean isNew =
pageContext.isAMStateNew();
The isAMStateNew() method in
oracle.apps.fnd.framework.webui.OAPageContext is a convenient way for
your controller code to see whether the application module state is new, or whether a
cached application module with existing state was used for the page (in other words, the
application module was retained).
• Open oracle.apps.fnd.framework.toolbox.labsolutions.webui.DebugBPageCO and
add a breakpoint at the following line of code in processRequest(): Boolean isNew
= pageContext.isAMStateNew();
• Create a method breakpoint using the technique described above. The fully qualified
method name to use is
oracle.apps.fnd.framework.server.OAApplicationModuleImpl.beforeRelease.
The beforeRelease() method in
oracle.apps.fnd.framework.server.OAApplicationModuleImpl is called
just before an application module's state is reset. So, if you opt to release an application
module instead of retaining it, the OA Framework will call this method just before it
releases the application module.
Tip: Remember that all application modules extend OAApplicationModuleImpl, so
at runtime, this method will actually be called for the subclasses created for this lab:
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugALabAMImpl and
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugBLabAMImpl.

Step 7.2 Perform Test #1


• In the LabSolutions project, run the DebugAPG page in debug mode (you need to run
this directly; it is not accessible from the test_fwklabsolutions.jsp).
• When your first breakpoint is reached in DebugAPageCO, toggle the Data debugging
window from the default Smart Data tab to the Data tab as shown in Figure 12 below.
• Use the Step Over debugging option to execute each line of code in the
processRequest method. Note the state of the isNew, aVal and bVal variables in
the Data window. After executing the code that sets the transaction "APageValue" value,
select the Resume debugging option so the page can render.
• When the page renders, select the Page B (Retain AM) submit button. This will perform
a JSP forward to the DebugBPG page with the retainAM request parameter set to
true.
Figure 12: Data Window State When DebugAPG Initially Renders

16
• When you reach the DebugBPageCO processRequest breakpoint, carefully execute
each line of code and note the state of the isNew, aVal and bVal variables. You'll
notice that the isNew value is set to true, meaning that the application module state for
this page is new. Since we retained the AM when navigating to this page (check the
processFormRequest method in DebugAPageCO for confirmation), wouldn't you expect
this value to be false? Why might it be true? Also, if we saved the aVal value on the
transaction, why is it null? See the Task 7, Test 1 solution if you need help.
Note: do not stop running or make any changes to the code at this point.
• When the DebugBPageCO renders, select the Debug A (Retain AM) submit button.
This will perform a JSP forward back to the DebugAPG page with the retainAM
request parameter set to true.
• Again, use the debugger to step through the processRequest code and check the
state of the isNew, bVal and aVal variables. You'll notice that isNew = false, and
aVal = "A". Can you explain this? See the Task 7, Test 1 solution if you need help.
• When DebugAPG renders, this time select the Page B submit button. This will perform
a JSP forward back to the DebugBPG page with the retainAM request parameter set
to false.
• At this point, JDeveloper will halt execution at the beforeRelease method in the
OAApplicationModuleImpl source. However, if you look at the "this" pointer in the
Data window (for those who are new to Java, "this" iterally means "this object" -- a
reference to the current object), you'll see that the object type is actually
DebugBLabAMImpl.
• Select the Resume debugging option, and note that you again enter the
beforeRelease method for DebugALabAMImpl. When you set the retainAM
request parameter to false, ALL root UI application modules that are currently cached
(retained) are released.

17
Figure 13: Data Window State When beforeRelease Breakpoint is Reached

Step 7.3 Perform Test #2


• Terminate the current OC4J process and change the AM Definition property of
PageLayoutRN region in DebugBPG to
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugALabAMImpl.
• Run DebugAPG in debug mode. Step through the processRequest code noting the
variable states, and when the page renders, select the Debug B Page (Retain AM)
submit button. Again, the code performs a JSP forward to the DebugBPG while retaining
the application module.
• Before you debug the processRequest method in DebugBPG, what do you expect
the isNew, aVal and bVal variable values to be? Step through the code and see if you
were right. If you were wrong, and you're not sure why, see the Task 7, Test 2.
• Try navigating back and forth between the pages using the buttons with the "Retain AM"
label. Your cached DebugALabAM and its state remains intact.
Tip: In this test, both pages are using the same application module instance. Another way to
verify whether pages are using the same instance of the same application module type is to
check the object's memory address (it's internal unique identifier). To do this, double-click the
"this" Name or Type value in the Data window (shown in Figure 13 above). This opens a Modify
Value window with the Current Value set to the objec'ts memory address.
Figure 14: DebugLabAMImpl Object's Memory Address

18
Task 8: Resolve a Common Missing Import
This task doesn't involve the use of the debugger, but it walks you through a common mistake
that can be difficult to understand if you've not seen anything like this before.
• Open
oracle.apps.fnd.framework.toolbox.labsolutions.server.DebugLabEmpFullVOImpl
and comment out the oracle.jbo.domain.Number import.
• Rebuild the LabSolutions project; notice that you get the following compilation error:
Error(34,28): class java.lang.Number is abstract; cannot be
instantiated
Whenever you use a Number in an OA Framework application, you must remember to import
oracle.jbo.domain.Number. If you fail to do this, the compiler assumes that this is a
java.lang.Number class (the java.lang classes are automatically included, which is why
you don't have to explicitly import commonly used classes like String).
In this particular code example, we are attempting to instantiate a Number class so we're getting
the error shown above. Alternatively, you might define a Number member variable without
explicitly instantiating it, and you'll get a runtime error when you try to set the value. Just try to
remember to always import oracle.jbo.domain.Number when you need it, and if you
experience problems related to Numbers in your code, always remember to check your imports
before spending a lot of additional time debugging this.

19
Task 9: Investigate Unexpected UI Results
Sometimes, debugging won't help you solve a problem because nothing's actually wrong with
the code. The downside of working with a "black box" that does a lot of the work for you --
particularly when you "code" declaratively -- is sometimes the smallest oversight on your part
leads to an unexpected result.
For example, you might have noticed that a header line is rendering above the Employee
Number field in the debug lab Create page (see Figure 15). While something like this might be
a bug, it's more likely to be caused by an incorrect property setting. Although a bit tedious, the
only thing you can really do in this case is carefully inspect all the property settings for the
regions and/or items related to the undesirable HTML. If you're uncertain about how various
property settings affect the corresponding HTML, see the JDeveloper OA Component Properties
documentation for a description of each property by region and item type. Also see the various
UI implementation topics in Chapter 4 of the OA Framework Developer's Guide.
Do you know why this line is rendering? Do you know how to stop it? See the Task 9 solution if
you need help.
Figure 15: Unwanted Header Line Above the Employee Number Field

Congratulations! You are now finished with this lab.

20

You might also like