Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3.0) Part Number B28967-02 |
|
|
View PDF |
This chapter describes the process of debugging your user interface project. It also supplies information about methods of the Oracle ADF Model API, which you can use to set breakpoints for debugging.
This chapter includes the following sections:
Section 16.1, "Getting Started with Oracle ADF Model Debugging"
Section 16.2, "Correcting Simple Oracle ADF Compilation Errors"
Section 16.4, "Understanding a Typical Oracle ADF Model Debugging Session"
Like any debugging task, debugging the web application's interaction with Oracle ADF is a process of isolating specific contributing factors. However, in the case of web applications, generally, this process does not involve compiling Java source code. Your web pages contain no Java source code, as such, to compile. In fact, you may not realize that a problem exists until you run and attempt to use the application. For example, these failures are only visible at runtime:
Page not found servlet error
Page is found but the components display without data
Page fails to display data after executing a method call or built-in operation (like Next or Previous)
Page displays but a method call or built-in operation fails to execute at all
Page displays but unexpected validation errors occur
The failure to display data or to execute a method call arises from the interaction between the web page's components and the Oracle ADF Model layer. When a runtime failure is observed during ADF lifecycle processing, the sequence of preparing the model, updating the values, invoking the actions, and, finally, rendering the data failed to complete.
Fortunately, most failures in the web application's interaction with Oracle ADF result from simple and easy-to-fix errors in the declarative information that the application defines or in the EL expressions that access the runtime objects of the page's Oracle ADF binding container.
Therefore, in your Oracle ADF databound application, you should examine the declarative information and EL expressions as likely contributing factors when runtime failures are observed. Read the following sections to understand editing the declarative files:
The most useful diagnostic tool (short of starting a full debugging session) that you can use when running your application is the ADF Logger. You use this J2EE logging mechanism in JDeveloper to capture runtime traces messages from the Oracle ADF Model layer API. With ADF logging enabled, JDeveloper displays the application trace in the Message Log window. The trace includes runtime messages that may help you to quickly identify the origin of an application error. Read Section 16.4, "Understanding a Typical Oracle ADF Model Debugging Session" to configure the ADF Logger to display detailed trace messages.
If the error cannot be easily identified, you can utilize the debugging tools in JDeveloper to step through the execution of the application and the various phases of the Oracle ADF page lifecycle. This process will help you to isolate exactly where the error occurred. By using the debugging tools, you will be able to pause execution of the application on specific methods in the Oracle ADF API, examine the data that the Oracle ADF binding container has to work with, and compare it to what you expect the data to be. Read Section 16.5, "Debugging the Oracle ADF Model Layer" to understand debugging the Oracle ADF Model layer.
Occasionally, you may need help debugging EL expressions. While EL is not well-supported with a large number of useful exceptions, you can enable JSF trace messages to examine variable resolution. Read Section 16.6, "Tracing EL Expressions" to work with JSF trace messages.
When you create web pages and work with the ADF data controls to create the ADF binding definitions in JDeveloper, the Oracle ADF declarative files you edit must conform to the XML schema defined by Oracle ADF. When an XML syntax error occurs, the JDeveloper XML compiler immediately displays the error in the Structure window. Choose Structure from the JDeveloper View menu to open the Structure window for any Oracle ADF file you edit in the XML editor.
Currently a limitation of the JDeveloper compiler is the ability to resolve EL expressions. EL expressions in your web pages interact directly with various runtime objects in the web environment, including the web page's Oracle ADF binding container. At present, errors in EL expressions can be observed only at runtime. Thus, the presence of a single typing error in an object-access expression will not be detected by the compiler, but will manifest at runtime as a failure to interact with the binding container and a failure to display data in the page. For information about debugging runtime errors, see Section 16.3, "Correcting Simple Oracle ADF Runtime Errors".
Tip:
The JDeveloper Expression Builder is a dialog that helps you build EL expressions by providing lists of objects, managed beans, and properties. It is particularly useful when creating or editing ADF databound EL expressions because it provides a hierarchical list of ADF binding objects and their valid properties from which you can select the ones you want to use in an expression. Oracle recommends using the Expression Builder to avoid introducing typing errors. For details, see Section 5.6.2, "How to Use the Expression Builder".Example 16-1 illustrates simple compilation errors contained in the page definition file: "fase
" instead of "false
" and "IsQueriable="false"/
" instead of "IsQueriable="false"/>
" (missing a closing angle bracket).
Example 16-1 Sample Page Definition File with Two Errors
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.35.62" id="browseusersPageDef" Package="oracle.srdemo.view.pageDefs" EnableTokenValidation="fase" ...> <parameters/> <executables> <variableIterator id="variables"> <variable Type="java.lang.String" Name="findUsersByName_name" IsQueriable="false"/
The Structure window for the above errors would display as shown in Figure 16-1.
If you were to attempt to compile the application, the Compiler window would also display similar errors, as shown in Figure 16-2.
To correct schema validation errors, in either the Structure window or the Compiler window, double-click the error to open the file. The file will open in the XML editor with the responsible line highlighted for you to fix.
After you correct the error, the Structure window will immediately remove the error from the window. Optionally, you may recompile the project using the make operation to recompile the changed file and view the empty Compiler window.
Failures of the Oracle ADF Model layer cannot be detected by the JDeveloper compiler, in part, because the page's data-display and method-execution behavior relies on the declarative Oracle ADF page definition files. The Oracle ADF Model layer utilizes those declarative files at runtime to create the objects of the Oracle ADF binding container.
To go beyond simple schema validation, you will want to routinely run and test your web pages to ensure that one of the following conditions does not exist:
The project dependency between the data model project and the user interface project becomes disabled.
By default, the dependency between projects is enabled whenever you create a web page that accesses a data control in the data model project. However, if the dependency is disabled and remains disabled when you attempt to run the application, an internal servlet error will be generated at runtime:
oracle.jbo.NoDefException: JBO-25002: Definition model.DataControls.dcx of type null not found
To correct the error, right-click the user interface project, choose Project Properties, and select Dependencies in the dialog. Make sure that the <ModelProjectName>.jpr option appears selected in the panel.
The DataBindings.cpx
file location changed but the web.xml
file still references the original path for the file.
By default, JDeveloper adds the DataBindings.cpx
file to the package for your user interface project. If a change to the location of the file is made (for example, due to refactoring the application), an internal servlet error will be generated at runtime:
oracle.jbo.NoXMLFileException: JBO-26001: XML File not found for the Container /oracle/<path>/DataBinding.cpx
To correct the error, open the web.xml
file and edit the path that appears in the <context-param>
element CpxFileName
.
Page definition files have been renamed but the DataBindings.cpx
file still references the original page definition filenames.
While JDeveloper does not permit these files to be renamed within the IDE, if a page definition file is renamed outside of JDeveloper and the references in the DataBindings.cpx
file are not also updated, an internal servlet error will be generated at runtime:
oracle.jbo.NoDefException: JBO-25002: Definition oracle.<path>.pageDefs.<pagedefinitionName> of type Form Binding Definition not found
To correct the error, open the DataBindings.cpx
file and edit the page definition filenames that appear in the <pageMap>
and <pageDefinitionUsages>
elements.
The web page file (.jsp
or.jspx
) has been renamed but the DataBindings.cpx
file still references the original filename of the same web page.
The page controller uses the page's URL to determine the correct page definition to use to create the ADF binding container for the web page. If the page's name from the URL does not match the <pageMap>
element of the DataBindings.cpx
file, an internal servlet error will be generated at runtime:
javax.faces.el.PropertyNotFoundException: Error testing property <propertyname>
To correct the error, open the DataBindings.cpx
file and edit the web page filenames that appear in the <pageMap>
element.
Bindings have been renamed in the web page EL expressions but the page definition file still references the original binding object names.
The web page may fail to display information that you expect to see. To correct the error, compare the binding names in the page definition file and the EL expression responsible for displaying the missing part of the page. Most likely the mismatch will occur on a value binding, with the consequence that the component will appear but without data. Should the mismatch occur on an iterator binding name, the error may be more subtle and may require deep debugging to isolate the source of the mismatch.
Bindings in the page definition file have been renamed or deleted and the EL expressions still reference the original binding object names.
Because the default error-handling mechanism will catch some runtime errors from the ADF binding container, this type of error can be very easy to find. For example, if an iterator binding (named findUsersByNameIter
) was renamed in the page definition file, yet the page still refers to the original name, this error will display in the web page:
JBO-25005: Object name findUsersByNameIter for type Iterator Binding Definition is invalid
To correct the error, right-click the name in the web page and choose Go to Page Definition to locate the correct binding name to use in the EL expression.
EL expressions were written manually instead of using the Expression Picker dialog and invalid object names or property names were introduced.
This error may not be easy to find. Depending on which EL expression contains the error, you may or may not see a servlet error message. For example, if the error occurs in a binding property with no runtime consequence, such as displaying a label name, the page will function normally but the label will not be displayed. However, if the error occurs in a binding that executes a method, an internal servlet error javax.faces.el.MethodNotFoundException:
<methodname>
will display. Or, in the case of an incorrectly typed property name on the method expression, the servlet error javax.faces.el.PropertyNotFoundException:
<propertyname>
will display. For information about displaying JSF trace messages to help debug these exception, see Section 16.6, "Tracing EL Expressions".
If the above list of typical errors does not help you to find and fix a runtime error, you can initiate debugging within JDeveloper in order to isolate the contributing factor. This process involves pausing the execution of the application as it proceeds through the phases of the Oracle ADF page lifecycle, examining the data received by the lifecycle, and determining whether that data is expected or not. To inspect the data of your application, you will work with source code breakpoints and Data window, as described in Section 16.4, "Understanding a Typical Oracle ADF Model Debugging Session".
If you are not able to easily find the error in your web page or its corresponding page definition file, you can use the JDeveloper debugging tools to investigate where your application failure occurs. Specifically, the goal for debugging the interaction between the web page and the Oracle ADF Model layer is to pause the application by setting breakpoints on the execution of the Oracle ADF page lifecycle and to examine the data loaded at runtime. When the objects of the Oracle ADF Model layer do not contain the data that you expect to see, this observation will help you to identify the probable contributing factor.
Generally, the process for debugging proceeds like this:
Run the application and look for missing or incomplete data, actions and methods that are ignored or incorrectly executed, or other unexpected results.
Create a debugging configuration that will enable the ADF Log and send Oracle ADF Model messages to the JDeveloper Log window. For more information, see Section 16.4.2, "Creating an Oracle ADF Debugging Configuration".
Choose Go to Java Class from the Navigate menu (or press Ctrl + -) and use the dialog to locate the Oracle ADF class that represents the entry point for the processing failure.
Tip:
JDeveloper will locate the class from the user interface project that has the current focus in the Application Navigator. If your workspace contains more than one user interface project, be sure the one with the current focus is the one that you want to debug.Open the class file in the Java editor and find the Oracle ADF method call that will enable you to step into the statements of the method.
Set a breakpoint on the desired method and run the debugger.
When the application stops on the breakpoint, use the Data window to examine the local variables and arguments of the current context.
Once you have set breakpoints to pause the application at key points, you can proceed to view data in the JDeveloper Data window. To effectively debug your web page's interaction with the Oracle ADF Model layer, you need to understand:
The Oracle ADF page lifecycle and the method calls that get invoked
The local variables and arguments that the Oracle ADF Model layer should contain during the course of application processing
Awareness of Oracle ADF processing, as described in Section 16.5, "Debugging the Oracle ADF Model Layer", will give you the means to selectively set breakpoints, examine the data loaded by the application, and isolate the contributing factors.
Note:
JSF web pages may also use backing beans to manage the interaction between the page's components and the data. Debug backing beans by setting breakpoints as you would any other Java class file.Even before you use the actual debugger, running with framework diagnostics logging turned on can be helpful to see what happened when the problem occurs. To turn on diagnostic logging set the Java System property named jbo.debugoutput
to the value console
. Additionally, the value ADFLogger
lets you route 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 is to edit your project properties and in the Run/Debug panel, select a run configuration and click Edit to edit it. Then add the string -Djbo.debugoutput=console
to the Java Options field.
ADF Faces leverages the Java Logging API (java.util.logging.Logger
) to provide logging functionality when you run a debugging session. Java Logging is a standard API that is available in the Java Platform, starting with JDK 1.4. For the key elements, see the section "Java Logging Overview" at http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/overview.html
.
Because standard Java Logging is used, you can edit the j2ee-logging.xml
file to control the level of diagnostics you receive in the Log window:
When you conduct a debugging session within JDeveloper, you will use JDeveloper embedded-OC4J and will want to modify the file in your JDeveloper install here:
<JDev_Install>
/jdev/system/oracle.j2ee.10.1.3.xx.xx/embedded-oc4j/config
Similarly, when you want to conduct a remote debugging session on Oracle Application Server, you can modify the file here:
<OAS_Home>
/j2ee/<OC4J_INSTANCE>/config
Or, when you want to conduct a remote debugging session on standalone OC4J, you can modify the file here:
<OC4J_Home>
/j2ee/home/config
To edit ADF package-level logging in the j2ee-logging.xml file:
If you want to change the logging level for Oracle ADF, you can edit the <logger>
elements of the configuration file.
Note:
By default the level is set toINFO
for all packages of Oracle ADF. However, Oracle recommends level="FINE"
for detailed logging diagnostics.For the packages oracle.adf.view.faces
and oracle.adfinternal.view.faces
, edit:
<logger name="oracle.adf" level="INFO"/><logger name="oracle.adfinternal" level="INFO"/>
For the Oracle ADF Model layer packages, edit these elements:
<logger name="oracle.adf" level="INFO"/><logger name="oracle.jbo" level="INFO"/>
Alternatively, you can create a debug configuration in JDeveloper that you can choose when you start a debugging session.
To create an Oracle ADF Model debugging configuration:
In the Application Navigator, double-click the user interface project.
In the Project Properties dialog, click Run/Debug and create a new run configuration, for example, named ADF debugging.
Double-click the new run configuration to edit the properties.
In the Edit Run Configuration dialog, for Launch Settings, enter the following Java Options for the default ojvm virtual machine:
-Djbo.debugoutput=adflogger -Djbo.adflogger.level=FINE
Oracle recommends the level=FINE
for detailed diagnostic messages.
You first need to understand the different kinds of breakpoints 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 combobox 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.
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 can edit the breakpoint in the breakpoints window by selecting Edit in the context menu on the desired breakpoint.
Some really interesting features you can use by editing your breakpoint are:
Associate a logical "breakpoint group" name to group this breakpoint with others having the same breakpoint group name. Breakpoint groups make it easy to enable/disable an entire set of breakpoints in one operation.
Associate a debugger action to occur when the breakpoint is hit. The default action is to just stop the debugger so you can inspect things, but you can add a beep, write something to a log file, and enable or disable group of breakpoints.
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
Note:
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 that lets you 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. This is especially useful while debugging when you might only be interested in a handful of a class' members.
If you are unable 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'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 useful 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.
The processing of your JSF page in combination with Oracle ADF Model is controlled by two classes:
oracle.adf.controller.faces.lifecycle.FacesPageLifecycle
class
oracle.adf.controller.v2.lifecycle.PageLifecycleImpl
class
FacesPageLifecycle
implements certain methods of PageLifecycleImpl
to provide customized error-handling behavior for ADF Faces applications. Generally, however, you will set breakpoints on PageLifecycleImpl
, as this class provides the starting point for creating the objects of the Oracle ADF binding context.
Tip:
TheFacesPageLifecycle
class provides the default implementation of the phase of the ADF Lifecycle. A good place to set a breakpoint is on the prepareModel()
method, as it initiates the first phase of the ADF lifecycle. For details about the Oracle ADF lifecycle, see Section 6.2.3, "What Happens at Runtime: The JSF and ADF Lifecycles".The successful interaction between the web page and these objects of the Oracle ADF binding context ensures that the page's components display with correct and complete data, that methods and actions produce the desired result, and that the page renders properly with the appropriate validation errors.
At runtime, several things must happen before the ADF lifecycle can prepare the model and display the web page. When the first request for an ADF databound web page occurs, the servlet registers the Oracle ADF servlet filter ADFBindingFilter
, named in the web.xml
file. The method ADFBindingFilter.doFilter()
sets up the ADF processing state, and the method ADFBindingFilter.initializeBindingContext()
creates an instance of oracle.adf.model.BindingContext
by reading the CpxFileName
init parameter from the web.xml
file.
Immediately after ADFBindingFilter.initializeBindingContext()
is called, BindingContext
is an empty container object that will define a hierarchy of the Oracle ADF Model layer objects. However, as the container object, BindingContext
must exist in order for the page's binding to be created. If it does not, an internal servlet error for the Container /oracle/
<path>
/DataBinding.cpx
will be thrown:
oracle.jbo.NoXMLFileException: JBO-26001: XML File not found
To debug creating the binding context for the web application:
In the oracle.adf.model.servlet.ADFBindingFilter
class, set a break on chain.doFilter()
and step into this method.
Set another break on ctx.get(BindingContext.IS_INITIALIZED)
and step into this method.
In the oracle.jbo.uicli.mom.JUMetaObjectManager
class, set a break on chain.getClientProjectExtension()
and step into this method.
When processing pauses, look in slot0 for a file with the expected package name in the Data window.
If the DataBindings.cpx
file is not found, then check that the servlet context parameter element correctly defines the fully qualified name for the .cpx
file and verify that the file exists in your project in the location specified by the qualified name path. Example 16-2 shows the context parameter for the SRDemo application.
Tip:
The name specified in theparam-value
element of the context parameter must be the fully qualified name of the .cpx
file.After BindingContext
is created by ADFBindingFilter
, the method PageLifeCycle.xXX()
passes the request's web page URL to the method BindingContext.findBindingContainer()
to find a page definition from the <pageMap>
element in the DataBindings.cpx
file that matches the web page. This becomes the BindingContainer
. This BindingContainer
object is the runtime instance object with all bindings created on it. If page definition file is not found, an internal servlet error will be thrown:
oracle.jbo.NoDefException: JBO-25002: Definition oracle.
<path>
.pageDefs.
<pagedefinitionName>
of type Form Binding Definition not found
To debug creating the binding container for the web page:
In the oracle.adf.model.BindingContext
class, set a break on findBindingContainerIdByPath()
and step into this method.
Look for the name of the databound web page associated with the binding container in the Data window.
In the Smart Data window, look for a matching entry for the expected databound web page file name.
In the Data window, there should be a matching page definition entry for the databound web page.
If the <pagename>
PageDef.xml
file is not found, then check that the <pageMap>
element in the DataBindings.cpx
file specifies the correct name and path to the web page in your project. Example 16-3 shows a sample DataBindings.cpx
file for the SRDemo application. Notice that the <pageMap>
element maps the JSF page to its page definition file
CAUTION:
If you change the name of a JSF page or a page definition file, the.cpx
file is not automatically refactored. You must manually update the page mapping in the .cpx
to reflect the new page name.Example 16-3 Sample Databinding.cpx Page Definitions
<?xml version="1.0" encoding="UTF-8" ?> <Application xmlns="http://xmlns.oracle.com/adfm/application" version="10.1.3.34.12" id="DataBindings" SeparateXMLFiles="false" Package="oracle.srdemo.view" ClientType="Generic"> <pageMap> <page path="/app/SRList.jspx" usageId="app_SRListPageDef"/> ...> </pageMap> <pageDefinitionUsages> <page id="SRListPageDef" path="oracle.srdemo.view.pageDefs. app_SRListPageDef"/> ... </pageDefinitionUsages> <dataControlUsages> <dc id="SRDemoFAQ" path="oracle.srdemo.faq.SRDemoFAQ"/> <dc id="SRAdminFacade" path="oracle.srdemo.model.SRAdminFacade"/> <dc id="SRPublicFacade" path="oracle.srdemo.model.SRPublicFacade"/> </dataControlUsages> </Application>
After BindingContainer
is created by BindingContext
, the ADF lifecycle initiates the Prepare Model and the Render Model phases before data can be displayed in the web page. Several things must happen before the bindings are resolved and data can appear in the web page:
Page parameters must be set.
Iterator and Method executables must be get refreshed by executing named service methods and ADF iterator bindings.
The ADF lifecycle enters the Prepare Model phase by calling BindingContainer.refresh(PREPARE_MODEL)
. During the Prepare Model phase, BindingContainer
page parameters get prepared and then evaluated. Next, BindingContainer
executables get refreshed based on the order of entry in the pagedef.xml
file's <executables>
section and on the evaluation of their Refresh
and RefreshCondition
properties (if present). When an executable leads to an iterator binding refresh, the corresponding data control will be executed, and that leads to execution of one or more collections in the service objects. If an iterator binding fails to refresh, a JBO exception will be thrown and the data will not be available to display.
To debug all executables for the binding container:
In the oracle.adf.model.binding.DCBindingContainer
class, set a break on internalRefreshControl(int, boolean)
as the entry point to debug the executables.
Tip: In the DCBindingContainer.internalRefreshControl()
method, you can determine whether the executable will be refreshed by checking the outcome of the condition if (/*execute ||*/ execDef == null || execDef.isRefreshable(this, iterObj, refreshFlag))
. If the condition evaluates to true, then the executable is refreshed and processing will continue to initSourceRSI()
.
In the oracle.adf.model.binding.DCIteratorBinding
class, set a break on callInitSourceRSI()
to halt processing and step into the method.
When processing pauses, look for callInitSourceRSI()
in the Stack window. The result displayed in the Smart Data window should show the result that you expect.
When your web page fails to display data from a method iterator binding, you can drill down to the entry point in JUMethodIteratorDef.java
and its nested class JUMethodIteratorBinding
to debug its execution.
To debug the method iterator executable for the binding container:
In the oracle.jbo.uicli.binding.JUMethodIteratorDef
class, set a break on initSourceRSI()
as the entry point to debug a method iterator binding executable.
Set a break on invokeMethodAction()
to halt processing and step into the method.
When initSourceRSI()
returns a rowset iterator, pause processing and look for mProvider in the Smart Data window. The mProvider variable is the datasource fetched for this rowset iterator. If the method returned successfully, it should show a collection bound to an iterator or a bean.
When your web page fails to display the detail data from an accessor binding, you can drill down to the entry point in JUAccessorIteratorDef.java
to debug its execution.
To debug only the accessor binding executable for the binding container:
In the oracle.jbo.uicli.binding.JUAccessorIteratorDef
class, set a break in initSourceRSI()
as the entry point to debug an accessor executable.
In the oracle.adf.model.generic.DCGenericDataControl
class, set a break in fetchProperty(RowImpl row, String propName)
to halt processing before looking into the Data window. Check if the method returns any property that is a collection, iterator, or a bean.
When initSourceRSI()
returns a rowset iterator, pause processing and look for callInitSourceRSI()
in the Smart Data window. The result should show the collection that you expect.
Tip:
If the debugger does not reach a breakpoint that you set on an executable in the binding container, then the error is most likely a result of the way the executable'sRefresh
and RefreshCondition
attribute was defined. Examine the attribute definition. For details about the Refresh
and RefreshCondition
attribute values, see Section A.7.1, "PageDef.xml Syntax".When the executable that produced the exception is identified, check that the <executables>
element in the pagedef.xml
file specifies the correct attribute settings.
Whether the executable is refreshed during the Prepare Model phase, depends on the value of Refresh
and RefreshCondition
(if they exist). If Refresh
is set to prepareModel
, or if no value is supplied (meaning it uses the default, ifneeded
), then the RefreshCondition
attribute value is evaluated. If no RefreshCondition
value exists, the executable is invoked. If a value for RefreshCondition
exists, then that value is evaluated, and if the return value of the evaluation is true
, then the executable is invoked. If the value evaluates to false
, the executable is not invoked. The default value always enforces execution.
Example 16-4 shows a sample pagedef.xml
file from the SRDemo application. Notice that the <executables>
element lists the executables in the order in which they should be executed, with the accessor iterator positioned after its master binding iterator.
Example 16-4 Sample Page Definition Master and Detail Executables
<executables> <methodIterator id="findAllServiceRequestIter" Binds="findAllServiceRequest.result" DataControl="SRPublicFacade" RangeSize="10" BeanClass="oracle.srdemo.model.ServiceRequest"/> <accessorIterator id="serviceHistoryCollectionIterator" RangeSize="10" Binds="serviceHistoryCollection" DataControl="SRPublicFacade" BeanClass="oracle.srdemo.model.ServiceHistory" MasterBinding="findAllServiceRequestIter"/> </executables>
During the prepareRender phase of the ADF lifecycle, the bindings determine the data to display, and properties on the bindings determine the conditions in which to display the data. When the web page is rendered the first time, each EL expression that points to a binding gets resolved by the BindingContainer
instance for that page. Based on the expression appropriate values like format
, isEnabled
, and isViewable
, the data value for a binding is returned from BindingContainer
. If the binding is unable to return the data, a JBO exception is thrown.
To debug the binding resolution for the binding container:
In the oracle.jbo.uicli.binding.JUCtrlValueBinding
class, set a break in getInputValue()
and step into the method.
If getInputValue()
returns an error, pause processing and look for the binding name in the Data window.
Continue stepping into getInputValue()
, and look for a return value in the Data window that you expect for the current row that this binding represents.
When the binding that produced the exception is identified, check that the <bindings>
element in the pagedef.xml
file specifies the correct attribute settings. Example 16-5 shows a sample pagedef.xml
file for the SRDemo application.
Example 16-5 Sample Page Definition Value Bindings
<bindings> ... <attributeValues id="name" IterBinding="variables"> <AttrNames> <Item Value="findUsersByName_name"/> </AttrNames> </attributeValues> <attributeValues id="email" IterBinding="findUsersByNameIter"> <AttrNames> <Item Value="email"/> </AttrNames> </attributeValues> <attributeValues id="lastName" IterBinding="findUsersByNameIter"> <AttrNames> <Item Value="lastName"/> </AttrNames> </attributeValues> <table id="UserexpertiseAreas" IterBinding="expertiseAreasIterator"> <AttrNames> <Item Value="expertiseLevel"/> <Item Value="product"/> </AttrNames> </table> </bindings>
In case of submit, again, the lifecycle first looks up and prepares the BindingContainer
instance. If the lifecycle finds a state token that was persisted for this BindingContainer
, it asks the BindingContainer
to process this state token. Processing the state token restores the variable values that were saved out in previous the render. If you need to debug processing the state token, break in DCIteratorBinding.processFormToken()
and DCIteratorBinding.buildFormToken()
.
After this, all posts are applied to the bindings through setInputValue()
on the value bindings.
When the executables are refreshed, actions and custom methods may be invoked on the page. At this stage, the corresponding action or method binding is refreshed. If an executable or its target binding is not executed, the action will be ignored.
The entry point for action and method execution is the DCDataControl.invokeOperation()
method. Although JUCtrlActionBinding.invoke()
is another potential entry point, method iterator bindings also use it to invoke methods implicitly. Instead, debugging on DCDataControl.invokeOperation()
allows you to work with the same method that the data control uses to invoke the method. This is preferred because some adapter data controls can interpret the method name in a custom way rather than leave it to ADF to call the method.
To debug the action or method invocation for the binding container:
In the oracle.adf.model.binding.DCDataControl
class, set a break on invokeOperation()
as the entry point to debug an action or method invocation.
When processing pauses, step though the method to verify instanceName in the Data window shows the method being invoked is the intended method on the desired object.
Verify args in the Data window shows the parameter value for each parameter being passed into your method is as expected. The parameter value below shows null.
To debug a custom method invocation for the binding container:
In your class, set a breakpoint on the desired custom method.
In oracle.adf.model.generic.DCGenericDataControl
class, set a break on invokeMethod()
to halt processing before looking into the Data window.
When processing pauses, step though the method to verify instanceName in the Data window shows the method being invoked is the intended method on the desired object.
Verify args in the Data window shows the parameter value for each parameter being passed into your method is as expected. The parameter value below shows null.
When the ignored action or custom method is identified, check that the <invokeAction>
definitions in <executables>
element and their corresponding <action>
and <methodAction>
definitions in the <bindings>
element of the pagedef.xml
file specifies the correct attribute settings.
Tip:
If the debugger does not reach a breakpoint that you set on an action in the binding container, then the error is most likely a result of the way the executable'sRefresh
and RefreshCondition
attribute was defined. Examine the attribute definition. For details about the Refresh
and RefreshCondition
attribute values, see Section A.7.1, "PageDef.xml Syntax".Whether the <invokeAction>
executable is refreshed during the Prepare Model phase, depends on the value of Refresh
and RefreshCondition
(if they exist). If Refresh
is set to prepareModel
, or if no value is supplied (meaning it uses the default, ifneeded
), then the RefreshCondition
attribute value is evaluated. If no RefreshCondition
value exists, the executable is invoked. If a value for RefreshCondition
exists, then that value is evaluated, and if the return value of the evaluation is true
, then the executable is invoked. If the value evaluates to false
, the executable is not invoked. The default value always enforces execution.
Example 16-6 shows a sample of the action and custom method binding definition in the pagedef.xml
file for the SRDemo application.
Example 16-6 Sample Page Definition Executables and Action Bindings
<executables> ... <invokeAction Binds="findServiceRequests" id="tableRefresh" Refresh="ifNeeded" RefreshCondition="${(userState.refresh) and (!adfFacesContext.postback)}"/> ... </executables> <bindings> <methodAction id="findServiceRequests" InstanceName="SRPublicFacade.dataProvider" DataControl="SRPublicFacade" MethodName="findServiceRequests" RequiresUpdateModel="true" Action="999" ReturnName="SRPublicFacade.methodResults.SRPublicFacade_ dataProvider_findServiceRequests_result"> <NamedData NDName="userIdParam" NDValue="#{userInfo.userId}" NDType="java.lang.Integer"/> <NamedData NDName="statusParam" NDValue="#{userState.listMode}" NDType="java.lang.String"/> </methodAction> ... </bindings>
The method validate()
on the BindingContainer
gets called, which calls validateInputValue()
on each of the bindings referred to in this BindingContainer
. If the validation set on an input field fails to behave as expected, then no validation error message will be displayed in the web page.
To debug validation-checking failures for the binding container:
In oracle.jbo.uicli.binding.JUCtrlValueBinding
class, set a break in validateInputValue(Object value)
to halt processing before looking into the Data window.
When processing pauses, look for slot1 in the Data window and confirm that the validation is performed. The value not shown below indicates validation was not performed.
When the validation that failed is identified, check that the validation rule for the value binding is correctly defined and that the input field component's <af:validator>
tag is bound to the same attribute defined by the value binding. Example 16-7 shows a sample validation rule in the pagedef.xml
file for the SRDemo application.
Notice that the ADF Model validation rule should appear on the attribute binding. For details about working with validation rules, see Section 12.3, "Adding Validation".
Tip:
To process ADF Model layer validation, the Faces validator tag must be bound to the associated attribute's validator property. For example:<af:validator binding="#{bindings.<someattribute>.validator}"/>
where <someattribute>
would be createProducts_description
to work with the sample validation rule shown in Example 16-7.
Example 16-7 Reference to Validation Rule in Page Definition File
<attributeValues id="description" IterBinding="variables" ApplyValidation="true"> <LengthValidationBean xmlns="http://xmlns.oracle.com/adfm/validation" OnAttribute="createProducts_description" DataType="CHARACTER" CompareType="LESSTHAN" ResId="description_Rule_0" Inverse="false" CompareLength="20"/> <AttrNames> <Item Value="createProducts_description"/> </AttrNames> </attributeValues>
EL is not well supported with exceptions to inform you of specific failures. However, Example 16-8 shows one common exception you are likely to see when the resolver is unable to completely evaluate the expression.
Example 16-8 Expression Evaluation PropertyNotFound Exception
javax.faces.el.PropertyNotFoundException: Error setting property 'resultsTable' in bean of type null at com.sun.faces.el.PropertyResolverImpl.setValue (PropertyResolverImpl.java:153)
You can check your web page's source code for problems in the expression, such as mistyped property names. When no obvious error is found, you will want to configure the logging.properties
file in the <JDeveloper_Install>
/jre/lib
directory to display messages from the EL resolver.
To trace EL expression variables:
Open <JDeveloper_Install>
/jre/lib/logging.properties
in your text editor.
Set java.util.logging.ConsoleHandler.level=FINE
.
Add the line:
com.sun.faces.level=FINE
Run your application and view the variable resolution in the JDeveloper Log window.
For example, the SRDemo application defines a backing bean backing_SRSearch.java
. Example 16-9 shows the SRSearch.jspx
page, which relies on the ADF table binding resultsTable
to create a databound table component.
Example 16-9 Reference to Backing Bean in Table Binding
<af:table rows="#{bindings.findAllServiceRequests1.rangeSize}"
...
binding="#{backing_SRSearch.resultsTable}"
id="resultsTable"
width="100%"
rendered="#{(bindings.hideResultsParam!='true') and
(bindings.findAllServiceRequests1.estimatedRowCount >0)}">
Example 16-10 shows the messages that appear in the JDeveloper Log window when you run the application with EL trace messages enabled. In this case, the resolver is not able to resolve the value binding resultsTable
from the backing bean and the PropertyNotFound
exception will appear in the browser.
Example 16-10 JDeveloper Log with EL Trace Enabled
02-Dec-2005 09:41:28 com.sun.faces.el.ValueBindingImpl getValue FINE: getValue(ref=backing_SRSearch.resultsTable) 02-Dec-2005 09:41:28 com.sun.faces.application.ApplicationAssociate createAndMaybeStoreManagedBeans FINE: Couldn't find a factory for backing_SRSearch 02-Dec-2005 09:41:28 com.sun.faces.el.VariableResolverImpl resolveVariable FINE: resolveVariable: Resolved variable:null 02-Dec-2005 09:41:28 com.sun.faces.el.ValueBindingImpl getValue FINE: getValue Result:null 02-Dec-2005 09:41:28 com.sun.faces.application.ApplicationAssociate createAndMaybeStoreManagedBeans FINE: Couldn't find a factory for backing_SRSearch 02-Dec-2005 09:41:28 com.sun.faces.el.VariableResolverImpl resolveVariable FINE: resolveVariable: Resolved variable:null 02-Dec-2005 09:41:28 com.sun.faces.el.ValueBindingImpl setValue FINE: setValue Evaluation threw exception: javax.faces.el.PropertyNotFoundException
The message FINE: Couldn't find a factory for backing_SRSearch
indicates that the backing bean was never created. To fix the error, check the faces-config.xml
file and make sure that the backing bean is listed. Example 16-11 shows the correct listing for the file.
Example 16-11 faces-config.xml Managed Bean Description
<!-- Page backing beans --> <managed-bean> <managed-bean-name>backing_SRSearch</managed-bean-name> <managed-bean-class>oracle.srdemo.view.backing.SRSearch</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <!--oracle-jdev-comment:managed-bean-jsp-link:1SRSearch.jspx--> </managed-bean>
In summary, when you encounter a PropertyNotFound
exception and the property is one that appears in an EL expression, you may check the syntax of your web page for simple errors. Then, rerun the application with the JSF trace messages enabled and examine the variable resolution messages for clues.