Oracle JDeveloper Tip
When your J2EE application isn't working as you thought it should, JDeveloper's excellent debugger is your friend. This quick article will help you understand some of its features that I find I use most often.
Firstly, even before starting to use the actual debugger, running with the framework diagnostics logging turned on can be helpful to see what it's doing when the problem occurs. To turn on diagnostic logging set the Java System property named
jbo.debugoutput
to the value
console
. Legal values for this flag are
silent
,
console
, and
file
in JDeveloper 10.1.2. In JDeveloper 10.1.3, a new value called
ADFLogger
is also supported which routes diagnostics through the standard J2SE Logger implementation which can be controlled in a standard way through the OC4J
j2ee-logging.xml
file.
The easiest way to set this system property while running your application inside JDeveloper 10g is to edit your project properties and:
Then add the string
-Djbo.debugoutput=console
to the
Java Options
field.
Often you will find it useful to debug the ADF Business Components in your application without having to start up the visual user interface of your ADF application. You are likely already aware that you can select any application module in the Application Navigator , and choose Test... from its right-mouse context menu to launch the Business Components Tester tool. What you might not know is that you can also launch the Tester tool in the debugger. This can be extremely useful and can make debugging ADF Business Components applications even easier than when having to startup the complete front-end GUI of your application.
To launch an ADF Application Module in the tester in debug mode, do the following:
In the Structure Window , notice the Sources folder, and select the Java implementation class for your application module.
If you application module is called
MyModule
, this class will be named
MyModuleImpl.java
Debug...
from the context menu on that application module implementation class to launch the debugger.
You'll notice that the
main()
method of your application module Java class looks like this:
public static void main(String[] args) {
launchTester("com.yourcompany.yourapp.model", /* package name */
"MyModuleLocal"); /* Configuration Name */
}
If you need to launch the application module in the debugger using a different configuration than the one indicated (e.g.
MyModuleLocal
in the code sample above), just change the string that gets passed as the second argument to
launchTester()
to be the name of the configuration you want to use instead.
You first need to understand the different kinds of breakpoints we support and where to create them.
To see the Debugger Breakpoints window, use the View | Debugger > Breakpoints menu choice from the main JDeveloper menu, or optionally the key accelerator for this: Ctrl+ Shift+ R.
You can create a new breakpoint by selecting the New Breakpoint... menu choice from the right-mouse menu anywhere in the breakpoints window. The Breakpoint Type dropdown list controls what kind of breakpoint you will create. The valid choices are:
Exception — break whenever an exception of this class (or a subclass) is thrown.
This is great when you don't know where the exception occurs, but you know what kind of exception it is (e.g.
java.lang.NullPointerException
,
java.lang.ArrayIndexOutOfBoundsException
,
oracle.jbo.JboException
, etc.) The checkbox options allow you to control whether to break on caught or uncaught exceptions of this class. The (Browse...) button helps you find the fully-qualified class name of the exception. The Exception Class combo-box remembers most recently used exception breakpoint classes. Note that this is the default breakpoint type when you create a breakpoint in the breakpoints window.
Source — break whenever a particular source line in a particular class in a particular package is run.
You rarely create a source breakpoint in the New Breakpoint window. This is because it's much easier to create it by first using the Navigate | Go to Class... menu (accelerator Ctrl+ Shift+ Minus), then scrolling to the line number you want -- or using Navigate | Go to Line... (accelerator Ctrl+ G) -- and finally clicking in the breakpoint margin at the left of the line you want to break on. This is equivalent to creating a new source breakpoint, but it means you don't have to type in the package, class, and line number by hand.
Method — break whenever a method in a given class is invoked.
This is handy to set breakpoints on a particular method you might have seen in the call stack while debugging a problem. Of course, if you have the source you can set a source breakpoint wherever you want in that class, but this kind of breakpoint lets you stop in the debugger even when you don't have source for a class.
Class — break whenever any method in a given class is invoked.
This can be handy when you might only know the class involved in the problem, but not the exact method you want to stop on. Again, this kind of breakpoint does not require source. The (Browse...) button helps you quickly find the fully-qualified class name you want to break on.
Watchpoint — break whenever a given field is accessed or modified (new in 10.1.3)
This can be super helpful to find a problem if the code inside a class modifies a member field directly from several different places (instead of going through setter or getter methods each time). You can stop the debugger in its tracks when any field is modified. You can create a breakpoint of this type by using the Toggle Watchpoint menu item on the right-mouse menu when pointing at a member field in your class' source.
After creating a breakpoint you and edit the breakpoint in the breakpoints window using the Edit... choice in the context menu on the desired breakpoint.
Some really interesting features you can do by editing your breakpoint are:
Associate a conditional expression with the breakpoint so that it the debugger only stops when that condition is met. In 10.1.3, the expressions can be virtually any boolean expression, including:
expr ==
value
expr.equals("
value")
expr instanceof
fully.qualified.ClassName
which are the three I use most frequently.
NOTE:One tip is to use the debugger watch window to evaluate the expression first to make sure its valid. |
An excellent but often overlooked feature of the JDeveloper debugger is the ability to filter the members you want to see in the debugger window for any class. In the debugger's Data window, pointing at any item and selecting Object Preferences... from the right-mouse context menu brings up a dialog where you can customize which members appear in the debugger and (more importantly sometimes) which members don't appear. These preferences are set by class type and can really simplify the amount of scrolling you need to do in the debugger data window when you might only really care about a handful of a class' members while debugging.
Interesting breakpoints in set it ADF framework code when you're trying to debug a problem are:
Exception breakpoint for
oracle.jbo.JboException
When you're not sure where to start, this is the base class of all ADF Business Components runtime exceptions.
Exception breakpoint for
oracle.jbo.DMLException
This is the base class for exceptions originating from the database, like a failed DML operation due to an exception raised by a trigger or by a constraint violation.
Source breakpoint in the
doIt()
method of
JUCtrlActionBinding
class (
oracle.jbo.uicli.binding
package).
This is the method that will execute when any ADF action binding is invoked, and you can step into the logic and look at parameters if relevant.
Source breakpoint in the
handleLifecycle()
method of the
DataAction
class (
oracle.adf.controller.struts.actions
package).
This is the method that controls the processing of the ADF/Struts request handling lifecycle.
Method breakpoint in the
oracle.jbo.server.ViewObjectImpl.executeQueryForCollection
method.
This is the method that will be called when a view object executes its SQL query.
Method breakpoint in the
oracle.jbo.server.ViewRowImpl.setAttributeInternal
method.
This is the method that will be called when any view row attribute is set.
Method breakpoint in the
oracle.jbo.server.EntityImpl.setAttributeInternal
method.
This is the method that will be called when any entity object attribute is set.
By looking at the stack window when you hit these breakpoints, and stepping through the source you can get a better idea of what's going on.
If you are unable to use the tips in this article to determine what the problem is and resolve it yourself, typically your next step is to ask someone else for assistance. Whether you post a question in the OTN JDeveloper Discussion Forum or open a Service Request on Metalink, including the stack trace information in your posting is extremely useful to anyone who will need to assist you further to understand exactly where the problem is occurring.
JDeveloper 10g's Stack window makes communicating this information easy. Whenever the debugger is paused, you can view the Stack window to see the program flow as a stack of method calls that got you to the current line. Using the right-mouse Preferences... menu on the Stack window background, you can set the Stack window preference to include the Line number information as well as the class and method name that will be there by default. Finally, the other handy context menu option Export... lets you save the current stack information to an external text file whose contents you can then post or send to whomever might need to help you diagnose the problem.