|
Not Yet Documented ADF Sample Applications
As part of helping customers be successful with JDeveloper and ADF
I'm often creating little example applications to illustrate a
point. My goal is to document them and put them together with an
OTN "HowTo" paper to accompany them, but I don't always have the
time to do this. If you try to use one examples in the meantime and can't figure
something out about how to use it, please post a question in the
OTN
JDeveloper discussion forum then drop me an email containing the
link to that forum posting and I'll do my best to help. Additional samples are available on the following ADF-related web sites:
Unless otherwise noted, the examples use the EMP and DEPT tables in the familiar SCOTT schema. If you would like SQL scripts to (re)create and populate the tables in the SCOTT and HR schemas, you can download demoscripts.zip. NOTE for 10.1.3.x Examples: If the example you want to try was built with a JDeveloper 10.1.3.x release different than the one you are using, the only change you need to make to the downloaded workspace is to copy the correct versions of the adf-faces-impl.jar and jsf-impl.jar from the version of JDeveloper 10.1.3.x you are using to the example workspace's ./ViewController/public_html/WEB-INF/lib directory before opening/running the example in your version of 10.1.3.x. These files are located in the JDEVHOME/jlib and JDEVHOME/jsf-ri directories respectively | 144. | Customizing Application Error Handler to Support Informational Messages [11.1.1.0, SCOTT schema] 20-MAR-2009
The base ADF product only distinguishes between warnings and
errors, so there is no default way to get a JSF message with
severity of INFO. This example includes a
CustomErrorHandler class that implements handling for
informational messages. The addInformationMessageTest()
method in the AppModule custom java class adds an
informational message by using the addWarning() API,
passing a custom subtype of JboWarning called
InformationalMessage. Due to the way warnings are
wrapped before they are passed to the custom error handler's
getDisplayMessage() method by the ADF framework, the
InformationalMessage constructor sets a value into the
error parameters that the CustomErrorHandler uses to
recognize the warning subtype as an informational message. The
overridden getDisplayMessage() method in the error
handler class detects whether the exception is an informational
warning, and if it is, it adds an informational message to the
FacesContext. It uses the setProperty() and
getProperty() API of the JboWarning object to set a
flag it can use to detect whether the exception has already been
reported by this custom mechanism. This is required because ADF
will invoke the getDisplayMessage() two times for each exception
reported, later only one of which gets reported to the user. Run
the Page.jspx to try the example. To see an error be
reported, enter a salary of 5002 and click (Next). To try a
warning, enter a salary of 5001 and click (Next). To see an
informational message, click the (addInformationMessageTest)
button. Notice that the custom error handler class is
declaratively configured via the ErrorClass attribute
on the root element of the DataBindings.cpx file (which
shows as the ErrorClass property of the root element in
the Property Inspector.
| | 143. | Referencing UserData Map Values from View Object Bind Variables in Groovy [11.1.1.0, SCOTT schema] 27-JAN-2009
This example includes a SessionHelper class to simplify
referencing entries in the ADFBC session's userData map from the
Groovy expressions providing the default values for bind
variables. The user data map is referenced via EL expressions in
the two JSPX pages, and it is referenced in Groovy bind variable
expressions in two places: (1) at the AM data model level for the VO
instance named AnotherInstanceOfQueryWithBindVarValue
(which you can see by selecting the VO instance in the Data
Model list and clicking the (Edit) button, and (2) on the view
accessor named QueryWithBindVarValue1 of the
EmpView view object. This latter view accessor is used
by the LOV definition on the EmpView view object's
Mgr attribute. To try the application, run the
SetUserMapValue.jspx page, type NameFilter
into the setUserMapValue_key field, and (for example)
the letter S into the setUserMapValue_value
field, and click (setUserMapValue). The table in the page
updates to show an example of a data model view object instance
using the bind variable value from the userData Map. Clicking on
the (GoTo Page Referencing Session Value in LOV Bind Var) button
takes you to a page where the search form shows that the view
accessor's rowset (based on the same
QueryWithBindVarValue view object) is using the bind
variable value from the userData map as well. The Groovy
expressions that access the userData map use the helper class
via the expression
test.model.SessionHelper.userData(adf.object).NameFilter. A
future release of ADF will make it simpler to reference the
ADFBC session object without the need for a helper class.
| | 142. | Passing RowIterator of Selected Tree Node to AM Method [11.1.1.0, SCOTT(Modified) schema] 20-JAN-2009
This example illustrates the correct way to operate on the
possibly multiple view link accessor rowsets of a tree
binding. A very common mistake developers make is that they
write application module custom methods that operate on a view
object instance in the datamodel, only to be surprised when the
changes they've made are not reflected in the tree on the
page. Their approach fails because the ADFM tree binding uses
view link accessor rowsets rather than data model view link
instances to work with detail rows. To understand the
difference, read section 35.1.3
Understanding View Link Accessors Versus Data Model View Link
Instances in the 11g Dev Guide. To make this point extremely
clear, the example's AppModule contains only a single
view instance in the data model called Departments. The
data model does not contain any view link instance or any
"Employees" view instance. While those are useful for some
master/detail UI scenarios, they are not needed/used-by a tree
binding. Instead, the tree binding materializes the employee
rows in each department by directly interacting with each
DeptView row's view link accessor attribute, producing
separate EmpView row sets for each of the distinct
department rows that the user expands to see the details
for. The example depends on a slightly modified version of the
usual EMP and DEPT tables called
DEPT_RANK and EMP_WITH_RANK. The latter table
contains one additional column named EMP_RANK which is
used to order the employees in a given department. You should
run the included CreateTables.sql script in your SCOTT
account before trying the demo. A few interesting points that
the demo shows off is the use of the generic
TableSupportBean which exposes some useful properties
to the EL expression language like
selectedNodeRowIterator and
selectedNodeRowKey. The method action bindings in the
page definition for the TreePage.jspx page reference
these properties in order to declaratively pass the correct
RowIterator and the key of the selected row in the table to the
application module custom methods which resequence the selected
employee's rank either up or down. Also note that in the
Tuning section of the General panel for the
DeptView view object, the Retain View Link Accessor
Rowset checkbox is checked on. This setting is required for
the tree binding to correctly reflect programmatic manipulations
in the pending transaction made by developer-written code in the
AM.
| | 141. | Automatic Runtime Query/Join Pruning with Declarative View Objects [11.1.1.0, HR schema] 20-DEC-2008
This example contains a single EmployeeAllInfo view
whose SQL mode is set to use the new-in-11g setting of
'Declarative'. It contains one editable Employees
entity usage, and six additional reference entity usages showing
related information about the employee's department, the
department's manager, the department's location, the
department's region, the employee's job, and the department's
country. When a view object is in declarative mode, its SQL
statement is determined at runtime instead of at design
time. Attributes in the view object can have their Selected
in Query property set to false, and these attributes will
only be selected if they are referenced by the page definition
for the current page, otherwise they will be left out of the
query. When multiple entity usages are involved, if all the
attributes from a given entity usage are left out of the query,
then the ADFBC runtime "prunes" that table related to that
entity usage out of the query and does not perform that
join. The application module in the Model project
includes three different instances of the same
EmployeeAllInfo view object. You can observe the
different runtime queries performed by the three different JSPX
pages by looking in the log while performing a search in each
page. The file Queries.txt included in the
ViewController project contains a formatted version of
the different queries. You can see in the query for the
MinimalEmployeeInfo.jspx page, that only the
EMPLOYEES table is included. In the query for
MediumEmployeeInfo.jspx you see EMPLOYEES,
DEPARTMENTS, EMPLOYEES (a second time for the
manager), and JOBS. The query for the final page joins
all of the tables.
| | 140. | Implementing OK or Cancel with Task Flow Transaction & Savepoint Support [11.1.1.0] 20-DEC-2008
This example illustates three bounded task flows that use
different declarative transaction options. The
manage-employees task flow has its
transaction property set to new-transction to
indicate that it should only be used as a top-level task when
no other current transaction is in effect. The
modify-employee task flow has its transaction
property set to requires-existing-transaction to
indicate that it only makes sense to be called as part of an
existing transaction (but cannot be called on its own), since
it requires parameters to work correctly. The
create-department task flow has its
transaction property set to
requires-transaction which allows it to be used either
as a top-level transactional flow, or else as a part of another
task flow with a transaction already in effect. To run the
example, run the ViewController project. The home page
has links that start either the create-department task
flow, or the manage-employees task flow. As part of
the task of managing employees, creating or editing an employee
calls the modify-employee task flow. While modifying
an employee, if you need to create a new department, the
create-department task flow is called. The 'Cancel'
return actions of the modify-employee and
create-department are configured to have the
restore-save-point property set to true so that, if
they are not the task flow that is controlling the transaction,
then they will use savepoints to allow canceling any pending
work performed in that flow without rolling back the entire
transaction. Experiment with performing some changes and doing
different combinations of (OK) and (Cancel) buttons to see the
effect of the nested transaction support. Before deciding to
save or cancel all changes you have made to employees, you can
see the modified rows' data in italics in the table, with the
modified attributes in bold/italic. This display is facilitated
by the use of custom row-specific attribute hints named
rowState and valueChanged that are enabled
due to the use of the CustomViewRowImpl framework
extension class in the FrameworkExtensions
project. The CustomViewObject in that project works
around a couple of issues in the 11.1.1 release related to the
quick query component (forcing the view criteria item operator
to be "Starts With" instead of "Like", and working around bug#
7660871 which causes the quick query criteria to not be applied
correctly in some situations). The CustomEntityImpl in
the project implements a generic solution for declarative
control over the posting order of associated (but not composed)
entities by allowing an entity to specify a custom
PostAfterAccessors property whose value is a
comma-separated list of association accessors which should be
checked for a new referenced row that should be posted before
the current entity. The Emp entity in the example is
configured with that property in order to cause a new,
referenced Dept entity instance to post first.
| | 139. | Making String Attributes Use the 'StartsWith' Operator in QuickQuery [11.1.1.0] 12-DEC-2008
In JDeveloper 11g, to create a "QuickQuery" search form you drag
the All Queriable Attributes view criteria from the
Named Criteria folder beneath any data collection in the
Data Control Palette and drop it onto your page, choosing "Quick
Query" from the component Create menu. It provides a one-line
search form that allows the user to pick from any of the
queriable attributes in the view object and perform a query. By
selecting the related search binding in the Executables
section of the page definition, you can use the Property
Inspector to set the default quick query attribute to the name
of the attribute that user's will likely search on most
frequently. They can then always use the dropdown field to
choose a different attribute to search on. Bug
7639222 reports the fact that end-users are surprised that the
Quick Query defaults to using the LIKE operator when searching
-- requiring, for example, that the end-user enter "k%"
[including the percent sign] to find an Ename like "KING". The
WorkaroundForBug7639222ViewObjectImpl framework extension class
in this example illustrates how to change the default quick
query behavior to use the "StartsWith" operator instead. This
allows the user to simply type "k" in the search field to find
"KING" as they would expect.
| | 138. | Auto-Enabling Commit and Rollback Buttons When Any Change in an Editable Table is Made [10.1.3.4] 10-DEC-2008
Since declarative PPR based on UI components id's in an editable
table does not work in 10.1.3, this example illustrates the
small bit of backing bean code (in
the onDeptnoDnameOrLocValueChange() method of the
Departments backing bean) that is necessary to make the
AutoSubmit=true inputText fields in the editable table
automatically enable the Commit and Rollback buttons as soon as
the first value is changed in the table. The page includes
normal declarative PPR (via the partialTriggers
attribute) that causes a click on the (Create) button or the
(Delete) button to enable the same two buttons. The expression
used in the disabled attribute is not the default one
dropped by the design time because it wasn't working for me to
enable the button when only a delete had been performed. This EL
expression referencing the transactionDirty attribute seemed to
work more reliably.
| | 137. | Implementing Custom View Row Hint Behavior [11.1.1.0.0] 9-DEC-2008
This example illustrates how to provide a custom view row
attribute hints implementation. The EmpViewRow class
overrides the createViewRowAttrHints method to return a
new instance of the EmpViewRowAttributeHintsImpl class
(which extends the framework base
class ViewRowAttrHints. In
the EmpViewRowAttributeHintsImpl class, notice that we've
overridden the getHint() API to conditionally return a
value for user-defined attribute hints named "mindate" and
"maxdate". These hints are coded to look at the value of
the Hiredate in the current row, and return a date String that
represents three days before that date for "mindate" and three
days after that date for "maxdate". The class also overrides
the getLabel API to customize the value of the "label"
UI hint for the Job attribute. Run the TestPage.jspx
and try to edit a "Hiredate" value. You'll see that the date
picker only allows you to change the date to a date that is
within a span of three days before to three days after the
current value. This occurs due to the UI component's referencing
the custom "mindate" and "maxdate" hints appropriately. Also,
you'll notice that the label for the "Job" field is the default
label with the value of the Sal attribute appended to
it.
| | 136. | Introducing a Checkbox to Toggle a Custom SQL Predicate on an LOV's Search Form. [11.1.1.0.0] 19-NOV-2008
This example shows a technique to include a checkbox in a
declaratively-defined LOV's search form which toggles on or off
a custom SQL fragment's being applied to the search. In this
simple example, we use the checkbox to allow the user to limit
the LOV search results to only include departments whose id is a
multiple of 20 (or not). The ViewController project includes a
simple view1.jspx page with a default ADF Form dropped
for the EmpView. The Deptno attribute of
the EmpView defines an LOV that references a view
accessor based on DeptView. The DeptView view
object has an additional SQL-calculated attribute
named ExtraAttr of type Boolean. The SQL
expression for the attribute is just the quoted string
'FALSE'. There is a view criteria
named LOVSearchCriteria defined on DeptView
and it includes view criteria items
for Dname, Loc,
and ExtraAttr. The ExtraAttr has the following
UI hints defined: Label Text is set to 'Show Only
Multiples of 20?'; Tooltip Text is set to some helpful
text, and Control Type is set to
'Checkbox'. The DeptView view object uses
the CustomViewObjectImpl class as its base framework
class, and so the DeptViewImpl custom view object class
extends that CustomViewObjectImpl to inherit a few
helper methods. The base CustomViewObjectImpl overrides
the getCriteriaItemClause() framework API invoke two
other methods getCriteriaItemClauseForDatabaseUse()
and getCriteriaItemClauseForCache() to customize the
SQL fragment returned for a particular view criteria
item. The DeptViewImpl class overrides these two
methods so that if the view criteria is "LOVSearchCriteria" and
the view criteria item is "ExtraAttr" and beging asked for the
fragment to use for database filtering, then we return the SQL
fragment "MOD(DEPTNO,20)=0" if the value of the view criteria
item is Boolean.TRUE, otherwise we return the harmless "1=1"
predicate. For the in-memory cache fragment, we override the
other method and return "1=1". Run the form, click the dropdown
list on the combobox and click on the "Search..." link to access
the popup LOV dialog. You'll see that if you check the checkbox,
then only departments whose id's are multiples of 20 appear in
the list, otherwise they are not restricted by this additional
(custom) criteria.
| | 135. | Using the queryPerformed Property of the Search Binding to Show a 'No Records Found' Message [11.1.1.0.0] 09-NOV-2008
The EL expressions used in the rendered property of
several components in the FindDepartments.jspx page in
this example use the queryPerformed property of the
search binding to conditionally hide the results table until the
user has performed a query. In addition, the same property is
used to conditionally show an 'Enter some criteria...' message
or a 'No departments found' message as appropriate. For more
information about the declarative options the search binding
supports, see the section entitled 'Changes to search form
binding default behavior since Technology Preview 4' in the
JDeveloper 11g
release
notes.
| | 134. | Passing Multiple Selected Keys from Tree, Table, and TreeTable to Application Module Method [11.1.1.0.0] 07-NOV-2008
A common requirement in pages containing table, tree, or
treeTable components is to allow the user to select multiple rows
and then carry out some operation on the selected rows. This
example illustrates the best-practice declarative approach to
accomplish this. First of all, notice that the code that
processes the rows is correctly encapsulated inside
the AppModule application module's custom java class,
and that both the processSelectedEmployees()
and processSelectedDepartments() methods are exposed on
the client interface so they are available for declarative data
binding in the data control palette. Notice they these accept
a java.util.Set (which we expect at runtime to
contain oracle.jbo.Key objects. The reason we're not
using Java generics like Set<Key> in the method
signature is that the ADFBC client interface mechanism does not
yet support using generics in the method signature. The
implementation of these methods processes the set passed in,
casting each object in the set to a Key and then using
the findByKey() on the appropriate view object instance
in the data model to find the row by its key and then act on
it. There are two pages in the demo view1.jspx
and view2.jspx. Start by looking at
the view2.jspx page, which includes a table
of DeptView rows from the view object instance
named Departments. Importantly, notice that to enable
the multi-select on the table three required steps have been
taken: (1) The rowSelection attribute is set to
"multiple", (2) the selectedRowKeys attribute
has been removed, and (3) the selectionListener has
been removed. Steps (2) and (3) are automatically setup to
support single-row selection and must be removed whenever
you enable multiple row selection in the table, or else the
multiple selection will not work correctly. The
custom processSelectedDepartments method was dropped
from the Data Control Palette onto the page as a button, and the
EL expression for the method argument is set
to ${View2.selectedAdfRowKeys[View2.myTable]} which
makes use of a generic helper backing bean that the
ViewController project includes to simplify working with multiple
selection in tables, trees, and treeTables. The View2
backing bean is defined in adfc-config.xml and rather
than using a specific backing bean class for the View2 page, its
using the generic helper
class MultiSelectSupportBackingBean. That bean
conveniently contains a property named myTable of
type RichTable which is designed to be referenced by
the binding property of a page containing a RichTable
where you'd like to perform some processing on its
multiple-selection. In fact, if you look at the binding
property of the af:table component in
the view2.jspx page, you'll see that it's set to this
property using the expression #{View2.myTable}. So
the ${View2.selectedAdfRowKeys[View2.myTable]}
expression used as the parameter value of the declarative method
action binding accesses the selectedAdfRowKeys
Map-valued property of the backing bean, passing
the View2.myTable instance of the RichTable on that page
as the map key. As you can see in
the MultiSelectSupportBackingBean class,
the selectedAdfRowKeys is an anonymous
subclass of java.util.Hashmap that overrides
the get() method to perform a custom operation when the
EL expression evaluator tries to access the map's properties. In
effect, this pattern allows us to introduce something that works
like a custom function that accepts one argument into our EL
expressions. In this case, the argument is the UI component for
which you'd like a Set of selected Keys. The view1.jspx
page shows the same
generic MultiSelectSupportBackingBean class in use as
the page's View1 backing bean, and three different
instances of method action bindings in the page definition
for view1.jspx are used to invoke
the processSelectedEmployees() custom method with the
appropriate UI component passed as the "argument" to the EL
expression to reference the Set of selected Keys. A last thing to
note about the example is how the EmployeeHierarchy view
object instance in the data model is setup. Notice that
the EmpView view object defines a view criteria
named EmployeesWithNoManager that finds employees that
have a Mgr attribute equal to
null. The EmployeeHierarchy view object instance was
added to the data model in the application module editor, then I
used the (Edit) button just above the Data Model tree to
edit that view object instance to apply
the EmployeesWithNoManager view criteria to it. This
means that initially the view object will only show employees
with no manager (e.g. KING). Then, due to the presence of
the test.model.links.Manages view link
between EmpView and itself, based on
the Empno->Mgr relationship, the direct reports of the
employees with no manager will appear as children in the tree and
treeTable due to the related tree binding rules that uses
the DirectReports view link accessor attribute to access
the nested child collections of direct reports rows at each
recursive level. Notice as well that there are no view link
instances required in the data model to work with the tree or
treeTable since the related tree bindings use the view link
accessor attributes to get detail information, and not data model
view instances linked via view link instances in the data
model. I highly recommend reading section 35.1.3
Understanding View Link Accessors Versus Data Model View Link
Instances to help understand the important distinction.
| | 133. | Joining Static Array of Database Type Data into View Object Query [11.1.1.0.0] 03-OCT-2008
This example illustrates an approach to take an array of
structured information and bind it into a view object query as
one of the tables in order to produce a database join between
the static information and the database data. The context in
which this example arose was that a service call was returning a
list of ranked/scored primary keys, that then needed to be
joined with the database table to which the primary keys
referred in order to produce a friendly display for end-users
that includes more descriptive information about the ranked
rows. You'll need to run the CreateTypes.sql script
before using the demo to create the SCORED_KEY
and SCORED_KEYS types in the
database. The ViewObjectImplWithScoredKeyBindVariable
framework extension class centralizes the code required to work
with the bind variable of
type oracle.jbo.domain.Array. In this case, its code is
binding the SCORED_KEYS type (which is a TABLE OF
SCORED_KEY) as an Array of SCORED_KEY types. Both
the ReadOnlyScoredEmployees
and EntityBasedScoredEmployees view objects inherit
this helper code from this
class. The setScoredKeysArray() method in the custom
view object class of both view objects calls the helper
method newScoredKeysArray() in the superclass to create
the Array of STRUCT and set the value of the view object's bind
variable. It expects to receive a List of
Map objects, expecting each Map in the List to contain
Map keys "Score" and "Key". The view objects both use the JDBC
positional binding style, indicating the (zero-based) integer
position of the bind variables as additional metadata in order
to still work with the bind variable as a named bind variable in
the view object API's. Run the TestClient class to see
the results of joining in the static data with the EMP table.
| | 132. | Programmatic View Objects Showing Master/Detail Data [11.1.1.0.0] 09-OCT-2008
This example illustrates some generic framework extension
classes in action for programmatic view objects whose data is
related master/detail. The generic infrastructure code lives in
the StaticDataViewObjectSupport project. All of the
view objects in the Model project specify
the oracle.adfbc.staticdata.CSVFileViewObjectImpl class
as their framework base class to inherit the generic
functionality of reading their data from a CSV (comma-separated
values) file. The ListOfMapsDataProviderViewObjectImpl
framework extension class implements a programmatic view object
whose data is populated from a java.util.List
of java.util.Map
objects. The CSVFileViewObjectImpl
extends ListOfMapsDataProviderViewObjectImpl to supply
a "data provider" that reads data from CSV files. By convention,
it reads data from the *.csv file in the same directory
in the classpath as the view object's component definition
file. So, for example, the model.States view object
reads its data from the model/States.csv file. The
compiler options of the project have been modified to add
the *.csv extension to the list of files that should be
copied to the outpath during compilation time. Four different
JSPX pages in the ViewController project allow you to
try out master/detail display of the programmatically retrieved
data.
| | 131. | ADF Web Application with Component Substitution [10.1.3.4] 06-OCT-2008
This example illustrates how to use the techniques outlined in
section 25.10
Substituting Extended Components In a Delivered Application
of the ADF Developer's Guide for Forms/4GL Developers to
substitute extended components into a running
application. The BaseADFWebApp workspace in the
download contains a simple, one-page DeptView data entry
form. Its Model project contains a test.Dept
entity object, test.DeptView view object, and
a test.AppModule application module containing an
instance DeptView1
of test.DeptView. Its ViewController project
contains a Departments.jspx page with the data entry
form. The Model project contains a ADFBC deployment
profile to deploy the ADFBC components as a simple java
archive. The ExtendsAndSubstitutes workspace contains
a ExtendsProject project which has imported
the test.Dept entity from the simple ADFBC JAR archive
created in the other workspace's Model project. It then
has created an extended entity
object extendsproject.DeptEx which extends
the test.Dept entity, overrides its Loc
attribute, and adds an attribute-level validator on Loc
to prevent the value from being the single, uppercase letter
"X". The ExtendsProject.jpx defines the component
substitution metadata saying that dept.Dept should be
substituted with extendsproject.DeptEx. This metadata
was defined using the Substitutions detail panel of
the Business Components project properties. In addition,
the Extends Project contains a
file ExtendsProject.cpx to workaround bug 6629321,
whose contents can be anything as long as it is a well-formed
XML file. In the example, the workaround file contains the
single element
<workaround_for_bug_6629321/>. The ExtendsProject
project contains another ADFBC deployment profile to deploy the
extended components as a simple JAR archive file. Finally,
the ViewController project adds the runtime Java VM
argument in its Run/Debug profile
of -DFactory-Substitution-List=ExtendsProject to use
the ExtendsProject.jpx file found in the classpath at
runtime as the component substitution
list. The ViewController project also includes a
project-level library defined to include the two simple Java
archive files for the extended components. To see the effect of
the substituted components, run the Departments.jspx
page and try to enter the value of "X" for the Loc
attribute of any row in the DeptView view object's
results and press (Commit). You'll see the validation error
added by the substituted extendsproject.DeptEx
component to know that the component substitutions are working.
| | 130. | Two Ideas to Handle JBO-35007 'Row Currency Changed' Exception [10.1.3.4, HR schema] 19-SEP-2008
This example illustrates how to use a custom page controller
class to override the handleError() method to
conditionally handle the JBO-35007 exception ('Row currency has
changed since the user interface was rendered.') in a way that
might be more useful to the end-user. This error can arise if
the user accidentally gets the current row in and editor form
out of sync with the current row in its underlying iterator.
One classic way this can occur is if the user is running
Internet Explorer and presses the [Ctrl]-[N] key to "fork" a new
window with the current edit form (typically in an innocent
attempt to view/edit two different rows side by side using two
separate browser windows. Another way this error can occur is
through use of the browser back button. To observe the custom
behavior, try running the listEmployee.jspx page using
Internet Explorer. Select an employee in the table and click the
(Edit) button. When the edit form appears, press [Ctrl]-[N] to
open a new browser window with the same form. Then, in that new
window, press (Back to List), select a different employee
row and click (Edit) again. At this point, return to the
original window and click the (Submit) button on the edit
form. Since this form is editing a row that is no longer the
current row in the underlying iterator, a JBO-35007 error will
be signalled, however the ControllerClass property of
the editEmployeePageDef XML file is configured
declaratively to use the custom page
controller RedirectJBO35007ExceptionToAnotherPagePageController
(in the bug.controller package) to handle the JBO-35007
and redirect to a problem.jspx page that tells the user
something about what just happened, and gives them a way to get
back to the list page. If you edit the value of
the ControllerClass property of
the editEmployeePageDef to be instead the name of
the SetRequestScopeAttributeFlagForJBO35007PageController
class instead, then when you repeat the above scenario to cause
the JBO-35007 error to occur you'll see that instead the page
becomes disabled and only allows the user to return to the list
page.
| | 129. | 11g Dynamic JDBC Credentials for Model 1, Struts, Trinidad, and ADF Faces Rich Client [11.1.1.0.0] 06-AUG-2008
This is an 11g production update of one of my most frequently
downloaded examples (Dynamic JDBC Credentials,
#14). There are four separate workspaces, one for each of
the supported ways you might build a web application using ADF:
DynamicCredentialsNoController.jws is a "Model 1" style
application with no controller
layer; DynamicCredentialsStruts.jws is
Struts-based; DynamicCredentialsTrinidad.jws is a
10.1.3 ADF Faces application that's been migrated to use the
Apache Trinidad components;
and DynamicCredentialsRichFaces.jws uses the new ADF
Faces Rich Client components that are new in 11g. Each project
references the same Model project
and FwkExtensions project. The generic framework
extension classes involved in implementing the solution live in
the FwkExtensions project. The Model project
contains the simple ADFBC components used in the example:
a TestModule application module with a
single DeptView VO instance of a DeptView view
object based on the DEPT table in the SCOTT
schema. While updating the example for 11g, I took the liberty
of using two new features that allowed me to simplify and
streamline the implementation. The first of these was using the
new ErrorHandlerClass attribute on the
root <Application> element of
the DataBindings.cpx file in each of the client web
projects in order to register a custom ADFM error handler
implementation (test.DynamicJDBCErrorHandlerImpl). This
error handler is designed to notice the DMLException
thrown by a failed database connection attempt (due to incorrect
username/password combination), and it throws that particular
exception rather than simply caching it on the binding
container. The second new feature employed is the ability to
register a global customization to the ADF Page lifecycle by
using a META-INF/adf-settings.xml file in each client
web project. Each project registers
the test.DynamicJDBCPagePhaseListener in order to
conditonally execute some custom logic before the ADF "prepare
model" phase of the lifecycle. This custom logic references the
data controls in the current page definition, causing them to be
checked out of the AM pool (if they were not already checked out
during the current lifecycle) before the JSF page rendering
begins. This allows the error handling code to catch the failed
connection attempt in time to redirect the user to the login
page before the rendering phase begins. The web.xml file for
each ViewController project contains a context parameter
(RedirectToLogin) that defines the login page to
redirect to for that particular web application. The JSF project
contains a second context parameter FacesURLPattern as
well. Due to Bug# 5080057, setting
the jbo.ampool.sessioncookiefactoryclass property in
the configuration is not correctly saved to
the bc4j.xcfg file. So, in order to configure a custom
session cookie factory class as required to repurpose the code
in this example in your own projects, you'll need to hand-edit
the bc4j.xcfg file to insert the child
element <jbo.ampool.sessioncookiefactoryclass>test.DynamicJDBCSessionCookieFactory</jbo.ampool.sessioncookiefactoryclass>
inside the appropriate <AppModuleConfig> element for
the configuration in question.
| | 128. | Synchronizing Emp Details with a Dept/Emp Tree [10.1.3.3] 21-FEB-2008
The Example.jspx page in this workspace illustrates a
tree based on the Departments view object
instance. The DeptView view object definition on which
this view instance is based, is viewlinked to the
EmpView view object with a view link accessor named
EmployeesInDepartment. The tree binding in the page
definition is configured with two rules in order to show the
Dname attribute for the DeptView rows, to
"drill down" into the EmpView details for each
DeptView row using the EmployeesInDepartment
view link accessor attribute, and to display the Ename
attribute for each EmpView in the tree. The tree
control has an id of myTree so that the
panelGroup component surrounding the employee detail
information can have its partialTriggers property set
to that id. This way, any user interaction with the tree
control will repaint the panelGroup and everything inside
it. Since we want to be able to conditionally toggle the
rendered property of the panelBox on and off, combined
with the fact that you cannot trigger a partial page refresh
event for a UI component that is not rendered, we need to
introduce this wrapping panelGroup component to be a stable UI
component in the page on which to configure the partial page
updating. The nodeStamp facet of the tree component
includes an switcher component to conditionally render
the tree nodes based on the current level of the tree. The
current level of the tree is determined by referencing the
expression node.hierType.viewDefName which allows us
to access the fully-qualified view definition name of the
hierarchy type (representing the tree binding rule) of the
current node. This will return a string of
"test.model.DeptView" for the nodes in the tree coming
from the DeptView view object, and a string of
"test.model.EmpView" for the nodes coming from the
EmpView view object. In order to avoid using these
"raw" view definition names as the switcher
component's facet names, we introduce a treeLevel map
in the Example backing bean to map the view definition
name to a logical facet name. The entries in this map
{(""test.model.DeptView", "DeptNode"),
("test.model.EmpView", "EmpNode")} are
configured declaratively in the faces-config.xml file
using the JSF managed bean facility. The facetName
property of the switcher is set to the EL expression
"#{Example.treeLevel[node.hierType.viewDefName]}"
which resolves to the logical facet name corresponding to the
view definition name of the current node in the tree, via this
map. In other words, DeptView nodes render using the
contents of the DeptNode switcher facet as a
outputText, while EmpView nodes render using the
contents of the EmpNode facet as a commandLink. The
command link is configured to have its action listener invoke
the declarative action binding
setCurrentRowInEmployeesIteratorWithKey which is the
name of the action binding in the page definition that uses the
built-in setCurrentRowWithKey operation against the
EmployeesIterator iterator binding. This action
binding is configured to pass the value of the EL expression
"#{node.rowKeyStr}" as the one parameter this built-in
operation requires. It is the stringified row key of the
current node in the tree that the user has clicked on. In the
Example backing bean, the onTreeNodeDisclosed
method is configured as the tree's disclosureListener. It has a
bit of code to set the set of expanded tree nodes to be only
the currently selected node, as well as a line of code that
hides the employee information panel box by setting its
rendered property to false. The
onClickEmployeeCommandLink is configured as the action
of the commandLink in the tree and it includes one line of code
that shows the employee info panel box. This panelbox includes
a panelForm that shows the employee detail information and
allows the user to edit the salary. In order to avoid the tree
interaction from posting data, it has its immediate
property set to true. This way, any user change to the form is
saved only if the user explicitly clicks on the (Save)
button. Last, but not least, the commandLink includes a nested
resetActionListener component to ensure that the editable UI
components on the page "pull" or "reset" their bound values
after the partial page request caused by clicking on the
tree. This ensures that the Sal field on the employee detail
panel is always correctly showing the value of the current
employees salary. [NOTE: An 11g version of this example that
has been migrated to use the Apache Trinidad components is
available here.]
| | 127. | Counting Number of Rows Changed (Inserted, Updated, Deleted) [10.1.3.3] 20-FEB-2008
This example illustrates an approach to count the number of
rows changed in the transaction (presumably for notifying the
end user). In the example, the total number of changed rows
(also broken down by inserts, deletes, and updates) is printed
to the console. The implementation involves a customized
DBTransactionImpl class which manages the counters in
the UserData hashmap in the Session and a custom
EntityImpl class (used by the Emp EO in the
project) which increments the appropriate insert, update, or
delete counter in its afterCommit() method.
| | 126. | Using Comma-Separated String Bind for Variable IN List [10.1.3.3] 10-JAN-2008
This example illustrates a simpler way to achive a variable
IN list in a view object's query. For example, imagine
that you want a DeptView view object to feature a
WHERE like DEPTNO IN (:TheDeptNo) but you need
the IN clause list to allow specifying one or more
department numbers at runtime. One approach illustrated by
example number 1 below involves writing some
code that assigns an array of one or more deptno values for the
bind variable. The approach presented here avoids the need for
any code in the ADF layer by using a database function
instead. Run the CreateTypeAndFunction.sql script to
create the NUM_TABLE type and the
IN_NUMBER_LIST() function. The function accepts a
comma-separate string argument and returns a NUM_TABLE
as its result. This allows the
CommaSeparatedListOfDeptno bind variable in the
example's DeptView view object to be of type
String. The view object's WHERE clause looks like
DEPTNO IN (SELECT * FROM TABLE( CAST (
in_number_list(:CommaSeparatedListOfDeptno) as num_table) )
). Run the AppModule in the tester can try
entering values like "10" and "10,40" for the bind variable to
see it in action.
| | 125. | Uploading Contents of af:inputFile to a CLOB Column [10.1.3.3] 03-OCT-2007
This sample is a CLOB-based version of example
#85. Using ADF BC's support for
the Oracle Intermedia ORDImage, ORDDoc, ORDAudio, and ORDVideo,
you can simplify uploading, downloading, and displaying media
and documents. However, since numerous users have asked for it,
this example illustrates a simple JSF page with an
inputFile component and the backing bean logic to
handle inserting the contents of the uploaded file into a CLOB
column in the database. Run the CreateTables.sql script
to drop and create the simple UPLOADED_FILES
table. Then, run the UploadFileToClob.jspx page. Note
that the page uses the af:form container with its
usesUpload attribute set to true. Also notice
that the inputFile control is bound to the backing bean
property named fileInputComponent, allowing the backing
bean to reference the UI component programmatically. The
valueChangeListener on the inputFile is mapped
via EL to the onFileUploaded() method in the backing
bean. That method accesses the ExampleModule client
interface of the ExampleModule application module, and
invokes the saveUploadedFile() method on it. It passes
in the file name, and a ClobDomain class representing
the contents of the uploaded file. The (Upload File) button's
action property is mapped via EL to the
onUploadFileButtonClicked() method in the backing bean.
This method either displays an error message if the filename to
be uploaded is bad, or else causes the "Last File Files
Uploaded" iterator to be re-executed to retrieve the latest list
of the last file files uploaded (by any user). See Configuring
ADF Faces File Uploading Servlet Parameters for information
on some settings you might need to configure.
| | 124. | Validating and Rendering Conditionally Required Attributes [10.1.3.3] 10-SEP-07
This example illustrates how to validate and render
conditionally-required attributes. After running the included
CreateTables.sql script to create the
OPTIONAL_REQUIRED_TEST table, run the
TestPage.jspx to see that when a row has its
RowType attribute set to the value A then the
ValueA inputText component renders, while if its
RowType attribute is instead set to the value
B then the ValueB inputText field
renders. These fields set the showRequired property to
true to show the required field indicator to the
end-user even though the underlying ValueA and
ValueB attribute are not marked as mandatory. The
conditional mandatory validation is performed in the
TestEntity entity object using entity-level method
validators. The radio group UI component is marked to have its
autoSubmit property true, and the
ValueChangeListener method in the backing bean for the
page sets a request-scope attribute as a flag to indicate that
the row type is changing. This flag is then referenced by the
ConditionalValidationPageController -- identical in
function to the one you might have seen in Example# 62
Cascading Lists in JSF -- which is configured to be used
by the TestPage by setting the ControllerClass
property of its page definition. This customized page
controller avoids validating the row if it detects that the row
type is changing. The conditional rendering of the ValueA or
ValueB inputText components is handled declaratively using an
appropriate EL expression for the component's rendered
property. When the autoSubmit radio group (with component id
"RowTypeRadio") causes its partial-page request, the panelForm
component in which the ValueA and ValueB inputText's reside is
declaratively "repainted" by having its
partialTriggers attribute set to that "RowTypeRadio"
id value. By performing the partial-page triggering on the
enclosing panelForm component, you avoid the gotchas related to
having PPR events delivered to currently-unrendered components.
| | 123. | Using a Custom Number Formatter to Parse/Format Social Security Numbers (SSN) [10.1.3.3] 31-AUG-07
This example includes a SocialSecurityNumberFormatter class
that extends the default ADF Business Components number
formatter class (DefaultNumberFormatter). It overrides the
parse() and format() methods to implement the parsing and
formatting of a United States social security number whose
format is 000-00-0000. The default number formatter does not
work with this format mask as is because the JDK DecimalFormat
class on which it's based doesn't correctly support that format
mask as you might expect. You'll need to run the provided
CreateEmpWithSocialSecurityNumber.sql script to create a
version of the EMP table with an addition SSN column to store
the social security number as a numerical value. The Emp entity
object sets the custom property named Ssn_FMT_FORMATTER to the
fully-qualified class name of the custom formatter class. This
property and its value are stored in the entity object's
companion EmpImplMsgBundle.java message bundle class. The
CustomDCErrorHandler class in the FwkExtensions project
contains logic that sets the attribute information on the
DataCreationException that is thrown if that information is not
already provided in the exception. This allows the error
message to be correctly reported as an exception specific to a
given attribute. Run the TestPage.jspx page to try entering
valid and invalid social security numbers. Notice that the
default <f:convertNumber> component has been commented out for
the <af:inputText> component for Ssn on the page.
| | 122. | Running Custom Backing Bean Code Before/After Default Table Selection Listener [10.1.3.2] 16-AUG-07
This example illustrates a TestPage.jspx page with an
af:table component whose selectionListener
property has been modified from the default EL expression dropped
when the table was created, to instead call a selection listener
method named onTableSelectionChanged() in the
TestPage backing bean. This default EL expression
normally looks like
#{bindings.TableBindingName.collectionModel.makeCurrent}
which declaratively "wires" the table selection event to invoke
the makeCurrent() method on the CollectionModel
of the table binding. In order to preseve the default
data binding functionality that reacts to the table selection
change, this backing bean method uses the invokeMethod()
helper method of the EL helper class to call the default
functionality with custom code before and after it. The EL helper
class is in the FwkExtensions project, which is marked
as a project-level dependency.
| | 121. | Declaratively and Programmatically Refreshing a View Object's Query Results [10.1.3.2] 24-JUL-07, Upd: 27-JUL-07
This example contains four JSF pages that each show a table of
department rows. The Departments.jspx page illustrates
how to use an invokeAction combined with an
Execute operation binding (and appropriate settings for
the Refresh and RefreshCondition properties of
the invokeAction) to conditionally refresh a view
object's query results based on the presence of a request-scope
flag attribute. You can read more about these settings in section
10.5.5
How to Use Refresh Correctly for InvokeAction and Iterator
Bindings. The AnotherPage.jspx, to which you can
navigate from Departments.jspx, contains two
af:commandLink components that navigate back to the
Departments.jspx page. One of those links uses a nested,
af:setActionListener component to declaratively set the
value of the request-scope attribute named refreshFlag
to the value true. The presence of this flag attribute
causes the invokeAction mentioned above to force a
requery of the rows. The DeptView view object is
instrumented to print a diagnostic message to let you see when
its base query and its estimated row count query get
executed. The range size of the iterator binding used on this
page is set to 2 to you can see the table paging behavior even
with only 4 rows of DEPT table data. When you use an
af:table and have a range size of N set
on your iterator binding to show only N rows per
page, then the estimated row count query will be used since the
table component needs that count to build its paging control. The
DepartmentsProgrammatic.jspx page is nearly identical to
the Departments.jspx page, except that it illustrates
how to accomplish the conditional requery of the view object from
code using the basic technique described in section 10.5.4.3
Using Custom ADF Page Lifecycle to Invoke an onPageLoad Backing
Bean Method section of the ADF Developer's Guide for
Forms/4GL Developers. It also uses a range size of 2. The
DepartmentsAlwaysRequestOnPageEntry.jspx page
illustrates how to create a page the refreshes its data each time
you navigate to it from another page (but not when you post-back
to it from the same page). And finally, the
DepartmentsTimedAutoRefresh.jspx page illustrates how to
use the combination of an af:poll component and an
Execute action binding to refresh the page without user
intervention every 5000 milliseconds (i.e. 5 seconds). Notice
that the af:poll component has an id attribute
set to the value "timer" and that an
af:outputText on the page as well as the
af:table UI components list this "timer" id in
their partialTriggers property so that they will be
partial-page refreshed to "repaint" any updated results. The
af:outputText just shows the current date/time to make
it easier to see when the timer is firing. In constrast to the
other three pages, this page has no explicit (Refresh) button, so
to create the Execute action binding in the page
definition I selected the Go to Page Definition choice in
right mouse context menu of the JSPX page visual editor window
and then used the Structure Window view of the page definition
for that page to select the bindings heading and
{Insert Inside bindings -> action}
right-mouse menu choice to create an action binding for the
DepartmentsIterator using the built-in operation named
Execute.
| | 120. | Simple AJAX-Style Partial Page Rendering (PPR) Example with AutoSubmit SelectOneChoice Control [10.1.3.2] 14-JUL-07
This examples contains a single JSF page with an EmpView
editing form. The EmpView view object includes the
Emp entity object as its primary entity usage, as well
as the Dept entity object as a secondary, reference
entity usage, in order to display the related Loc value
for the department to which the current employee is assigned. The
Deptno is bound to a af:selectOneChoice
component whose autoSubmit property has been set to
true. This causes a PPR postback whenever the end-user
changes the value of the list. The Loc field is
displayed as a read-only af:inputText, and has its
partialTriggers property set to the value of the id of
the af:selectOneChoice component
("DeptnoPoplist") that should trigger the partial page
re-paint of the that Locaf:inputText
component. When you run the page notice that if you navigate
between rows in the EmpView the PPR counter at the top
of the page increments to illustrate that the entire JSF page is
being re-rendered. In contrast, if you just change the value of
the autoSubmit-enabled Deptno poplist, then the value of
the corresponding Loc field repaints on the page, but
the PPR counter at the top stays the same (since only the bit of
the page that needed to be repainted was redrawn). Notice that
other than the PPRDemo managed bean that facilities
showing a counter on the page to better visualize when PPR is
occurring and not, the example requires no Java code to
implement.
| | 119. | Simple EJB-Based CRUD-Style Contacts Application [10.1.3.2] 13-JUL-07, Upd: 23-JUL-07
This example illustrates a simple JSF application that allows you
to list, edit, add, and remove contacts. The MyServiceBean
in the Model project is the stateless EJB 3.0 Session Bean
that acts as the business service. To keep the example simple, the
session bean works with an in-memory set of Contact POJOs
(Plain Old Java Objects). The Session Bean's service methods each
prints a diagnostic message to the console so you can better
understand and appreciate when the ADF Model layer is working with
the cached results of the finder methods as well as when it invokes
business service facade methods to add, edit, and remove a
Contact. The example is designed so that when the name of a
Contact is changed, the Contact's
updated property is updated inside the business service to
reflect the update time. When a new contact is added, edited, or
deleted, the application causes the executeQuery() method on the
method iterator to be executed to rebuild the RowSet of
data being managed by the RowSetIterator of the iterator
binding.
When an iterator is refreshed during the ADF page lifecycle it gets
a chance to decide whether its data needs to be recalculated by
asking the business service, or whether it can use its cached
data. For a method iterator, this decision is based on checking
whether the associated method action has stored the result of its
execution yet for a given set of its parameter values. If either
its result has not yet been calculated, or if any of its parameter
values has changed, then the method iterator is implicitly
requeried. When a method iterator is requeried, it invokes its
related method action binding and caches the result (unless the
CacheResults property is explicitly set to false,
which is not the case in this example!) and then rebuilds
the RowSet of Row objects that wrap the actual
data beans -- Contact beans in this example. These
Row objects adapt all bean data to have the same generic
API and delegate to the wrapped "dataProvider" bean in each row to
get/set the attribute values. It illustrates both programmatic and
declarative techniques for accomplishing this: the former by
invoking the executeQuery() in backing bean code, while
the latter using a combination of an Execute action
binding related to the method iterator and an invokeAction
executable whose Refresh and RefreshCondition
properties have been set to control the ADF lifecycle phase during
which the Execute action should fire as well as a boolean
EL expression to qualify under what conditions it should fire. You
can read more about these settings in section 10.5.5
How to Use Refresh Correctly for InvokeAction and Iterator
Bindings. It's important to note that since the
findContactsByName(String) method takes a parameter, we
take maximum benefit of the ADF Model layer's results caching when
we insure that the EL expression used to pass the method action
parameter continues to evaluate to the same value used when the
data was originally retrieved. In this example, the value of the
nameSearch that the end-user might apply to filter the
results is kept in the session-scoped UserInfo managed
bean so it can be referenced by the method action on both the
ListPage.jspx and the EditPage.jspx pages. If you
are not careful to insure this, then having the parameter values be
different on different pages, given the conditions described above
for the implicit execution of the method iterator, will cause
potentially unwanted re-execution of the business service
methods. The FwkExtensions project in the example includes
generic helper objects and framework extension classes to customize
the error handling very similar to those described in the ADF
Developer's Guides. The FindOrMergePage.jspx illustrates
an example of performing data binding to a method result that
returns a single Contact bean instead of a collection of
beans (List<Contact>), using the helper method
executeQueryForMethodIterator to re-execute the method
iterator's query (since JDeveloper design time prevents the
creation of a declarative Execute binding against such a method
iterator at the moment). If you enter an email address on this
page, it will find an existing contact by email if it exists and
update its name if you supply a non-null value for the name
parameter. If you enter an email that does not exist, it will add
it to the list. This page also shows off some programmatic
techniques for conditionally clearing the page definition variables
used by the ADF parameter form dropped onto the page. Since the
FindOrMergePage can make updates as well as add new rows,
the af:commandLink on the page sets the requestScope flag
to signal to the ListPage to refresh its data on
navigating there.
| | 118. | Selectively Uppercase String Bind Variable Values Through a Custom Metadata Property [10.1.3.2] 11-JUL-07
This example illustrates a framework extension class
CustomViewObjectImpl that overrides the
bindParametersForCollection method to conditionally
uppercase any String-valued bind variable parameter values that
happen to have a custom metadata property named Uppercase
set on them in their bind variable definition. You can use the view
object editor to inspect the bind variable named TheName
on both the DeptView and EmpView view objects to
see that they both have this Uppercase custom metadata
property set. Both of these view object specify
CustomViewObjectImpl as their base class in inherit this new,
generic functionality that is metadata-driven. To experiment with
the example, run the application module and enter a department name
is lower/mixed case like "research". Then click on the ":id" icon
of the detail Employees view instance and try filtering the
employees to ones whose Ename starts with the letter "s"
(entered in lowercase, too).
| | 117. | Editable Checkbox in an ADF Faces Table [10.1.3.2] 19-JUN-07
This example illustrates a simple technique for supporting an
editable checkbox in an ADF Faces table to allow toggling a
persistent status flag on or off. Before running the example JSPX
page, run the CreateTable.sql script in the Model
project to create a SETTINGS table with three rows of
example data. Since SQL does not have a native boolean datatype to
use for the type of a column in a table, the STATUS column
in the SETTINGS table is defined as NUMBER(1)
with 0 representing false and 1 representing
true. The example illustrates how you can introduce a transient
Boolean-valued attribute StatusAsBoolean to work
with the numerical true/false value as a Boolean. In the custom
SettingsViewRowImpl row class, the
getStatusAsBoolean and setStatusAsBoolean methods
have been written to convert the numerical value to a boolean upon
reading it and convert a boolean value to the correct
Number value upon writing it. In the JSPX page in the
ViewController project, the
af:selectBooleanCheckbox is bound declaratively to the
StatusAsBoolean attribute in the current row using the EL
expression #{row.StatusAsBoolean}. When you run the page,
try changing the state of the checkboxes and clicking
(Commit). Then from SQL*Plus, you can verify that the changed
boolean checkbox states have been correctly saved as 0 or
1 appropriately.
| | 116. | Including Multiple Levels of Automatically-Updated Reference Information in a View Object [10.1.3.2, HR schema] 09-MAY-07
This example illustrates an EmployeesView view object that
queries employees from the HR schema. It contains four levels of
reference entity usages, showing for the current employee: (1) the
name of the Department they work in, (2) the StreetAddress of the
Location of that Department , (3) the Country name in which that
location resides, and (4) the Region name in which that country
resides. Run the DemoModule in the ADF Business Components
browser and double-click on the Employees view object
instance to see its data. Experiment with changing the DepartmentId
foreign key attribute of an existing employee to notice that all
four levels of reference information correctly synchronize. You can
use the AllDepartments view object instance to remind
yourself of what some valid department id numbers are, and you can
use the four-level master/detail-coordinated view object instances
(Regions -> Countries -> Locations ->
Departments) to understand better what to expect when
changing the DepartmentId. The trick to having this
multi-level reference information synchronization work correctly is
that at each level the foreign key attribute referencing the next
level is included in the view object's attribute list. Notice that
the attributes whose names start with "PK" in the view object have
a Display control hint set to "Hide", so the ADF Business
Components browser hides them.
| | 115. | Custom Domain to Persist Transient ArrayList of Account Beans [10.1.3.2] 03-APR-07
This example shows a custom ListOfAccounts domain that
implements the necessary interfaces to allow its contents -- a list
of Account beans -- to be passivated and activated
correctly to the application module persistent state snapshot. It
shows a combination of required aspects including implementing the
XMLDomainWriter and DomainInterface interfaces, as
well as containing a public static getXMLDomainFactory()
method that returns an instance of a class that implements the
XMLDomainReaderFactory and XMLDomainFactory
interfaces. The ExampleTransientView in the project is a
transient view object with one String-valued attribute
marked as the key attribute, and another ListOfAccounts
attribute of type model.types.common.ListOfAccounts, our
custom domain. Both of these attributes are marked as updateable
and have their "passivate" property set to true. This view object's
create() method contains the best practice code required
for a transient view object that will be programmatically populated
by creating and inserting rows. Run the TestClient class
to exercise the creation of two rows in the transient view,
passivating the transient state, releasing the application module,
acquiring a new application module, activating the passivated
state, and iterating the transient rows again.
| | 114. | Showing a JSF Message if Search Produces No Rows or Too Many Rows [10.1.3.2] 30-APR-07
This example illustrates a SearchPage.jspx built using the
technique described in section 18.3.5
How To Create Search and Results on the Same Page of the ADF
Developer's Guide for Forms/4GL Developers that has been enhanced
with a small amount of backing bean code that customizes the ADF
page lifecycle to add a JSF FacesMessage in case the
EmployeesResultsIterator returns either no rows or too
many rows (with the limit hard-coded for this example to 10). The
SearchPage backing bean inherits from the
BackingBeanBase class as described in section 10.5.4.3
Using Custom ADF Page Lifecycle to Invoke an onPageLoad Backing
Bean Method of the Dev Guide (simplified slightly by using my
favorite EL helper class). The rendered attribute on
the af:table showing the search results in the
SearchPage.jspx uses an EL expression to cause the table
to render only when the number of rows found is between 1 and the
maximum allowed (10).
| | 113. | Apply Bind Varible Values to Filter View Link Accessor RowSets [10.1.3.2] 17-APR-07
This example illustrates a TestPage.jspx with a tree binding
based on a Departments view object instance of type DeptView.
The WorksInDeptLink view link defines a view link accessor attribute
named EmpView that is used by the tree binding to access the detail
rowsets of employees for each department. The DeptView
view object defines a custom method named
setLowHighSalaryRangeForDetailEmployeesAccessorViewObject()
that is exposed on the view object's client interface. The
TestPage.jspx includes a declaratively-bound parameter
form for invoking this method, passing in values for a
low-salary and high-salary range. This method accesses the view
object instance that the system creates at runtime to support
the view link accessor accesses, and sets the values of the two
named bind variables defined by the EmpView. The
DeptViewImpl class also contains an overridden
createViewLinkAccessorRS() method that applies the
bind variable values to each view link accessor rowset
created. Run the TestPage.jspx page and enter values
for the low and high salary range you want to see for employees
in the tree. For more information on the difference between the
view object instances in the application module's data model
and the system-created view object instance used to provide the
view link accessor attribute rowset, see 27.1.3 Understanding View Link Accessors Versus Data Model View Link Instances.
| | 112. | Using XSQL Pages with ADF Iterators in a JSF Application [10.1.3.2] 22-MAR-07
This example illustrates a TestPage.jspx with a button
whose action navigates to an XSQL page TestPage.xsql
to format the data in the iterator using XML/XSLT
techniques. The TestPage.xsql uses the custom XSQL
action class test.view.xsql.ADFViewObject that is
identical to the one that appeared in the ADF Toy Store Demo,
only refactored to live in a different package. The interesting
things to note about getting this example to work are: (1) The
web.xml file defines a filter-mapping for the
*.xsql URL pattern, (2) the DataBindings.cpx
has been modified in the code editor to contain an additional
page mapping entry for the /TestPage.xsql path so ADF
knows what page definition you want to use for that page, and
(3) by insuring that the URL requesting the page contains the
"/faces/" prefix in the path, this triggers the handling of the
request by the Faces Servlet (and indirectly the
ADFPhaseListener that is registered to be used by the
Faces infrastructure). This makes sure that the request-scoped
bindings attribute is correctly set to reference the
current page's runtime binding container.
| | 111. | Avoiding Runtime Describe Overhead When Defining Dynamic Read-only View Objects [10.1.3.2] 19-MAR-07
This example illustrates the code necessary to programmatically
create view definitions at runtime for dynamically-created
SQL-based view objects to avoid the runtime DESCRIBE overhead
that is associated with using the simpler API
createViewObjectFromQueryStmt(). The
TestClient program calls an application module's
client interface method named
createViewObjectAndViewLinks(). That method constructs
two view objects instances and a view link between them. Then,
the client code finds and iterates through the results of these
view objects. Since we programmatically define the names and
data types of the view object's attributes, ADF will not need
to perform a runtime DESCRIBE (involving a round-trip to the
database) to discover that information at runtime.
| | 110. | Updating Another Area of the Page When Table Selection Changes [10.1.3.2] 15-MAR-07
It's common to want a JSF page with a summary table that allows
the user to select a current row and a detail area showing more
information about the currently selected row. If you have enabled
the autoSubmit property of the af:tableSelectOne
component your af:table's selection facet, then it can
be a little puzzling why the other information on the page does
not update when you change the current row. This example
illustrates how to declaratively configure your af:table
and an af:panelForm that displays additional information
about the selected row in the table. The secret lies in
configuring the partialTriggers property of the
component that you want to be updated when the table selection
changes. In the example, you see that I'd assigned an id of
myTable to the af:table component, and on the
af:panelForm component I've
listed myTable as one of the component id's that should
trigger a partial-page request "repaint" (of the
af:panelForm). To allow you to experiment with toggling
the autoSubmit property of the tableSelectOne on or off at
runtime, I've configured a simple SessionSettings
session-scoped managed bean that has a single property named
useAutoSubmit. By setting the value property of
the af:selectBooleanCheckbox at the top of the page to
the EL expression #{SessionSettings.useAutoSubmit} we can
allow the user to use the checkbox to toggle the value of that
managed bean property. By also using the same EL expression
#{SessionSettings.useAutoSubmit} for the value of the
af:tableSelectOne component's autoSubmit
property, we allow the changing value of the managed bean
property to influence the runtime behvaior of the table
selection to be auto-submitting or not. Finally, since a change
in state of the checkbox needs to cause the table to repaint, I
have assigned an id value of
tableAutoSubmitControl to the checkbox, and listed that
tableAutoSubmitControl component id in the
partialTriggers property of the af:table. At
runtime, you'll see that if auto-submit it off, then the current
row changes when you click on the (testCurrentRow) button. If
auto-submit is on, then the current row changes as soon as you
click into the radio group button on the new current row. In both
cases, the panelForm to the right is updated to reflect
the values of the new current row. The (testCurrentRow) button is
a bound declaratively to the testCurrentRow() method on the
application module's client interface. It was created by dropping
that method from the Data Control Palette onto the page. When you
click on the button, you can see that the
getDeptView1().getCurrentRow() method call inside that
method already "sees" the new current row (and prints out its
Deptno value to the console).
| | 109. | Declaratively Populating Attributes from an Oracle Sequence [10.1.3.2] 15-MAR-07
Section 9.4.1.2
Eagerly Defaulting an Attribute Value from a Database
Sequence from the ADF Developer's Guide explains the two
lines of code you would add to an overridden create()
method of your entity object to programmatically populate its
primary key attribute from a sequence at row-creation time. Even
though this is only a couple of lines, if many of your entity
objects have sequence-valued primary key attributes and you are
not using database-trigger-assigned sequence values (described in
section 6.6.3.8
Trigger-Assigned Primary Key Values from a Database
Sequence), then you might be interested in a more generic,
metadata-driven solution. This example illustrates a simple
CustomEntityImpl framework extension class on which both
the Dept and Emp entities in the sample are
based. It's overridden create() method tests for the
presence of a custom attribute-level metadata property named
SequenceName and if detected, populates the attribute's
default value from the next number in that sequence using the
same basic code as above. The Dept entity defines the
custom SequenceName property on its Deptno
attribute with the value DEPT_TABLE_SEQ, while the
Emp entity defines that custom property on its
Empno attribute with the value
EMP_TABLE_SEQ. The supplied
CreateDeptAndEmpTables.sql script creates the tables and
sequences for you.
| | 108. | Customzing ADF Faces Convert Number Detail Error Message from a Message Bundle [10.1.3.2] 05-MAR-07
The af:convertNumber tag supports a number of attributes
that allow you to customize the detail error message when
conversion fails. For the basic number conversion failure, this
attribute is named convertNumberMessageDetail. In order
to reference a resource bundle message, normally you would expect
to be able to use an f:loadBundle tag in your page to
define a variable for a Map of the resource bundle strings, and
then reference the message using an EL expression like
#{res.NOT_A_NUMBER}. The complication is that the
resource bundles loaded with loadBundle are only
available during the page rendering phase, but not during the
validation phase. So, in order to drive the
convertNumberMessageDetail from a message bundle, I
needed to borrow some of the code from the JSF reference
implementation's loadBundleTag class that exposes a
resource bundle as a Map, and I put it in the
AppliationMessageMap managed bean class in this
example. I've configured that to be a session-scoped managed bean
and configured its basename managed property to have the
value view.resources.JSFMessages in
faces-config.xml. This allows me to reference my custom
error message for "Field 2" in the demo, in its
f:convertNumber tag's
convertNumberMessageDetail attribute using the EL
expression AppMessages.messages.NOT_A_NUMBER. To see the
custom error message, try typing a value like "adf" into Field 2
and clicking (Submit). You can run the demo with your browser
set to prefer "Italian [it]" to see the custom error message
translated in Italian.
| | 107. | Displaying ADF BC Mandatory Field Errors Using UI Hint Labels [10.1.3.2] 05-MAR-07, Upd: 13-MAR-07
The TestPage.jspx page in this example contains an ADF
Form dropped from the data control palette based on the
Employees view object. It consciously chooses to avoid
performing client-side required-field validation by not
setting the required property of the inputText
controls (which defaults to false). Instead, it sets the
showRequired property of the components to the same EL
expression that would normally be used by the client-side
required property. This has the effect that required
fields are rendered with the visual required indicator, but the
mandatory field validation is performed by the ADF BC layer
instead of on the client. The ViewController project
includes a custom ADF Phase Listener, a custom Faces Page
Lifecycle class, and a custom ADF Error Handler class just like
the SRDemo sample application (explained in section 20.8.1
of the Dev Guide) in order to customize the error reporting
behavior. A few enhancements that have been made in this
example's version of these classes are (1) The use of the
getComponentClientId method on the
FacesCtrlAttrsBinding object to retrieve the Faces
component client id in order to construct a FacesMessage
that is specifically related to a given UI component, (2) the use
of the ADF Faces LabeledFacesMessage class to create a
FacesMessage that remembers the label of the component
to which it's associated, and (3) the special-case handling of
AttrSetValException errors for mandatory fields in order
to display a custom string from the CustomMessageBundle using the
end-user-friendly UI label string of the attribute name that is
required. In addition, since we've disabled the use of
client-side mandatory field enforcement, combined with the fact
that the ADF model layer does not by default validate the binding
container if the end-user has not entered any values into any of
the fields, we've overridden the validateModelUpdates()
method in the CustomFacesPageLifecycle class in order to
call a helper method
forceValidationOfNewRowWithAllNullMandatoryAttributes()
which does what it's name suggests. This ensures that if the user
creates a new row and immediately clicks (Save) without entering
any values for any fields, they see the expected errors about any
mandatory fields. In addition, by running the
TestHomePage.jspx you can running two different
standalone create forms by clicking on an appropriate command
button. The CreateNewEmployeePage.jspx page is a more
traditional, declarative create form based directly on a view
object as described in section 13.6
Creating an Input Form of the Dev Guide. The
CreateNewEmployeePageUsingAMMethodViaEntity.jspx page
shows an alternative approach that requires coding an application
module custom method, exposed on its client interface, dropped
onto the page as an ADF Parameter Form. Note that using the
method-based approach, the method parameters are named the same
as the underlying entity object attributes so that the created
page definition variables and bindings have names that match the
entity object attributes. Also note that the application module
method uses an entity-based view object to create the new
employee rather than directly creating the entity object so that
the automatic bundled-exception handling is preserved. Try
setting the "Ename" to the value XXXXX in order
to observe what happens when an attribute-level validation rule
fails. Finally, also note that the UI Hints for the parameter
form page definition variables are defined in a message bundle
specific to the page definition. With the view object based
approach, those are automatically inherited from the underlying
entity object. The example also illustrates the use of
selectOneChoice "dropdown list" controls for mandatory
fields. Their corresponding list binding is configured to allow a
null value to correctly handle the fact that in a newly-created
row the value of that attribute will be null if your entity
object does not provide an alternative default value. The example
contains workaround code in the form of the
viewcontroller.util.ListBindingHelper to workaround bug#
5930745 where an additional blank entry can inadvertently be
added to the list when the list binding related to a
selectOneChoice control has a validation exception due to its
being mandatory. Finally, the backing beans for the
CreateNewEmployeePage and the
CreateNewEmployeePageUsingAMMethodViaEntity pages were
created in order to workaround bug# 5930784 where ADF/JSF
incorrectly performs page navigation even when exceptions have
been registered on the current page. By double-clicking on the
declaratively-bound button and allowing JDeveloper to generate
the ADF binding code in the backing bean, this reliably avoids
page navigation when the action binding has caused exceptions to
be raised. If you notice that sometimes the attribute-level
exceptions are reported with errors that appear next to the
fields and other times with errors reported only at the top, this
is related to bugs# 5918276 and 5929646 where the
getComponentClientId() function of the
FacesCtrlAttrsBinding returns null if the binding has
not previously "seen" a non-null value during the session as well
as the fact that the FacesCtrlListBinding does not
support a getComponentClientId() method. It is the
ability to retrieve the client id of the component related to a
binding that allows this example's custom error reporting to
construct an ADF Faces Message that will be rendered next to the
component to which it relates.
You can run the demo with your browser set to
prefer "Italian [it]" to see the page translated in Italian.
| | 106. | Further Filtering View Link Accessor RowSets at Runtime [10.1.3.1] 08-FEB-07
The test() method in the TestModule in this
example illustrates the important point discussed in section 27.1.3
Understanding View Link Accessors Versus Data Model View Link
Instances of the ADF Developer's Guide for Forms/4GL
Developers. It highlights how the view link accessor rowset is
based on a distinct, system-created view object instance as
compared with the developer-created view linked detail view
object instance in the data model, despite the fact that they are
both instance based on the same base view object definitionEmpView. The code shows adding an additional runtime
WHERE clause filter to the view link accessor rowset by
accessing its view object instance, and then performs a similar
task on the data model detail view object instance to show they are
indepdent. Run the TestClient.java class to see the
results of the test() method in action.
| | 105. | Efficiently Enforcing Uniqueness of Non-Primary Attribute Value [10.1.3.1]
This example illustrates how to implement an efficient existence
check to enforce the uniqueness of a non-primary-key
attribute. Using a Dept entity object based on the
DEPT table, we assume that in addition to the
Deptno primary key's uniqueness that is declaratively
enforced using the ADF UniqueKeyValidator, we also want to enforce
the uniqueness of the Dname attribute value. For the sake
of argument, we assume we'd like the value to be unique in a
case-insensitive way so that we won't allow one department called
"Sales" while another is named "SALES". The DeptDefImpl
class in this example implements an existsByDname() method
following the technique outlined in section 9.6.2
Implementing an Efficient Existence Check of the ADF
Developer's Guide for Forms/4GL Developers. This routine on the
custom entity definition class uses the
FindDeptByUniqueDname view object to test
case-insensitively whether a row exists in the DEPT table
with the supplied department name. If it doesn't exist in the
database, it then searches the entity cache to detect whether
perhaps another new instance created in the current transaction
might already be using the candidate department name value,
too. The Dept entity object class has an attribute-level
method validator defined to trigger the validateDname()
method in the DeptImpl class. This method gets the custom
entity definition class and calls the existsByDname()
method, returning true if the candidate department name does not
already exist. See section 9.3.1 How to Create an
Attribute-Level Method Validation for more information on
creating an attribute-level method validator. You can use the ADF
Business Components tester to verify that it's impossible to insert
two departments with the same department name.
| | 104. | Selecting a Row to Edit from a Popup Dialog [10.1.3.1]
The EditDepartment.jspx page in the example allows the
user to edit a row in the DEPT table. A button on that page has its
Action property set to dialog:selectDepartment
and has its useWindow property set to true so
that it invokes a modal, popup dialog containing the page
SelectDepartment.jspx. The commandButton on that page
contains a nested af:returnActionListener component whose
value is provided by the EL expression
#{row.rowKeyStr}. That will evaluate to the string format
of the current row's key (described in more detail in section 10.5.6
Understanding the Difference Between setCurrentRowWithKey and
setCurrentRowWithKeyValue of the ADF Developer's Guide for
Forms/4GL Developers.) The
onReturnFromSelectDepartmentDialog return listener method
in the EditDepartment backing bean shows how to process
the selected key value returned from the dialog and to set that row
as the current row for editing, followed by forcing the calling
page to refresh.
| | 103. | Programmatically Scrolling the JSF Table's Current Page of Rows [10.1.3.1, HR schema]
The ProgrammaticScroll JSF backing bean in this example
illustrates three different approaches to perform programmatic
scrolling of the 25 rows in the HR schema's COUNTRIES
table. Run the ProgrammaticScroll.jspx page and try using
the (<<) and (>>) buttons, optionally changing the scrolling
increment value in the text field located between these
buttons. You can use the drop-down list to pick among the three
different programmatic scrolling approaches.
| | 102. | Entity Object with Attributes that Must be Stored in Encoded Format [10.1.3.1]
This example illustrates the methods to override in order to
implement an entity object one or more of whose string attributes
must be stored to the database in an encoded format. The example
includes a simple CreateTablesAndPopulateData.sql script
that creates a USER_INFO table with USERNAME and
PASSWORD columns. As a trivial example of a entity object
String-valued attribute stored in encoded format, the corresponding
UserInfo entity object assumes that its Password
should be stored in this way. The encoding technique employeed in
the example is simple. A string like "abcd" is encoded when stored
in the database as "[dcba]", that is, with its letters reversed and
surrounded by brackets. Upon retrieving the entity object data from
the database, the example decodes a queried value for the password
by turning a string like "[dcba]" back into "abcd". The code is
implemented as a CustomEntityImpl framework extension
class, which the UserInfo entity uses as its base
class. The generic encode/decode logic in this class is enabled on
an entity object's String-valued attribute by setting the custom
attribute property named EncodeValue, which the
UserInfo entity's Password attribute has set. I
was hoping the code involved would have been more elegant, and if I
discover a more elegant approach I'll update this sample to reflect
what I learn. Of course, we make the assumption that encoded
attributes are not going to be user-queriable, however the example
code does nothing to stop the user from trying to query on it.
| | 101. | Reporting Model-layer Warnings and Informational Messages to JSF [10.1.3.1]
ADF Business Components has a built-in warnings facility that
complements the validation and exceptions features. This example
illustrates how to configure a custom FacesPageLifecycleClass
(described in more details in 10.5.4.1
Globally Customizing the ADF Page Lifecycle of the ADF
Developer's Guide for Forms/4GL Developers) which registers
itself as the JboExceptionHandler. This allows it to
receive the handleWarning() notification when any
business components warning is signalled in custom code. As
illustrated in the DeptImpl class in the example, you
signal a warning by constructing an instance of the
JboWarning class and passing it to the
addWarning() method of the
ApplicationModule. To distinguish between a warning and
a purely information message, the example introduces a subclass
InformationalMessage that extends JboWarning
and the handleWarning() method in the
CustomFacesPageLifecycle class reports the warning as a
FacesMessage with the appropriate severity. To
experiment with the demo, run the TestPage.jspx page and
try entering the value "ERROR" for the Dname
field. That will cause an attribute-level validation to fail for
that attribute. If you instead enter a Dname value of
"WARN", then you'll see a warning reported. And if you
simply make a change and save it successfully, you'll see a
purely informational message reported.
| | 100. | JSF Parameter Form to Invoke a Stored Procedure [10.1.3.1]
The example illustrates how to create a JSF parameter form for
calling a PL/SQL stored procedure. You'll need to run the
supplied CreatePLSQLPackages.sql script to create the
PL/SQL package named example_pkg used by the demo. This
package contains a single procedure do_something which
accepts a string parameter, number parameter, and date parameter
and inserts these values into a new row in the
EXAMPLE_PKG_TABLE table. In the J2EE application, the
stored procedure invocation is encapsulated inside the business
service inside the custom application module method
collectDataUsingStoredProcedure. It accepts one string
parameter, one number parameter, and one date
parameter. Internally the method calls the stored procedure using
the helper routine described in section 25.5.2
Invoking Stored Procedure with Only IN Arguments of the
developer's guide. This custom application module method is
published on the client interface as described in section 8.4.1
How to Publish Custom Service Methods to Clients. The JSPX
page in the ViewController project was created by
dragging the collectDataUsingStoredProcedure from the
Data Control Palette and dropping it onto the page as an ADF
Parameter Form. The page defintion variables get automatically
cleared after each page submit due to a navigation rule that
redirects back to the same page. The table below the input form
was created by dropping the data collection named
ExamplePkgTable from the Data Control Palette as a
read-only table. Both the view object attributes and the page
definition variables are leveraging ADF UI control hints to
supply translatable prompts and format masks.
| | 99. | Avoiding Clearing a View Object's Queried Rows at Rollback [10.1.3.2] 2006, Upd: 17-APR-2007
This example illustrates a technique to avoid having a view
object's queried rows cleared on rollback. There are three view
objects in the project, one named DeptView which is an
entity-based view object, one named
DeptViewNonEntityBased which is a read-only,
non-entity-based view object, and one named
TransientViewObject that is programmatically populated
and not based on a query. For read-only SQL-based view objects
and transient view objects, you can
prevent a rollback from clearing the view row cache by overriding
both the beforeRollback() and afterRollback()
method and commenting out the call to super. For an
entity-based view object, you need to override these two methods
as well as call the setClearCacheOnRollback() method on
the oracle.jbo.Transaction interface, passing
false. Note that this technique applies only to queried
rows and not to newly added rows. This is due to the fact that
during a rollback, as noted in the state diagram in section 9.2.5
Understanding Entity Objects Row States of the ADF
Developer's Guide for Forms/4GL Developers, any entity object
with 'New' status is removed (which transitions its status to
'Dead'). Note that the TransientViewObject is populated
by the prepareSession() method of the application
module, and that on its "Tuning" panel in the view object editor
it is set to never query rows by using the "No Rows" setting in
the "Retrieve From Database" section. This is equates to
declaratively setting the max fetch size of the view object to zero.
| | 98. | Entity Object Lightweight Event Publish and Subscribe [10.1.3.1]
This example illustrates one way to use the lightweight JavaBeans
event publish/subscribe mechanism that ADF Business Components
supports for entity objects. The Dept entity in the
project has published an event named
OnDnameOrLocChanged. When you define a new event on the
Publish tab of the Entity Object Editor, you indicate zero
or more entity attributes that will be delivered as part of the
event "payload" to any subscribed listeners. The event name is
user-defined and your code decides when it will fire by calling
the automatically generated method of the same named as the
event. In this case, looking in the DeptImpl.java class,
you can see that I've added a call to this
OnDnameOrLocChanged() method inside the
setDname() and setLoc methods. When you publish
an event, in addition to the generated method used to fire the
event, JDeveloper also generates code into a custom Entity
Definition class for the entity publishing the event. If you look
in the DeptDefImpl.java, you'll see generated methods to
addOnDnameOrLocChangedListener() and
removeOnDnameOrLocChangedListener. Other entities that
want to subscribe to the event can do so programmatically by
looking up the entity definition object of the publishing entity,
casting it to the more specific custom entity definition class
name, and then calling the addEventNameListener()
method. The Emp entity in the demo declaratively
subscribes to the OnDnameOrLocChanged event, indicating
that the event should be delivered to all associated Emp
entities based on a particular association that relates it to the
publishing entity. Note that the method to be invoked to receive
the notification must have a signature that matches the number,
type, and order of the attributes delivered in the payload of the
published event. Otherwise, you can choose to have the event
only delivered to entities that have programmatically registered
to receive the event using the methods mentioned above. If you
test the AppModule application module and try changing
the value of the Loc or Dname attribute of a
department, you can observe in the JDeveloper Log window that the
associated Emp entities in that department receive the
notification.
| | 97. | Force View-Object Attribute Default to Override Entity Default [10.1.3.1]
By design, if a view object attributes supplies a declarative
default value, it will be used as long as the underlying entity
object attribute (if there is one) has not already defaulted the
attribute to some non-null value. If you want to force a
view-object-attribute-level default to always be used, even if
the underlying entity object default has been provided, then this
example illustrates a MyViewRowImplframework
extension class that will achieve that. The DeptView
view object in the example indicates that it should use the
MyViewRowImpl class as its view row implementation
class. The Dept entity object supplies default values
for its Loc and Dname attributes, and the
DeptView view object specifies a further
view-object-attribute-level default value for the Loc
attribute as well. You can use the ADF Business Components tester
to try creating a new row to observe the behavior.
| | 96. | Sortable Transient View Object [10.1.3.3] 2006, Upd: 01-OCT-2007
This example illustrates a technique to override the
applySortCriteria() method in a custom ADF BC data
control to call setSortBy() on the iterator binding's
underlying view object instance instead of the default of calling
setOrderByClause(). The effect is that this leverages
the view object's built-in support for performing in-memory
sorting described in more detail in section 27.5.2
Sorting View Object Rows In Memory in the ADF Developer's
Guide for Forms/4GL Developers. The ViewController
project contains a custom subclass of the ADF BC data control, a
custom subclass of the ADF BC Data Control Factory, and a
reference to this factory in the DataBindings.cpx
file. The CountryList view object retrieves its data
from the companion CountryList.properties file. When you
run the CountryList.jspx page, try clicking the table
headings to sort ascending or descending by the
CountryCode or the Description. While not
required for the in-memory sorting example, the workspace also
includes a few classes required if you don't want your
application module to make any database connection at all. The
NoDatabaseConnectionApplicationPoolImpl class that
subclasses the default application module pool implementation to
return null in a few strategic places to avoid the application
module's connection to the database. The custom database
transaction factory class
NoDatabaseConnectionDatabaseTransactionFactory is
configured to be used by setting the TransactionFactory
property of the configuration, and it creates an instance of the
custom NoDatabaseConnectionDBTransactionImpl2 class
which overrides the doRollback() method to do nothing.
| | 95. | Change Preferred UI Locale with a Button in the Page [10.1.3.4] 2006, Upd: 11-NOV-2008
This example illustrates a technique to allow the user to toggle
the preferred UI locale between English and Italian by pressing a
button in the UI. The CustomFacesPageLifecycle class is
a custom ADF Faces page lifecycle class that overrides the
prepareRender phase of the ADF page lifecycle to adjust
the locale of the JSF UI View Root (from which the current user's
preferred locale is derived for the rest of ADF at runtime). For
more details about how its configured in the project see 10.5.4.1
Globally Customizing the ADF Page Lifecycle of the ADF
Developer's Guide for Forms/4GL Developers. It references the
App managed bean to see what the user's preferred locale
is. In the overridden prepareRender method, if
App.preferredLocale is different from the current UI
View Root's locale, then the method sets the locale of the view
to the preferred locale before calling
super.prepareRender. If it ends up changing the locale,
it also forces any List Binding objects with a translatable label
for their null entry (like "<No Department>") to have their
list of valid values recalculated so the null entry will render
in the new current locale. The TestPage.java backing bean sets
the value of the App.preferredLocale to either
ENGLISH or ITALIAN depending on the button you
click. Notice that the JSF resource-bundle-based message strings
change, as well as the ADF BC component UI hints that supply the
strings for the table column titles and field prompts. Also, the
AnotherPage.jspx page allows the user to change the
value of a transient number attribute that was added to the
entity object. The format mask of #0.00 is specified as
part of the UI control hints at the entity object level and you
can see that when in Italian a number like 3.45 is
presented and edited using the locale-appropriate decimal symbol
3,45. The regular JSP page
RegularJSPPageNotUsingJSF.jspx in the project
illustrates how a regular JSP page might test and set the JSF
managed bean that holds the user's preferred locale setting. This
might be interesting to understand if you are trying to allow the
user to set their preferred language from a regular JSP acting as
a login page in an otherwise-JSF-based application.
| | 94. | View Link Accessor Driving Details from a Parameterized Table Function [10.1.3]
This example contains two read-only view objects in its
Model project, one named MasterView and the
other named ListBasedOnTableFunction. The former is a
simple SELECT from DUAL that unions two rows of dummy data. The
first row has the value "D" for its LIST_TYPE column,
and the second row has the value "E". The
ListForMasterRow view link defines a link between the
master views ListType attribute and an attribute in the
detail view object (which one doesn't actually matter), and it
contains a custom view link SQL WHERE clause of simply "1 =
1". The ListBasedOnTableFunction view object defines a
named bind variable Bind_ListType that has exactly the
same name as the bind variable that the framework will
automatically add for the view link. The expert-mode SQL
statement for this view object references this bind variable
as the argument to the GET_NAME_VALUE_LIST() PL/SQL
function whose invocation it wraps in a TABLE() operator
to treat the table-valued function result as if it were a table
of data. The CreateTypesAndFunctions.sql script in the
Model project creates the NAME_VALUE_TYPE object type,
the NAME_VALUE_LIST type, and the
GET_NAME_VALUE_LIST() function. The function is written
to return a list of (Dname,Deptno) pairs from the DEPT
table if the value passed in is 'D' and a list of (Ename,Empno)
pairs if the value passed in is 'E'. Of course, the
implementation of the function could be arbitrarily more
interesting and dynamic without affecting the view object. The
ViewController project contains a simple JSF page with a
tree control displaying the two rows in the master view and their
parameterized detail rows (which are a function of the value of
the ListType attribute in each master row). The
SwingView project contains a simple Panel1
panel with a similar Swing tree control showing the same thing.
| | 93. | Entity and View Object Based on Web Service [10.1.3]
This example contains two separate workspaces
DeptADFBCWebService and
EntityAndViewBasedOnWebService. The former contains two
projects. The first is named Project and contains a
simple DeptService application module, and a default
Dept entity object, and entity-based DeptView
view object. The application module has custom methods on its
client interface like retrieveDepartmentData(),
estimateCount(), findDepartmentByDeptno(),
insertDepartment(), updateDepartment(),
mergeDepartment(), and
deleteDepartmentByDeptno(). The DeptService
application module has been published as a J2EE Web Service as
described in section 33.4
Publishing Application Modules as Web Services of the ADF Dev
Guide. The second project in the DeptADFBCWebService
workspace is a Tests project that contains JUnit tests
to test both the application module's local client interface as
well as testing the deployed web service. The tests should all
succeed if you have run the supplied
CreateEmpAndDeptTables.sql in the SCOTT
account. The WAR deployment profile in the Project
project deploys the web service to an external OC4J instance,
which you can launch most easily by running the
start_oc4j batch file (or shell script) in the
./jdev/bin subdirectory of your JDeveloper installation
home directory. After deploying, you can test the web service by
pointing your browser at the URL http://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort.
Note that the web service unit test fixture makes use of a web
service proxy class named DeptServiceSoapHttpPortClient
that was generated using JDeveloper's Web Service Proxy wizard,
using the WSDL URL of http://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort?WSDL
The second EntityAndViewBasedOnWebService workspace
contains an HRModule application module, and default
entity objects and view objects for the DEPT and
EMP tables. The DeptImpl.java has overridden
appropriate methods in a way similar to what is described in
section 26.4
Basing an Entity Object on a PL/SQL Package API of the ADF
Dev Guide to have this Dept entity based on a web
service. Similarly, the DeptViewImpl.java class has
overridden appropriate methods, similar to the technique
described in section 27.8.4
How to Create a View Object on a REF CURSOR of the
guide. When you use the Business Components Tester to test the
HRModule -- and you make sure you have the webservice in
the other workspace deployed and currently running -- you can
work with the data in the EmpView and DeptView
view object instances. When the data is read for the
DeptView it will pull it in from the underlying web
service. If you update the data for an existing department,
create a new department, or delete an existing department, the
changes are saved back using the web service in the other
workspace. Also try using simple view criteria in the tester to
search for department rows in the DeptView. That should work,
too.
| | 92. | Dynamic, Data-Driven JSF Parameter Form [10.1.3]
This example illustrates one technique for implementing a
dynamic, data-driven parameter form. The Database
project in the workspace contains CreateTables.sql and
InsertData.sql scripts that define and populate four
simple tables: PARAMETER_FORM_DEFINITION,
PARAMETER_DEFINITION, PARAMETER_CHOICES, and
PARAMETER_FORM_ITEM_SET. See the database diagram in
that project for a visual view of how they are related. The
insert data script populates some sample data for two parameter
forms named "Form1" and "Form2", each of which has some
collection of parameters in its form item set. The
ParameterFormItems view object queries the list of
parameters for a given parameter form by its form id, which is
passed in as a named bind variable (TheFormId). There is
a view link defined between the ParameterFormItems view
object and the ParameterChoicesView that enables a view
link accessor attribute named ParameterChoices in each
row of the ParameterFormItems view object's results. In
the ViewController project, you will find three
pages. The TestParameterForm.jspx page allows you to
select any of the defined parameter forms and test it by setting
the #{processScope.ParameterFormId} attribute to the
parameter form you've selected and navigating to the
DynamicParameterForm.jspx page. That page is the real
meat of the example. It includes a ADFM tree binding to expose
the hierarchical collection of data for the
ParameterFormItems and its collection of available
choices (via the ParameterChoices view link accessor
attribute). The page definition for this page includes an
invokeAction that triggers the firing of an
ExecuteWithParams action binding when the page is not
handling a post-back
(RefreshCondition="#{adfFacesContext.postback==false}"). This
allows the ParameterFormItems view object's
TheFormId named bind variable to be declaratively set to
the value in the #{processScope.ParameterFormId}
attribute that defines which data-driven parameter form to
show. The page defines uses an <af:forEach> to iterate
over the parameter form items. Inside this loop, it uses an
<af:switcher> based on the value of the
DisplayType attribute of the parameter definition. The
switcher determines whether to display the item as an
inputText, a selectOneChoice (i.e. dropdown
list), or a selectOneRadio (i.e. radio group) depending
on whether the DisplayType of each parameter is
'I', 'S', or 'R' respectively. In the
case of rendering the parameter as a dropdown list or radio
group, an inner <af:forEach> accesses the nested
collection of available choices defined to populate the list. The
last part of the example involves understanding where the user's
entered values are posted and stored. This is handled by a
transient view object attribute named UserValue that has
been added to the ParameterFormValues view object. The
ShowUserEnteredValues.jspx page renders the parameters
along with the user-entered values, and the
DynamicParameterForm.java backing bean class contains
code that illustrates how you would access the values of the
users parameter item values in the backing bean if needed. For
extra credit, you can use the ADF Business Components Tester on
the ParameterFormModule to maintain the parameter form
metadata that drives the parameter forms, adding a new form, new
items, or new item choices as needed.
| | 91. | Reusing Databound ADF Swing Panels with Different View Object Instances Using Model Parameters [10.1.3]
The EmployeePanel in this example was created using the
Panel wizard in the ADF Swing category in the New
Gallery. Then, I manually parameterized its data control and
iterator name using two page definition parameters named
dcParam and rsiParam (where 'rsi' is short for
RowSetIterator). The example includes four other ADF Swing panels
that then reuse the EmployeePanel, each passing in
appropriate values for the dcParam and rsiParam
parameters. To drop an instance of a reusable ADF Swing panel,
simply select the Component Palette page named ADF Swing
Regions and you'll see that the EmployeePanel
automatically appears there as a reusable component. When you
drag/drop the EmployeePanel onto a panel where you want
to use it, JDeveloper pops up a dialog asking you to fill in EL
expressions to give appropriate values for the panel's
dcParam and rsiParam parameters. In this way,
you can reuse the same panel with different view objects. You'll
see a special "page" binding appear in the Executables
section of the including panel's page definition, along with
metadata capturing the EL expressions you've entered. The example
features a Panel1 panel that reuses
EmployeePanel to display the results of the data
collection named EmpView1 in
TestModule1DataControl. A Panel2 panel reuses
the EmployeePanel panel bound to the data collection
named AllEmployees in the
TestModule2DataControl, based on a different application
module. The Panel3 panel illustrates that you can reuse
the EmployeePanel for a data collection that is a
view-linked detail view object instance, in particular the
EmployeesInDepartment data collection in the
TestModule2DataControl. And finally, the Panel4
panel shows that you can reuse the EmployeesPanel bound
to a view object that's completely different than the original
one that was designed to create it, provided that it has the
expected attribute names with the expected data types. In this
case, it is bound to the data collection named
EmployeesReadOnly in the
TestModule2DataControl, an instance of the
non-entity-based (and hence read-only) view object of the same
name.
| | 90. | Avoiding Dirtying the ADF Model Transaction When Transient Attributes are Set [10.1.3]
At the ADF Model data binding layer, there is no distinction
between attributes that are transient or persistent. When any
attribute's value is changed through an ADFM binding, the
ADFM-layer transaction is marked as dirty. This can have the
unwanted side-effect of enabling the JClient navigation bar's
Commit and Rollback buttons even if the only thing the end-user
did was to change the value of a transient field, potentially
leading to end-user confusion. This JClient example illustrates a
DeptView to which an additional transient Boolean
attribute named Selected has been added. The
View project in the example illustrates a custom ADF
Business Components data control class
(MyCustomADFBCDataControl) that extends the default ADFBC data
control class (JUApplication). The custom version
overrides the setTransactionModified() method to avoid
dirtying the transaction unless the transaction related to the
underlying application module is actually dirty. The companion
MyCustomDataControlFactoryImpl is required to
instantiate the custom data control class, and the
DataBindings.cpx file references the fully-qualified
class name of the custom data control factory class in the
FactoryClass property of the
<BC4JDataControl> element in the
<dataControlUsages section of that file. Run the
Panel1 class to see the code in action. Clicking on the
Selected? checkbox toggles the value of the transient
flag, as visible by the message that the setSelected()
method in the custom view row class prints to the console, but
the JClient toolbar does not enable the Commit or Rollback
buttons until you actually modify some persistent attributes.
| | 89. | Maintaining Many-to-Many Intersection Rows in a Multiselect Table [10.1.3, SRDemo schema]
This example illustrates a very model-centric approach for
managing the rows in an intersection table of a many-to-many
relationship using a multi-select table. It is based on the
tables in the SRDemo schema USERS, PRODUCTS,
EXPERTISE_AREAS. The Staff view object is an
entity-based view object based on the User entity object
that has a WHERE clause to retrieve only the users having a
USER_ROLE is either 'technician' or
'manager'. The ProductExpertiseAreas is an
entity-based, expert-mode view object whose SQL statement is
crafted to use outer joins to return exactly one row for each
available product. The view object has the Product
entity object as its primary entity usage, and has
ExpertiseArea as a secondary, reference entity usage. It
defines a named bind variable Bind_UserId that is
consciously named exactly the same as the system bind
variable the framework will add for the view link between
Staff and ProductExpertiseAreas (based on the
UserId). That view link has a customized view link SQL
clause to allow the USER_ID to be NULL so that
the detail rowset retains a row for every product, even when the
current user does not have expertise for that product
currently. Due to the outer join, rows retrieved retrieved in the
ProductExpertiseAreas view object will have a non-null
ExpertiseArea entity row part when the current user has
expertise area in that product. Conversely, if the current user
does not have expertise in a given product, the
ExpertiseArea entity row part will be a blank entity
row. To simplify the client, we introduce a transient
Boolean-valued attribute on the
ProductExpertiseAreas view object named
HasExpertise. We override the getHasExpertise()
and setHasExpertise() methods in the view row class to
handle retrieving and setting this transient attribute. The
setter method handles either creating a new
ExpertiseArea instance corresponding to the current
userId and prodId combination, or removing an
existing entity row, depending on whether HasExpertise
is being toggled on or off. Implementing a model-centric solution
gives three interesting benefits: (1) You can test and debug the
complete functionality just using the ADF
Busines Components Tester, (2) UI can just bind a checkbox to
the Boolean HasExpertise property, and the functionality
works the same in JSF, JSP, or Swing. The ViewController
project contains a simple JSF page that displays a table
containing a selectBooleanCheckbox bound directly to the
HasExpertise attribute. In other words, it is not using
a special tableSelectMany component in its selection
facet. The checkbox is just a part of the "data" in each row.
Note: This example uses the SRDEMO schema from the SRDemo sample application. | | 88. | Dynamically-Updating JSP Graph in JSF Page [10.1.3.2] 2006, Upd: 25-JUL-2007
This example illustrates a JSF page with a dynamically-updating
graph. In the 10.1.3 release, ADF supports creating graphs and
the corresponding graph binding, however the graph tag is not yet
a JSF UIComponent. The PageWithDataAndGraph.jspx page in
this example illustrates how you can still use the
<graph:Graph> tag inside the JSF page by wrapping it
with an <f:verbatim> tag. In addition, to allow this
non-JSF component to still be updated dynamically (AJAX-style)
you further wrap the <f:verbatim> tag by a panel like
panelGroup. The backing bean for the page illustrates
how to allow an updateable UIComponent in a table to trigger
partial page rendering for other elements in the page by
programmatically calling the ADF Faces addPartialTarget
API. I initially created the graph tag by creating a regular
(i.e. non-JSF) JSPX page, and dropping the
EmployeesInDepartment data collection from the Data
Control Palette as a Graph, then I copied the graph tag and its
corresponding tag namespace to the page I wanted to include it
in. Lastly, I then copied the Graph binding into the page
definition of the target page, and ensured that its binding id
was unique. After renaming the graph binding to be unique, I
updated the EL expression in the Graph tag's
data attribute to reference the renamed graph
binding. Finally, I edited the chart's visual properties by
double-clicking on the BIGraphDef1.xml node in the
navigator and using the graph definition editor, the Structure
Window, and the Property Inspector. Also of interest is that the
chart binding is setup to graph a transient entity object
attribute called TotalComp which simply is the sum of
the Sal and Comp attributes to provide an
employees total compensation. Notice that you can edit the
Sal or Comm values in the table and the graph
dynamically updates. You can also use the navigation list or the
(Next) / (Previous) buttons to change the department, and the
graph updates to reflect the employees in the current
department. The Emp entity in the Model project
uses the generic, automatic attribute recalculation logic
explained in section 26.8
Implementing Automatic Attribute Recalculation of the ADF
Developers Guide for Forms/4GL Developers, and implemented in
the SRDemo
Sample ADFBC Version.
| | 87. | Expose Original Attribute Values in Pending Transaction [10.1.3]
Section 9.9
How to Access Original Attribute Values in the ADF
Developers Guide for Forms/4GL Developers explains the
getPostedAttribute() API you can use to access the value
of any attribute as it existed at the beginning of the current
transaction. This example illustrates a technique for exposing
that API in a generic way to the ADF binding layer so that your
application pages can display that original value to the
end-user. This could come in handy to allow the user to visually
review their pending changes in the transaction before finally
confirming to save the changes with a (Commit) button. In the
Model project, The technique involves: (1) exposing the
getPostedAttribute() API as public in a
CustomEntityImpl framework extension class since
otherwise the method would be protected, (2) automatically adding
a "shadow" attribute named OrigAttrName_orig for
each attribute in the view object (in the overridden
create() method of the CustomViewObjectImpl
class, and (3) returning the original value of the appropriate
underlying entity attribute using getPostedAttribute()
in an overridden getAttributeInternal() method of the
CustomViewRowImpl class. The Dept entity is
configured to use the CustomEntityImpl and the
DeptView view object is configured to use the
CustomViewObjectImpl component class and the
CustomViewRowImpl row class. In the
ViewController project, the technique involves
referencing the "_orig" attribute names in the EL
expressions for the values of certain UIComponents. Try
navigating through multiple rows in the DeptView and
making changes to the Dname and or Loc
attributes in any of them. As you scroll back and forth before
issuing the final transaction commit, you will notice that the
previous value of the changed attributes appear next to your
modified values wherever you've modified them.
| | 86. | Registering a Customized Page Lifecycle as JSF Managed Bean [10.1.3]
This example illustrates an interesting technique (that I
initially learned from the always-clever JHeadstart
team). The CustomFacesPageLifecycle class is registered
in the faces-config.xml file as an application-scoped
managed bean named PageLifecycle (the name is arbitrary,
of course). The CustomADFPhaseListener class is
registered in the "Life Cycle" section of the
faces-config.xml as well. Its overridden
createPageLifecycle() method uses the EL helper
class to return the custom page lifecycle class using the method
EL.get("#{PageLifecycle}"). Why would you want to do
this, you ask? The TestPage.jspx illustrates two simple examples
(and there may be more). The (Some Button) on the page has its
Action property set to the EL expression
#{PageLifecycle.onButtonClicked}, illustrating that the
custom lifecycle class (being EL-accessible) can have global
helper routines like an action listener method. Another example
is the Dname af:inputText fields whose Value
property is set to the EL expression
#{PageLifecycle.attributeBindingWrapper[bindings.Dname]}.
This shows that the helper routines in the custom page lifecycle
class can leverage a customized Map approach to
effectively provide simple, one-argument callable methods. In
this case, the getAttributeBindingWrapper map wraps the
AttributeBinding passed in as an argument. The second of
the two Dname inputText's shows that by wrapping the
attribute binding in this way and setting the Disabled
property to true, you can get an inputText that shows as a
disabled field instead of a read-only label which is the default
rendering of read-only inputText fields.
| | 85. | Uploading Contents of af:inputFile to a BLOB Column [10.1.3.3] 2006, Upd: 03-OCT-2007
Using ADF BC's support for the Oracle Intermedia ORDImage,
ORDDoc, ORDAudio, and ORDVideo, you can simplify uploading,
downloading, and displaying media and documents. However, since
numerous users have asked for it, this example illustrates a
simple JSF page with an inputFile component and the
backing bean logic to handle inserting the contents of the
uploaded file into a BLOB column in the database. Run the
CreateTables.sql script to drop and create the simple
UPLOADED_FILES table. Then, run the
UploadFileToBlob.jspx page. Note that the page uses the
af:form container with its usesUpload
attribute set to true. Also notice that the
inputFile control is bound to the backing bean property
named fileInputComponent, allowing the backing bean to
reference the UI component programmatically. The
valueChangeListener on the inputFile is mapped
via EL to the onFileUploaded() method in the backing
bean. That method accesses the ExampleModule client
interface of the ExampleModule application module, and
invokes the saveUploadedFile() method on it. It passes
in the file name, and a BlobDomain class representing
the contents of the uploaded file. The (Upload File) button's
action property is mapped via EL to the
onUploadFileButtonClicked() method in the backing bean.
This method either displays an error message if the filename to
be uploaded is bad, or else causes the "Last File Files
Uploaded" iterator to be re-executed to retrieve the latest list
of the last file files uploaded (by any user). See Configuring
ADF Faces File Uploading Servlet Parameters for information
on some settings you might need to configure.
| | 84. | Declaratively Toggling Display of PanelBox Based on Radio Group Value [10.1.3]
This example illustrates a simple JSF page with a
selectOneChoice and a selectOneRadio, each
with its respective value bound to an Integer-valued
backing bean property. The switcher controls use the
respective property value to toggle the display of an
appropriate PanelBox, and the partialTriggers
property setup on the containing panelGroup component
causes the panel to repaint when the value of the respective
selectOneXXX component changes.
| | 83. | Dump Application Module Pooling Statistics Servlet [10.1.3]
This example illustrates a servlet that dumps application module
pooling statistics and/or ADFBC database connection pooling
statistics to the browser. The
DumpPoolStatisticsServlet is configured in the
web.xml to map to the URL
/DumpPoolStatistics. The
DumpConnectionPoolStatisticsServlet is configured in
the web.xml to map to the URL
/DumpConnectionPoolStatistics. In contrast to using a
JSP page to dump these statistics, using servlets configured
this way instead avoids engaging the ADF Binding Filter, the ADF
Faces filter, or the ADF Faces servlet when viewing pooling
statistics. Run the EditEmps.jspx and click (Next) or
(Previous) a few times. Then click the "DumpPoolStatistics"
and/or "DumpConnectionPoolingStatistics" links in the page to
open a new browser window with the pooling statistics. Recall
that if your ADF application using J2EE datasources instead of a
JDBC URL connection, then you will be using your application
server's connection pool instead of the ADFBC connection
pool. In that case, the database connection pooling statistics
won't appear using this mechanism. CAVEAT: the connection
pools are named using the fully-qualified JDBC connection
credentials, which includes the password. We recommend using the
DumpConnectionPoolStatistics servlet with care in a
production environment and not leaving the configured
permanently (unless you protect access to it with a password
using HTTP authentication).
| | 82. | Adding a Dynamic 'Valid' Attribute to View Objects [10.1.3]
This example illustrates an framework extension approach for
adding a dynamic attribute named Valid to any view
object whose value returns true if the primary entity usage in
the row is valid, or false if it is invalid. The
CustomViewObjectImpl class adds the dynamic attribute
in its overridden create() method. The
CustomViewRowImpl class overrides the
getAttributeInternal() method to return the desired
value for the dynamic attribute. The Emp entity object
in the example has four different validation methods that
enforce business rules like: (1) If Deptno=40, then Job must be
SALESMAN or CLERK, (2) Salesmen in department 40 must have
salary of 1500, (3) Clerks in department 40 must have salary
1000, and (4) Comm is not greater than Sal. The
untitled1.jspx page in the ViewController project has a
ADF Faces table and references the dynamic Valid
attribute to highlight invalid rows in yellow using some
appropriate EL expressions in the inlineStyle attribute
of the fields in the table. The untitled1PageDef.xml
file had to be hand-modified to include the dynamic
Valid attribute in the AttrList of the
EmpView table binding so that the EL expression used
above of #{row.Valid} would be resolvable. And finally,
the Untitled1PageController class is registered as a
custom page controller for the untitled1.jspx page (by
setting the ControllerClass attribute at the root of
the page def XML document. This custom controller overrides the
default way that the validateModelUpdates() phase of
the ADF page lifecycle is implemented to force invalid rows to
be revalidated. This works around Bug# 5396224, where clicking a
second time on the ADF faces table's "Next" or "Previous"
navigation link causes a validation error to not be reported
again.
| | 81. | Refreshing Calling Page After Adding New Row in Popup Dialog [10.1.3]
This example illustrates one technique for causing the current
page, containing a "Browse Employees" table, to refresh upon
returning from a popup dialog wherein the user has added a new
employee. The onReturnFromDialog() in the
BrowseEmployees backing bean is configured as the
ReturnListener for the button. It calls a
refreshCurrentPage() helper method to accomplish the
page refresh. It works in combination with setting the
partialSubmit property and the
useWindow properties to true on the (Add New
Employee) button in the page. The onSaveNewEmployee()
method is required for the ActionListener on the (Save
New Employee) button since we want to conditionally return from
the dialog, only when no errors occur during the execute
operation on the "Commit" action binding. Using the declarative
<af:returnActionListener>, we couldn't accomplish
this conditional behavior. As a bonus, the example also
illustrates edit and delete behavior as well. By choice, the add
a new employee is performing an immediate commit, while the edit
and delete operations need to be explicitly committed or
rolled-back by the user.
| | 80. | Simple JSF Popup List of Values Page [10.1.3]
This example contains an "untitled1.jsp" page that uses a
separate "pickDept.jsp" page as a popup List of Values (LOV) dialog
page. The pickDept page includes
<af:returnActionListener> and
<af:setActionListener> as nested children
components of the submit button. These cause the popup dialog
page to return to the calling page and to set the selected value
into the Deptno attribute binding that I've added to the
pickDept page's page definition.
| | 79. | Setting First Row in New Page Current When Paging Through Table [10.1.3.3] 2006, Upd: 22-OCT-2007
This example contains an onRangeChanged() range-change listener
method in the TestPage.java backing bean for the TestPage.jspx
page. It uses a couple of lines of code to set the range starting
row to the new starting row index (zero-based) passed in the
RangeChangeEvent object, then sets the first row in the new range
to be the current row. It also sets a requestScope attribute as a
flag to allow the onSelectionChanged method to known whether or
not it should ignore the firing of the normal ADF selection
change listener or not. Note that the EmpView view object has its
"Fill last page of rows when paging through rowset?" property set
to false on the Tuning panel of the View Object editor.
| | 78. | Updating Form Fields When Using Immediate=True [10.1.3]
This example contains a DEPT-based view object presented
in both a table and a form display. The (Create), (Delete), and
(Rollback) buttons are set to have their immediate
property to the value true which causes validation to be
circumvented. There are two functionally-identical JSPX pages,
one which programmatically calls resetValue() on the
Faces UI components in the backing bean to cause their values to
be refreshed, and the other which uses the <af:resetActionListener>
to accomplish the same thing declaratively.
| | 77. | Using a View Object with SQLXML to Query Data from XML [10.1.3]
This example contains a DepartmentDataFromXML view
object that uses the SQL XML support in Oracle 9i Release 2 (or
later) to query the data from an XML document into a view
object. The view object accepts the XML text in a named bind
variable, and uses the xmltype() constructor to treat
that XML text as an XML document. Then it uses the
xmlsequence() operator to treat the results of
extract()-ing the <ROWSET>/<ROW> elements
from the XML document as individual rows of source data. Finally,
it uses the table() operator in combination with the
extractValue() operator to retrieve the data values from
each row of <ROW> fragments, breaking out a
DEPTNO, DNAME, and LOC value from the
row. The TestPage.jspx in the ViewController project allows you
to experiment with passing in different XML as the value of the
bind variable.
| | 76. | Optionally Filter Query Based on Presence of URL Parameter [10.1.3] This example contains a TestPage.jspx and
TestPageTwo.jspx. The first one illustrates using a combination
of an invokeAction executable in the page definition, bound to an
ExecuteWithParams built-in action, to declaratively pass the
value of the URL parameter named dname to the named bind
variable on the DeptViewWithBindVariable. The second
page illustrates an alternative technique that may be applicable
if the where clause that needs to be added is too complex or too
dynamic to create at design time. It uses a combination of an
invokeAction executeable in the page definition, bound to a
method action, to conditionally invokes either the
clearFilterOnDeptView() or the
filterDeptViewByDname() on the application module's
custom interface. Try tacking on an additional dname URL
parameter to either of the pages like ?dname=acc or
dname=*s* to see the effect of the filter. Intererstingly,
the pages use the ADF Faces af:switcher component to
conditionally present the results in a table or in a form
depending on how many results are identified by the query.
| | 75. | Test Consistency of an Entity Without Locking or Modifying Cache Data [10.1.3]
A customer asked how he could test whether an unmodified
entity instance is consistent or not with the corresponding
row in the database without having to first modify/lock the
row and without updating the entity cache with the new
values. These particular requirements meant that he couldn't
use the built-in features that perform this comparison for you.
This example illustrates a possible generic solution
to this by constructing an on-the-fly, read-only view object
to fetch the values of the persistent attributes in the entity
and comparing their values with the current entity
attributes. See the testConsistency method in the
CustomEntityImpl class. Run the sample Form.java
class and click on the (testConsistencyOfCurrentRow) button to
try it out. The textConsistencyOfCurrentRow() method
is a custom method the view object's custom interface which
gets the current row, then delegates to it's
testConsistency() method mentioned
above. NOTE: this solution could be optimized by
comparing only a "change indicator" column in the entity if it
is marked and it also doesn't do any special treatment for LOB
attributes whose comparisons you generally want to avoid due
to their overhead.
| | 74. | Automatically Disabling Eager Coordination of Details Not Visible on Current Page [10.1.3]
This example illustrates one possible idea for a generic
technique to automatically disable master/detail coordination
for detail view objects that are not displayed on the current
JSF page. It might be relevant to consider when you have a "deep" or
"wide" hierarchy of master/detail view objects in your
application module data model, where the end-user will be
navigating/changing master rows often, triggering automatic
master/detail coordination based on the view link instances in
your data model. By design, the business service layer has no
knowledge of what a "page" is or what view objects in the data
model are used by a given "page". By extending the framework's
business layer and controller layer, you can supply
information about the view objects in use in the current
page's binding container to the business service to enable it
to leverage this additional information to avoid eagerly
querying detail data that is not visible on the current
page. The framework extension class
CustomApplicationModuleImpl contains a method
enableDetailsForViewInstances() that accepts an array
of view instance names representing the views displayed on the
current page. It proceeds to explore the view link instances
in the data model related to the supplied view object names,
and enable/disable master/detail coordination as appropriate
so that only the view objects in the supplied list are
queried. The ExampleModule application module extends
this base class, and exposes the method on its client
interface. In the ViewController project, the
CustomJSFPageLifecycle class overrides the
prepareModel() method to augment this phase of page
processing to add a call to the abovementioned
enableDetailsForViewInstances() method, passing in a
list of view instances corresponding to the iterator bindings
in the current page's binding container.
Another framework extension class
CustomViewObjectImpl overrides the
executeQueryForCollection() method to short-circuit
any attempt to query a detail view object when the
framework-supplied named bind variable connecting it to the
current master row has a null value. It accomplishes this by
temporarily setting the maxFetchSize for the view
object to zero, calling the super, then restoring the original
maxFetchSize value.
The view controller project is instrumented with a customized
DCJboDataControl in order to add educational log output at the
beginning and ending of each request, and the
CustomViewObjectImpl class overrides the
bindParametersForCollection method to log the
execution of each query sent to the database. These two
elements make it easier to observe which view object queries
are getting executed on each request for educational
purposes.
The data model includes a main "CurrentEmployee" view over the
EMP table, with a number of first-level, and one 2nd-level
detail queries. The data in these detail queries is just dummy
detail data queried again from cartesion products over the
same EMP table to simulate various kinds of detail data.
There are four JSF pages in demo: Home.jspx,
Drill.jspx, AnotherPage.jspx, and
ThirdPage.jspx. Each shows some subset of the overall
data model.
Again for educational purposes, you can experiment with
enabling or disabling the generic optmizations using the value
of the AM configuration parameter named
enable.optimizations. The ExampleModule comes with two
different configurations, one that has this parameter enabled,
and the other where its disabled. By selecting the
DataBindings.cpx file in the ViewController
project, and selecting the ExampleModuleDataControl
node under the dataControlUsages section in the
Structure Window, you can use the Property Inspector to set
the Configuration property to toggle between using
the ExampleModuleLocal configuration where the
optimizations are disabled and the
ExampleModuleLocalOptimizationsEnabled configuration
where the optimizations are enabled. The example is configured
by default to use the configuration that has the optimizations
enabled. By experimenting with the
various pages in the demo that present different parts of the
overall hierarchy of view objects in the data model, you can
observe in the Log Window the difference in which queries get
executed as you navigate to different pages, navigate to
different master rows with the (Previous)/(Next) buttons,
drill down to third-level details, etc.
The ThirdPage also illustrates two
techniques for forcing data in view objects to be requeried to
have the user eagerly see the very latest data. The technique
illustrated for EmpDetails5 involves setting the
CacheResults property to false on its
iterator binding. This causes the framework to perform a
clearCache on the view object at the end of the
request. Requerying the EmpDetails6 iterator is done
using an invokeAction in the page definition, bound
to an ExecuteQuery action binding. This
invokeAction has a RefreshCondition set to
conditionally perform the data-refreshing query when the page
is rendered, but not during post-back. In both cases you can
observe when the data is refreshed by looking at the value of
the CurrentTime column in the tables.
In your testing, make sure to visit all of the pages (even
several times) and perform various levels of change
master/detail current rows to get the full effect of the
difference between the optimized and unoptimized cases.
| | 73. | Named Bind Variable Values Based on Attribute in Current Row of Another View Object [10.1.3.2] 17-JUL-2006, Upd: 07-JUN-2007
This example illustrates a CustomViewObjectImpl
framework extension class that adds an interesting feature to
any view objects that extend it. It allows such view objects
to have named bind variables whose value will be automatically
derived from an attribute in the current row of another view
object. In the example, the Globals view object is a
transient view object with no query, one updateable Number
attribute named DepartmentNumber, and a max fetch
size set to zero ("No Rows" setting on the "Tuning"
panel). The ExampleModule application module
overrides the prepareSession() method to insure there is a
blank row in the "Globals" view object instance. The
Employees view object has a named bind variable
TheDeptno that has a bind-variable-level custom
metadata property named VOAttributeReference set to
the value Globals.DepartmentNumber. Alternatively,
the implementation supports setting the view object bind
variable to an expression at the view instance level by
setting an application module custom property named
ViewInstanceNAme_BindVariableName_VOAttributeReference. This
allows you to use the same view object multiple times and have
different automatic value expressions for different view
object instances. At runtime, the
CustomViewObjectImpl's overridden
bindParametersForCollection() method detects any
named bind variables with such a custom property set,
evaluates the value of the indicated attribute in the current
row of the named view object instance, and automatically binds
that evaluated value for the bind variable's value. The view
object's query has a WHERE clause that accommodates the value
of the bind variable bind both NULL or non-NULL. When you run
the JSF page, type in a department number and click (Execute)
to narrow the list down to only those departments.
| | 72. | Search Page with 'Sticky' Criteria Value Across Pages Using View Object Named Bind Variable [10.1.3]
This example illustrates a simple search page over an EmpView
view object with three named bind variables EmpName,
LowSal, and HighSal. The SearchPage.jspx
was created by dropping the "ExecuteWithParams" action as a
parameter form. It presents the results on a second
ResultsPage.jspx. If the results were on the same page,
then the ADF data binding layer would preserve the user's
search criteria entry across postbacks to the same
page. However, since showing the results causes page
navigation, when the user returns to the search page, the
search criteria are back to their default values. In this
case, the named bind variables define their respective default
values to be null, so this means the reset criteria is null
when you come back to the page. If you want to have the user's
search criteria for the named bind variable stay "sticky"
across pages, then you can save it in an attribute in the
process scope, and then assign the search field binding to the
value of that processScope-saved value just before the page is
rendered. The example uses a variation on the
OnPageLoadBackingBeanBase class described in Using
Custom ADF Page Lifecycle to Invoke an onPageLoad Backing Bean
Method section of the ADF Developer's Guide for Forms/4GL
Developers. The SearchPage.java backing bean
overrides the onPagePreRender() method to set the
values of the search field bindings to the value of the saved
processScope attributes of the same names. The
ControllerClass property of the search page's page
definition references the backing bean as its page phase
listener using the EL expression #{SearchPage}. The
setActionListener components on the buttons in the
search page declaratively set the values of the processScope
variables.
| | 71. | Dropdown Lists in Table with Different Choices per Row [10.1.3, HR schema]
Complementing screencast
#7 ("Creating an Editable Table with a Dropdown List in
Each Row"), this example illustrates how to implement the more
complex scenario where the list of valid choices for the
dropdown list in each row is a function of some value in the
row. Specifically here, the table of "Departments" shows a
dropdown list for each department row where the list of choices
is the set of employees in that same department. The example
allows the user to choose between using a read-only view object
or an entity-based view object to drive the list. While in
practice you wouldn't provide your own end users this choice,
the sample helps you understand whether you should choose an
entity-based view object or read-only view object for your own
LOV queries. Instead of performing a separate query for each
department to retrieve the employees in that department, the
example illustrates querying all of the employees and then
changing the 'QueryMode' in order to perform in-memory
filtering as needed to return only those employees that below
to a particular department. See section 27.5
"Performing In-Memory Sorting and Filtering of Row Sets" in
the ADF Developer's Guide for Forms/4GL Developers for more
information on in-memory filtering. The JSF backing bean for
the page uses a useful trick to allow invoking an application
module method with a single parameter from inside an EL
expression. You'll see such an expression in the JSPX page in
the sample by looking at the <f:selectItems> tag
that's generating the set of choices for the selectOneChoice
dropdown list in each row of the table. Its value
attribute is set to the EL expression
#{DropdownListInTableChangingByRow.lovList[row.DepartmentId]}. This
syntax accesses a backing bean property named lovList
and if that property is a Map, then the EL resolver
will call the get() method on the Map-valued
property to access the entry with the key equal to the
expression row.DepartmentId inside the square
brackets. By implementing the lovList property in the
backing bean as an anonymous subclass of
java.util.HashMap with an ovverridden get(Object
key) method, we can intercept the attempt to access the
Map entry with the key of the current row's department id, and
instead have its value come from an invocation to an
application module method that returns the correct set of
employee choices for that current department. Not a totally
obviously technique, but I've included further comments in the
code that explain more of the implementation details.
| | 70. | Conditional View/Controller-Layer Defaulting of Fields in a Create Form [10.1.3]
Generally we advise putting business logic like attribute
default values into on overridden create() method of your Entity
Object as described in section 9.4.1
"Defaulting Values for New Rows at Create Time" of the ADF
Developer's Guide for Forms/4GL Developers. Section 9.10,
"How to Store Information About the Current User Session"
explains how a custom application module method can save data
into the per-user session "user data" hashtable, which entity
object business logic like create()-time defaulting can then
reference. However this example contains a Create.jspx page with
a Create.java backing bean that illustrates a case of
controller-layer logic that conditionally returns a default
value for the "Loc" binding based on controller-layer flags like
the presence of a #{requestScope.creating} attribute,
and on the value of a #{sessionScope.locDefaultValue}
attribute. The #{requestScope.creating} flag is set
declaratively using an <af:setActionListener> on the
(Create) button in the Browse.jspx page. The example works by
using a backing bean property to "decorate" the normal Loc
attribute binding. If certain conditions are true, then the
getLoc() method in the backing bean returns the value
of the session variable instead of returning the normal value of
the Loc binding. Try setting the session value to some value,
then experiment with clicking on the different buttons in the
browse page to show the defaulting occurring or not occurring as
inidicated on the button labels. We adopt this approach instead
of trying to programmatically set the binding immediately to the
conditional controller-layer default value so that we don't
cause the new row to change from its initialized status to a
"new" status (which will add it to the rowset. See section
10.4.4 What You May Need to Know About Create and CreateInsert
in the developer's guide for more information on this.
| | 69. | Browsing and Editing ORDImage Columns with JSF/ADF [10.1.3]
This example illustrates a simple browse page and edit/upload
page for images stored in an Oracle table column of type
ORDImage. Run the CreateTable.sql script in
thae Model project to create the IMAGE_TABLE
table. See the README.TXT file in the
ViewController project for some of the manual steps
that were necessary to create the working example since
JDeveloper 10.1.3 does not currently offer automatic
design-time support for ORDImage attributes, even though the
runtime support is there as the example illustrates.
| | 68. | Restore Current Row After Rollback [10.1.3, SRDemo schema]
This example illustrates a generic framework extension class
for view objects (CustomViewObjectImpl.java) that overrides the
beforeRollback() and afterRollback() methods in the base
ViewObjectImpl class to cache the key of the current row and
then restore the current row by key after the rollback. The
application module contains a line of code in its overridden
prepareSession() method which calls
getDBTransaction().setClearCacheOnRollback(false); The
(Rollback) buttons in the two example JSF pages are bound to
backing beans that call a helper method named
executeRollbackActionAfterDisablingExecuteOnRollback()
inherited from a RollbackHelperBase class. This method first
calls setExecuteOnRollback(false) on the binding container,
then finds an action binding named "Rollback" in the current
binding container and invokes execute() on it. The ADF Faces
tables in the two different pages are setup with the
"AutoSubmit" property set to true on their TableSelectOne
subcomponent. Unrelated to the currency restoration, but
interesting to note nonetheless, both tables have an
explicitly-assigned "Id" property value so that other panel in
the page can register a "partialTriggers" based on that
property to cause an Ajax-style partial-page refresh whenever
the current row in the table is changed.
Note: This example uses the SRDEMO schema from the SRDemo sample application. | | 67. | Data-Driven Radio Group in an Emp JSF Table [10.1.3]
This example illustrates an ADF Faces table showing rows in the
EMP table, where the Deptno attribute in each row is indicated
with a data-driven radio group. The page also illustrates the
automatic data-driven radio group you can get for a single-row
form by dropping the "Deptno" attribute of the "EmpView" view
object from the Data Control Palette as an "ADF Single Select Radio"
control. When using the radio group inside a table, you can see that
the tags are slightly different since the current value of the
radio group is given by the EL expression #{row.Deptno} instead of
an EL expression the references a binding directly. The list of values
for the radio group is provided in both cases by the DepartmentList
table binding in the page definition, based on the corresponding
iterator binding pointing to the DepartmentList view object instance
in the data model.
| | 66. | Simple Extension Using ADF BC Design Time Objects API [10.1.3]
This example contains a simple JDeveloper extension called
EmpDeptExampleExtension patterned after the JDeveloper
Extension SDK's "FirstSample" example. It adds a simple menu
option to the right-mouse menu called "Create Emp/Dept
Objects..." When you choose this option, it uses the API's in
the oracle.jbo.dt.objects package to create entity objects Dept
and Emp for DEPT and EMP tables in the SCOTT schema. It then
creates an association between them, default view objects for
the entity objects, a view link between the two view objects,
an application module, and view object instances and a view
link instance in its data model. Required installation steps
include: (1) Ensure you have installed the "Extensions SDK"
from the JDeveloper "Check for Updates..." center, (2) Making
sure you've defined a connection named "scott", (3) Editing the
"ADFBC DT Library" library definition to point to the
JDEVHOME/jdev/extensions/oracle.BC4J.10.1.3.jar in your
JDeveloper 10.1.3 installation, (4) Editing the target JAR file
name in the EmpDeptExampleExtension.deploy deployment profile
so that the JAR (whose name you should leave as-is) gets
deployed to the JDEVHOME/jdev/extensions directory in your
JDeveloper 10.1.3 installation. Then, after deploying the
deployment profile to produce the extension JAR file, exiting
JDeveloper, and restarting, you should have an additional menu
pick on the context menu in the Application Navigator. Choosing
this menu option in an empty project will create the objects
described above which you can immediately test using the
Business Components Browser.
| | 65. | Set Deleted Flag Instead of Actually Deleting a Row
Sometimes when the user deletes a row, you don't actually want
to physically remove the row from the table, but rather just mark
a "DELETED" column to have a value like "Y" instead. This example
shows how implement this by overriding the entity object's remove()
method to set a "Deleted" flag before removing the row, and then
overriding the entity's doDML() method to change a DML_DELETE operation
into a DML_UPDATE operation instead. The example includes a SQL script
to ALTER the standard EMP table to include a DELETED column.
| | 64. | Recalc Sum of Salary at the View Object Level
This example illustrates a technique where a transient attribute
of a view object is updated to reflect the total sum of some
attribute of all the rows in the view object's default row set.
The code to recalculate the sum of the salary is in the
getSumOfSal() method in the EmpViewImpl.java class. The custom
EmpViewRowImpl.java class for the view row implements the
getter method for the SumOfSal attribute by delegating to
this view object method. The EmpViewImpl class extends a base
DeclarativeRecalculatingViewObjectImpl class that contains
some generic code to enable declaratively indicating that one
attribute's change should recalculate one or more other
attributes. The EmpView defines the "Recalc_Sal" property to
leverage this mechanism to recalculate the "SumOfSal" attribute.
If you restrict the VO's results using the BC Tester tool, you'll
see the sum of the salaries reflects the subset. If you add a
new row or delete an existing row, the sum of sal is updated, too.
| | 63. | BeforeCommit Validation Only Once Per Entity Type [10.1.3]
This example illustrates a technique to introduce a new event
called validateEntityCollectionBeforeCommit() that fires only
once per entity object type involved in a transaction. The
DeptImpl.java class for the Dept entity in the sample
illustrates enforcing a rule that only a since department can
have the string "XX" in its name. The CustomEntityImpl.java
class contains the overridden beforeCommit() method which
cooperates with a custom DBTransactionImpl2 subclass to track
whether or not the beforeCommit() method has fired yet this
commit-cycle for a given entity type. If it's the first entity
instance of a given type for which the beforeCommit() is
firing, it invokes the new
validateEntityCollectionBeforeCommit() method that entities
inheriting from this framework extension class can override to
code their validation logic.
| | 62. | Cascading Lists in JSF [10.1.3.2, HR schema] 2006, Upd: 18-JUN-2007
This sample works on the HR schema, but requires first running
the supplied CreateAndPopulateCitiesTable.sql script to
create and populate an additional CITIES table that it
uses. The sample includes two JSF pages, illustrating two
different styles of cascading poplists you might need to
implement. Use the first style, represented by the
CascadingLists.jsp page, when the driving list serves
only to partition the set of choices in the dependent list. In
that page, only the CountryId is actually an attribute
of the LocationsView row. The RegionId of the
selected region is not present. On the other hand, use the
second style, represented by the
CascadingListsUsingTwoListBindings.jspx when both the
driving list and the dependent list have to update the value of
an attribute in the row being edited. In that page, a row in the
CitiesView includes both a RegionId and a
CountryId attribute.
The CascadingLists.jsp page allows creating, updating,
and deleting locations. The page has a "Regions" dropdown list
and a "Countries" dropdown list. The Regions
selectOneChoice is bound using a navigation
list binding, and the Countries selectOneChoice is bound
using a normal (LOV-style) list binding. The
onRegionListChanged backing bean method fires for the
ValueChangedEvent of the Regions dropdown, and simply
sets a request-scoped attribute to signal that the user has
changed the regions choice. This is a sign they want to be
editing the the current row to be a country in a different
region. The invokeAction in the page definition invokes
an application module method during the renderModel phase
(Refresh="renderModel") if the request-scoped property
just mentioned is not set. The onCountryChanged backing
bean method fires for the ValueChangeEvent of the
Countries dropdown, setting a different request-scoped attribute
to signal that the user has changed the country choice. Since
the navigation list causes the current row in the
RegionsIterator to change based on the user's current
selection, and since the Countries view instance in the
data model is an actively-coordinated detail view based on the
Regions master view, the changing of the current row in
the Regions view automatically coordinates the
Countries view to have the correlated set of countries
for the new current region. The
CascadingListsUsingTwoListBindings.jspx page uses two
list bindings instead of having the driving this be based on a
navigation list. The RegionId list gets its set
of valid choices from the RegionsList in the data
model. The CountryId gets its set of valid choices from
the CountriesListForRegion view instance in the data
model. This latter view instance is based on the
CountriesListForRegion view defintion that uses a named
bind variable (TheRegionId) in order to filter the list
of countries by a region id supplied as a parameter. The lists
use ValueChangeListener methods like the ones used in
the other page. The difference in this example is what the
refreshCountryListUnlessCountryChanging invokeAction
invokeAction executable in the page def is doing. In this page's
page definition, this invokeAction causes an
ExecuteWithParams action binding on the
CountriesListForRegionIterator to be triggered during
the prepareRender lifecycle phase whenever the user is
not changing the country. Notice that this invokeAction is
sequenced after the iterator binding for
CitiesViewIterator so that the value of the RegionId
binding will reflect the up-to-date state of the current
CitiesView row. That ExecuteWithParams action
binding is configured to pass the value of the
#{bindings.RegionId.inputValue} as the value of the
TheRegionId parameter of the view object. This ensures
that the whenever the page is displayed the country list
correctly reflects the current region.
Both pages' page definition references the
ConditionalValidationPageController class as described
in section 10.5.4.2
Customizing the Page Lifecycle for a Single Page of the ADF
Dev Guide in order to avoid validating the row if the page
request was caused due to the auto-submit of the Regions or the
Country poplists. Also, this custom page controller overrides
the prepareRender() method to conditionally set the
CountryId binding to null if the user is changing the
region poplist, detected based on the presence of the
request-scope RegionChanged attribute mentioned
previously. Also note that the example contains a group of
classes in the test.view.bug5930745 package to
workaround Bug# 5930745 that causes a JSF selectOneChoice
control to incorrectly display a blank entry when the value of a
ADFM List Binding is null and it has registered exceptions. The
ViewController project in this example also implements
the same custom error handling code as example# 107 and contains
a slightly-modified routine in its
CustomFacesPageLifecycle class for "dirtying" the first
updateable, mandatory attribute binding found to have a null
value. This avoids skipping validation when the user tries to
save the row without changing any values. NOTE:
fortunately all of this becomes easy and declarative in
JDeveloper/ADF 11g!
| | 61. | Driving All JSF Application Menus from Single XML File [10.1.3]
This example illustrates an XMLMenuManager bean that reads in a
single XML file (using Apache Commons digester) that complies
with the Menus.xsd XML Schema in the project. This XML file
describes all of the levels of menus for the example
application. The name of the XML file is injected as a managed
property in the faces-config.xml. The application doesn't
really do anything beyond showing the different levels of
menus, but it was some interesting ideas I wanted to share in
case it gave others some thoughts to run with to turn it into
something more fully-featured. In the ViewController project,
the SRDemoMenus.xml file describes the structure of the menus
that you will see if you run any of the five pages in the
sample. The labelKey property in the XML corresponds to the
resource bundle key for showing a locale-sensitive menu
label. An italian-translated message resource file is included
for experimentation. Click on File, then Print to see a
third-level menu.
| | 60. | Triggering OnPageLoad-Style Code in a JSF Backing Bean Using ADF PagePhaseListener or PageController [10.1.3]
This example illustrates two variations on an approach to have
custom backing bean code be fired during the prepareModel phase
of the ADF controller lifecycle (which is cooperating with the
JSF controller lifecycle at runtime). The PageLoadExample.jspx
page has a PageLoadExampleBacking bean. It implements the ADF
PagePhaseListener interface. The page definition for the
PageLoadExample.jspx page sets its ControllerClass property to
the EL expression #{PageLoadExampleBacking} so that the ADF
controller page lifecycle implementation delegates phase
listener calls to the backing bean. The PageLoadExample2.jspx
page is doing the same thing, except that its backing bean is
inheriting from a base class that hides some of the code. This
page also has a button that navigates to "AnotherPage" which is
setup similar to PageLoadExample2 backing-bean-wise. The
PageLoadExample3.jspx is using a backing bean that extends the
ADF PageController class. It's pageDef controllerClass property
is set to #{PageLoad3Backing} and this case illustrates that
you can mix the backing bean goodness with the overidability of
any aspect of the ADF page controller page lifecycle all in the
same class. The onNext() method in the backing bean illustrates
how the ADF page lifecycle will invoke an onXXX() method in the
page controller class when an action binding named XXX is
executed. This approach is how developers code event handlers
in JSP/Struts PageController classes in 10.1.3 as well.
| | 59. | Showing View Object Attribute Names or Label Hints in JSF Table [10.1.3]
This example illustrates one approach for binding a ADF Faces
table to show the attribute names of an "EmpView" view object
as its data, along with a checkbox that allows the user to
multi-select which attributes they like in the table. The
attribute metadata is populated into a transient
"EmpViewMetadata" view object in the prepareSession() method of
the application module. Two application module contains two
custom methods. The retrieveMapOfSelectedAttributeNames
iterates over the transient view object and returns a Map
containing the attribute names and the selected flag. The
resetEmpMetadataView resets the selected flag in each row of
the transient view object back to false. Both of these buttons
were exposed on the app module's client interface, and were
dropped from the data control palette as command buttons. The
selected checkbox was not created with a checkbox binding
(which translates string-valued true/false values). Instead, I
just dropped a selectBooleanCheckbox from the component palette
and set its Value property to #{row.Selected} since the
attribute name in the metadata view object that represents the
Boolean-valued selected flag is named Selected. The table
binding needs to ensure that it includes all the attributes
from the EmpViewMetadata view object. Double-clicking on the
declaratively bound button for retrieveMapOfSelectedAttributeNames
I let JDeveloper create me a backing bean and I too the Map
that results from invoking the retrieveMapOfSelectedAttributeNames
method and put it in the sessionScope. The EmployeeTable.jspx
page references this #{sessionScope.selectedAttributes.XXXX}
expression for each column showing attribute XXXX as the
value of the "rendered" property.
| | 58. | ADF and JSF Utility Classes [10.1.3]
This is a workspace containing a project with JSFUtils.java and
ADFJSFUtils.java utility classes that have some useful static
methods for building JSF/ADF applications.
| | 57. | Understanding How Pooling Parameters Affect Runtime [10.1.3]
This one-page JSF example is instrumented to print out console
log messages related to the ADF beginRequest(), afterConnect(),
prepareSession(), passivateState(), activateState(), reset(),
and endRequest() methods. By changing application module pooling
configuration settings and re-running the page, you can easily
see the difference in the log output to better understand what
is happening in the framework differently based on those
configuration setting changes. For more details on ADF application
module pooling, see Understanding Application Module
Pooling Concepts and Configuration Parameters | | 56. | Globally Changing the Default Number Format
This small example illustrates one approach to globally change
the default format mask for number attributes. It uses a custom
EntityDefImpl class to programmatically override the
resolveDefObject() method and set the FMT_FORMAT and
FMT_FORMATTER properties attribute definition property map of
any entity object attributes definitions of entity objects that
use this custom entity definition class.The same technique
could be applied for date attributes
| | 55. | Subclassing the ADFBC Data Control to Override begin/end-Request Method [10.1.3]
This example illustrates a MyDCJboDataControl that extends JUApplication
(which in turn extends the DCJboDataControl) so that it can override
the beginRequest() method to perform some controller later code at the
beginning of each request. There is also an endRequest() method that
can be similarly overriden, but it's not shown in the example. The
MyDataControlFactoryImpl.java overrides the default data control factory
to return the name of the MyDCJboDataControl class, and the DataBindings.cpx
file has been updated to reflect the name of this custom data control factory
class. The demo doesn't do anything spectacular, but after clicking on the
button in the test page to set a session level attribute, the conditional
code in MyDCJboDataControl will invoke a custom method on the application
module's custom interface passing in the value of the session attribute.
| | 54. | UIX Page with a Read-Only LOV for Selecting Department [10.1.2]
This example illustrates a UIX page called EditEmp.uix
where the user can see the DNAME value of the current
employee's EMP row, but cannot edit it directly. They must
click on the flashlight icon to popup an LOV to choose a
new department instead. The EmpView includes the Dept as a
reference entity and the EmpViewRowImpl.java class overrides
the setAttribute(int,Object) method to suppress the attempt
to set the Dname value. The LOV ends up setting the foreign
key Deptno attribute, and the ADF view object reference
mechanism faults in the correct DNAME value for that new
foreign key value automatically. Setting the Columns property
on the messageLovInput field was the trick I found to disallow
edits by the user, without marking the field read-only (which
has the side-effect of hiding the flashlight icon).
| | 53. | JClient Panel Allowing User to Supply Bind Variable Before Executing Query, Showing Results in JTable
This example contains a DeptView view object having the where
clause dname like upper('%'||:0||'%'), that
is a "zeroth" bind variable using the Oracle-style positional
bind variable notation. The Panel1.java class was created by
dropping a JScrollPane followed by dropping the DeptView1 view
object instance as a Table from the data binding palette onto
that JScrollPane. The "Go!" button was dropped from the data
control palette as an Execute button to cause the query to
execute. The field accepting the parameter is just an unbound
JTextField named jTextField1. There is code added in two places
in Panel1.java that is highlighted with the string ADDED
CODE in the comment preceding it. The first added code
short-circuits the initial execute query by setting the
underlying view object's maximum fetch size to zero (0)
initially, just before the call to refreshControl(). The second
added code adds an ActionBindingListener to the action binding
named "Execute" that got created when we dropped the "Execute"
action from the data control palette. That listener has a couple
of lines of code in its beforeActionPerformed()
method that sets the maximum fetch size back to unlimited (-1)
and sets the where clause parameter value by position.
| | 52. | Accessing Custom AppModule, ViewObject, and ViewObject Attribute Properties via EL in a JSP Page
This one-page example contains examples of the EL expressions
you can use to access the custom properties defined on an ADF
application module, view object, and view object attribute from
a JSP page. Run the "/EditDepartments" data page in the struts
diagram to see the results. There are some comments in the
EditDepartments.jsp page at the three places I'm using EL to
refer to custom properties from different levels.
| | 51. | Example of Accessing Bindings and BindingContainer as Managed Properties in JSF Backing Bean [10.1.3 EA1]
This simple example has a single Example.jsp page containing an
ADF Faces read-only table bound to the DeptView1 iterator, and a
few buttons. One button was created by dropping the
myCustomMethod() of the application module onto the visual
editor as a command button and is totally declarative. That
action created me the necessary action binding to invoke the
method. The parameter value being passed in is provided by an EL
expression property of the action binding parameter in the page
definition. The other two buttons are invoking action methods in
the MyManagedBean class. That managed bean is a simple POJO
class that is declaratively configured in the faces-config.xml
to inject a "bindingContainer" and a "myCustomMethod" property
of appropriate type, using appropriate EL expressions. This
means I can refer to these in my action method in an easy
way. The example simply outputs the result of invoking the
application module method into an output text field in the
page. NOTE: We're planning to make this more easy and automatic
for 10.1.3 production!
| | 50. | Simple Example of Runtime Component Substitution
This workspace illustrates a simple example of a powerful ADF
Business Components feature called runtime component
substitution. The BaseProject project represents an
application delivered by a software house or ISV containing ADF
business components. The CustomizedProject represents a
project that has performed some kind of on-site customization to
the base application's components. The CustomizedProject has
imported the com.somecompany.someapp package and created a new
CustomizedView view object in its
com.somecustomer.someapp package which extends the
originally delivered view object component named
ExpertViewObject in the base application's
com.somecompany.someapp package. In the
CustomizedProject, the component substitution list has been
customized to indicate that
com.somecompany.someapp.ExpertViewObject should be substituted
by com.somecustomer.someapp.CustomizedView instead. This is done
by editing the project properties in 9.0.5 and beyond, or in
previous versions by editing the *.jpx node in the
project. Doing a right-mouse "Test..." on the same SomeModule in
both projects, you'll see that in the base project the query
returns the number "1", while in the CustomizedProject the query
returns the number "2". This illustrates that at runtime the
indicated component substitution has been effected. You can
also see the same effect by running the TestClient program in
the base project, and running the CustomizedProject (which has
been configured to have the BaseProject's TestClient class as
its default run target). When running the base project, the test
client program will print the result "1" to the console. When
running it in the context of the CustomizedProject -- whose Java
VM arguments supply the jbo.project=CustomizedProject as
a system parameter to point the runtime framwork at the project
file where the component substitutions are defined -- you'll see
the same class, without recompilation or changes of any kind,
produces the result "2" to the console.
| | 49. | Declarative and Programmatic Techniques to Pass Arguments to Method Action Bindings
When you have a button that invokes a method in your data
control, there are two ways you can pass the parameters:
declaratively and programmatically. This small example contains
two runnable Swing frames that illustrate each technique. The
Form.java class illustrates the programmatic technique of adding
an action binding listener for the action binding and setting
the parameters list in the beforeActionPerformed() method. The
FormDeclarative.java class uses a JTextField that is bound to a
data control created for the simple MyBean class to hold a
transient property value. The UIModel for the FormDeclarative
page has a "sayHello" action binding, whose nested parameter
definition refers declaratively to the value of the text field's
binding object using the expression
FormDeclarativeUIModel.name. In both cases, if you type your
name into the text field and click the button, "Hello, YourName" appears in the log
window. Note that the "sayHello" action binding has its
"Requires Update Model" property set to true so that the value
in the current field is applied to the model bindings before the
method is invoked.
| | 48. | Custom Servlet Filter to Register a Globally-Available Data Control
This example contains an example of how to register a "system"
data control that needs to be available to the controller layer
on each request, without having to register that data control in
each application's DataBindings.cpx file. The scenario to
imagine is some metadata-driven controller logic, which needs
access to a "system" or "metadata" data control to accomplish
its job. In the example, the DataPage1Action class simulates
access to such a System Data Control in order to access a data
collection that provides some database-queried "metadata" like
the current database date, which it prints to standard out. Of
course in a real example, this would be more interesting
metadata that would help the DataAction decide what it should be
doing on the current request. The SystemDataControl project in
the workspace contains the InsureSystemDataControlFilter, which
is a servlet filter that shows how to extend a base template
filter class called
AdditionalBeginOrEndRequestProcessingFilterBase to perform some
additional custom processing at the beginning and ending of the
request. TheInsureSystemDataControlFilter loads a "System.cpx"
file to define the metadata for the system data control, and
insures that it is registered in the binding context. It also
illustrates how to access a custom data control parameter named
ReleaseMode to generically detect whether the data control
should be marked for being reset at the end of the
request. Since the SystemDataControl in the example is an ADF
Application Module, the ADF BC data control implements this
reset() method as a stateless release of the underlying
application module. Note that the sequential order of defining
the servlet filters in the web.xml file is important here,
particularly that the ADFBindingFilter come before the
InsureSystemDataControl filter in the file. This will guarantee
that the ADF Binding Filter will execute first, and the
InsureDataControl filter second. The logic implemented in
theAdditionalBeginOrEndRequestProcessingFilterBase guarantees
that even if the filter is engaged multiple times in the same
request, that the addition begin/end request processing only
occurs at the initial entry into the filter and the final exit
of the filter during the span of a single request.
| | 47. | Accessing Attribute Definitions on Source and Target of a View Link
This example contains an application module method called
demonstrateAccessingViewlinkAttributes() which
illustrates the coding technique you can use to access both the
source and target attribute definitions involved in a view
link. Run the test client to invoke this client-exposed method
in the appropriate way, using the generated client TestModule
interface, and the output will show in the console.
| | 46. | Exposing Entity Row State as View Row State on the Client in a Generic Way [10.1.3.2] 2006, Upd: 29-MAR-2007
This example illustrates a generic technique, implemented in a
combination of an extended ViewObjectImpl class and an extended
ViewRowImpl class, that exposes a dynamic attribute named
"RowState" on any view object that extends the custom
ViewObjectImpl class. It uses addDynamicAttribute() in an
overridden create() method in the ViewObjectImpl subclass to add
the dynamic attribute, and an overridden sourceChanged() event
to handle the notification of the change in row state for the
underlying entity object. The custom view row class overrides
getAttributeInternal() to return the value of the
Entity.getEntityState() method (translated to a user-readable
string value), as the value of the dynamic attribute. Note that
the ViewObjectImpl custom class -- counter to best practices! --
needed to be placed in the oracle.jbo.server package
because one of the API's required to implement this solution
generically was not currently public. I've created Bug # 4547474
to track getting the appropriate API made public in the future.
| | 45. | Accessing Array-Valued Bean Properties from a Row in JSTL
This example illustrates a model-one style JSP page (e.g. no
controller layer) that uses JSTL to render the
java.util.List-valued results of invoking the
findNominalRecords() method in the JavaBean-based data control
based on the "Service" bean in the "Model" project. The results
are just a couple of hard-coded NominalRecord beans, but the
point of the example is illustrating the JSTL syntax used to
refer to the underlying bean properties in a row through the ADF
binding layer when necessary. Normally we handle nested
collections as accessors, but this example illustrates an
alternative that works for JavaBean-based data binding that in
some cases might be a little simpler. Run the TestPage.jsp page
to see it in action.
| | 44. | Customizing How ADF BC Metadata Gets Loaded
This example shows an example of how to implement a custom
XMLContext implementation and use it at runtime. In the example
project, the MyMetaobjectContext class extends the base
XMLContextImpl class in the ADF BC framework, and overrides the
lookup() method. This method is responsible for returning an
InputStream over an XML document containing valid metdata for
the ADF BC component whose fully-qualified name is passed in. My
custom implementation loads the XML from an alternative source
if the component being looked up is "test.Dept", otherwise it
performs the default lookup (which will find the XML metadata in
a file on disk in the appropriate directory matching the
fully-qualified component's package name). Set a breakpoint in
the lookup() method of MyMetaobjectContext class, then debug the
TestModuleImpl class to launch the TestModule application module
in the Business Components tester in debug mode. We indicate to
the framework that it should use our customized metadata context
class by setting the configurationi property MetaObjectContext
to the fully-qualified class name of the XMLContext
implementation that we want to use. If you look at the
properties in the TestModuleLocal configuration for the
TestModule application module, you'll see that property there,
set to the value test.MyMetaobjectContext.
| | 43. | Generic Framework Extension to Suppress FIRST_ROWS Optimizer Hint in Range Paging Queries
The MyCustomViewObjectImpl.java class in this little example
illustrates how to write generic code in an overridden
buildRangePageQuery() method which conditionally strips the
FIRST_ROWS query optimizer hint out of the "wrapped" range
paging query that the framework would normally
build. Generally the FIRST_ROWS hint gives the best performance
for thiscase(which is why we default it in there), but some
users have found situations where they wanted to suppress
it. The generic framework extension code calls the getProperty()
method on the ViewObjectImpl class to see whether the view
object developer has set a custom property named
RangePagingFirstRows to the value N, and if they
have, it strips the query optimizer hint before returning the
range paging query. On the "Java" panel of the view object
editor for the Employees view object, if you click the
(Extends...) button, you can see that I've changed the base
class for this view object component to use the
demo.fwkext.MyCustomViewObjectImpl class instead of the default
base class. If you visit the "Properties" panel of the view
object editor, you can see where I've defined the custom
property to make the conditional behavior "kick in" for this
view object. Other view objects that extend our customized
framework base class for view objects would continue to get the
default behavior unless they also define that property.
| | 42. | Enabling SQL Trace in Your Application Module to Get Query Tuning Statistics
This is the example that goes with the Verifying
Effectiveness of View Object Fetch Size Using SQL Trace
article. It illustrates how to enable SQL Trace in the
afterConnect() method of your application module if you don't
fancy turning it on for your entire database instance.
| | 41. | Example of Using Customized ADF Binding Class in a ADF/Struts Web Application
This example illustrates the minimal details necessary to get
the ADF binding layer to use a customized ADF binding
implementation class at runtime, in the context of a web
application. The steps would be the same for an ADF JClient
application or other use case, the only thing that might change
is the place you register you custom binding definition factory
with the JUMetaObjectManager. In the example, the
MyADFBindingFilter extends the base ADFBindingFilter and calls
JUMetaObjectManager.setControlDefFactory() to register a custom
control binding definition
factory. MyCustomBindingDefFactoryImpl extends the default
JUBindingDefFactoryImpl and overrides the createControlDef()
method to return a different binding definition class for one of
the subtypes of bindings. In this case, I've chosen to provide a
customized binding class the the binding subtype
"DCTextField". MyCtrlAttrsDef extends the default JUCtrlAttrsDef
and overrides the createControlBindingInstance() method to
return a new instance of my customized MyCtrlAttrsBinding
instead of the default. And finally, that MyCtrlAttrsBinding
extends the default JUCtrlAttrsBinding object and overrides the
setInputValue() method to print out a custom message to system
output to allow you to see at runtime that the custom binding is
getting used.
| | 40. | Simple UIX Pages Showing Two Techniques to Cause Query to Be Re-Executed to Refresh Data
After writing the Why
Isn't Refreshing the Browser Page Enough to Refresh the Data
Displayed? article, this workspace illustrates two of the
techniques described thereinusing two different ADF datapages
showing the DEPT table in a UIX page. One overrides the
prepareModel() method to force the underlying view object query
to be re-executed on each page render. The other illustrates
how to offer the user a (Refresh Data) button that let's them
refresh the data by re-executing the query on-demand. The
latter uses an onRefreshData() method in the related data action
class to re-execute the query.
| | 39. | Simple JClient Panel Binding to JavaBean DataControl Method Returning Array of Order Beans
This demo illustrates is asimple example of a hand-written
CustomerService JavaBean data control that has a single method
public Order[] findAllOrdersByCustomer(Customer c). I'm
just simulating the data by constructing it inside the service
method. To create the panel, I dropped a button and a text field
onto a JPanel in the BorderLayout-North position of the main
panel, then added a JScrollPane into the BorderLayout-center
position. Finally, I expanded the "Operations" node in the data
control palette, expanded the findAllOrdersByCustomer method to
see the "return" node, and then dropped a table for it into the
JScrollPane. I added one line of code to initially bind the
method result iterator rowset to null, which allowed me to avoid
invoking the service method when the panel is initially
displayed. Typing in values of "1" and "2" into the field and
pressing (Go) cause different orders to show in the grid.
| | 38. | Set Fixed JDBC URL Connection to Custom Value from Alternative Source
This example is a twist on the DynamicCredentials example above,
simplified to contain only the essential ingredients to provide
the JDBC URL connection information (username, password, JDBC
URL) from an alternative source than the information in the
bc4j.xcfg file. The example hard-codes the information inside
the CustomJDBCURLInfoProvider class. You could modify this
example to read the information from some alternative source
like a properties file, system parameters, or other location to
meet your needs.
| | 37. | Console Program Example of Using ADF Data Binding Layer
This simple TestClient.java program illustrates how to use the
ADF data binding layer from a simple Java console program. It
shows working through the same API's with both a JavaBean-based
data control and an ADF ApplicationModule data control. NOTE: If you
try to open this project in JDeveloper 10.1.3, you will need to
double-click on the TestClientUIModel.xml file to open
it in the code editor before it will get migrated to the 10.1.3
format correctly.
| | 36. | Composite Entity Using Stored Procedure API to Create/Modify/Remove Master and Children
This example includes a InstallTablesAndPackages.sql script to
create the DEPT and EMP tables, along with a DEPT_SERVICE
package that features a three-procedure API: add_dept(),
update_dept(), and remove_dept(). The PL/SQL API accept an
instance of the DEPT_T object type which contains a nested EMPS
attribute of type EMP_T_LIST (which is a TABLE OF EMP_T
type). The procedure handles inserting, updating, and deleting
all dept and related-emp information. We're using DEPT and EMP
here to represent two strongly-related tables which in the ADF
layer are represented as two composed entity objects. The
overridden doDML() method on DeptImpl illustrates how to have
the DeptImpl handle the DML for both Dept and any modified
children entities. The example tries to build on a common
pattern where the view objects and entity select are
accomplished against database views, while the entity object DML
operations happen against the simple PL/SQL API. Both the
Dept.Deptno and the Emp.Empno attributes are populated from DB
triggers from a sequence, so the example code illustrates also
how to simulate the refresh-after-insert behavior that the
framework would normally perform on your behalf
| | 35. | JDev 9.0.4 JSP DataTags Example Showing Attribute in Search but Not in Results
This example slightly alters the DataTableComponent.jsp for the
default <jsp:DataTable> tag to addin an "if" blockto allow
developer-picked view object attributes to be hidden in
theresult display table. It skips over displaying the view
object attribute if the custom BC4J attribute property named
HideInTable is set on that attribute.
| | 34. | Conditionally Refreshing Associated Entities via Accessors, Driven by Component Metadata
This sample illustrates some generic framework extension code to
customize how the Entity object works so that associated
entities can be conditionally refreshed from the database. By
default, accessingassociated entities using entity accessor
attributes will fetch the entity into the entity cache if not
there already, but subsequently use the cache to satisfy the
attribute access. This technique illustrate how you can use
custom entity object metadata properties to annotate particular
entity object accessor attributes where you want to eagerly
refresh the value of the associated entity (or entity rowset, in
the case of a 1-to-many association) whenever its accessed. A
key design principal of the ADF Business Components layer of
Oracle ADF is that it uses the database as its shared cache
between different user's work. Each root application module
instance has its own related transaction where local data is
read and cached before any changes get committed, but within the
span of a single transaction if user 1 has read and cached an
entity object while simultaneously user 2 has read, updated, and
committed a change to that same entity, user 1 will continue to
"see" the object as it is in his cache. Selectively performing
this eager refreshing of certain key entities can insure that
business logic written using entity accessor attributes will
always see the latest changes made by any user session during
its current transaction. Notice the overridden
getAttributeInternal() method in the MyEntityImpl class, and the
custom metadta properties on the Dept and Emp entities in the
sample. Launch two separate Business Components tester instance
to simulate two parallel user transactions, and try updating the
value of a Dept.Dname to "XXX" in one tester and committing it,
then seeing that the Emp-level business rule fails
validation. Conversely, try updating an Emp.Ename to "XXX" in
one tester instance and committing it, then seeing that the
Dept-level business rule values validation.
| | 33. | Creating ViewLinks Between ViewObject Instance in Different Application Modules at Runtime
This sample illustrates some generic code in the
ExtendedApplicationModuleImpl class in the project which
introspects custom property metadata to create view link
instances between a master view objectinstance in the current
application moduleand a detail view object instance that can be
in the current module or any nested application module
instance. Using this to create view link instances between view
object instance in the same application modules is not that
interesting since you can set those up at design time using the
application module editor. However, creating view links between
a view object in the current AM and another VO instance in a
nested AM cannot be done at design time or by hand-editing the
XML. It needs to be done in code. See the custom properties of
the DeptModule AM in the example for the information that the
generic code is leveraging to setup the runtime viewlink.
| | 32. | JDev 9.0.3/9.0.4 BC4J/JSP Request Processor to Show Error Page for Down Database
This sample is a JDeveloper 9.0.4.1 project with a simple JSP
using the BC4J <jbo:*> tag library to show department
information. It contains a custom Struts request processor
class, test.MyRequestProcessor, which extends the
BC4JRequestProcessor used in 9.0.3 and 9.0.4 BC4J/Struts
applications to properly handle the case when the database is
down, so that a declaratively-configured struts global exception
mapping can forward control to a "DatabaseIsDown.jsp" page. It
relies on a custom subclass of the BC4JRequestProcessor to catch
the ApplicationPoolException raised earlier in the Struts
request processor lifecycle, and then later in the lifecycle
throw the exception as part of the processActionPerform() step,
so that Struts' declarative exception handling will work as
expected.
| | 31. | JClient JTable Using Range Paging Mode
The Range
Paging mode offers developers an alternative strategy for
paging through large numbers of database rows in a view
object. Using this mode, only the current page of rows is
queried from the database and kept in memory. This simple demo
illustrates a basic JClient form containing an
PanelEmployeesView that contains a databound JTable that shows
the Employee data from the HR schema. Note that the line in the
PanelEmployeesView.java's jbInit() method that calls
tableEmployeesView1.setModel() has been moved to the end of the
method to make sure that executes after the JTable has been
added to its JScrollPane. In this way, the automatic calculation
of the range size will work as expected, based on how many rows
the user can see in the table. The RANGE_PAGING_AUTO_POST mode
is set on the view object instance in the AppModuleImpl.java
class's overridden prepareSession(...) method. This variant of
the RANGE_PAGING mode allows the combination ofquerying,
viewing, scrolling, and updatingthe visible rows a page at a
time, as well asmaking inserts and deletes to them (which change
the rows in the current visible range).
| | 30. | Looking Up Referenced Deptno Given Only the Referenced Dname
This example contains an EmpView that joins editable information
related to an Emp entity object, and reference information
related to aDept entity object. It illustrates the overrides
necessary to permit a user to type in the Dname of the related
department and to have the application lookup that department by
name and set the appropriate department foreign key attribute
automatically. The TestClient.java program exercises the EmpView
view object by "feeding" it an XML message containing a value
for Empno, Ename, and Dname, then illustrates that the readXML()
API can be used either to create a new row or update an existing
row. Finally, it uses the writeXML() API to print out the XML
for that new row and show how the related department information
like the "Loc" value has been looked up by the built-in ADF view
object reference mechanism. See the DeptDefImpl.java class for
an example of a custom entity definition class that provides
alternative lookup methods to the built-in
findByPrimaryKey(). The overridden EmpViewRowImpl.java class
uses this lookup method in its setDname() attribute to perform
the lookup necessary.
| | 29. | Creating a Dynamic Attribute Binding for a Dynamic View Object Attribute
You can programmatically add dynamic attributes to a ViewObject
with the addDynamicAttribute() API. This small sample
illustrateshow to create an attributecontrol binding at runtime
for your dynamically created View Object attribute. The
TestPage illustrates a JSTL-based read-only table, based
onhaving dropped a "Read-Only Dynamic Table" from the data
control palette. The dynamic table binding figures out its
attributes at runtime, so it picks up the"Foo" attribute that is
added by the addDynamicAttribute("Foo") call in the
DeptViewImpl.java file's create() method. The TestPageAction
class in the ViewController project illustrates how to
programmatically add an attribute binding for thedynamic "Foo"
attribute if it's not already there. The TestPage.jsp uses this
binding to allowthe user to enter a value for Foo for anyrow in
the Dept table.
| | 28. | Custom DateRange Validation Rule Bean with Custom Design Time Editor
Did you know that you can extend the set of built-in,
declarative validation rules by writing your own? Sure you can!
This example project illustrates an example DateRangeRule
validator bean that validates that a starting date attributes
comes before an ending date attribute. It also illustrates how
you can define a custom JavaBean Customizer panel to provide a
custom editing experience for downstream users of your validator
bean in the ADF Business Components design time. The
DateRangeRule validator bean is linked to its custom
DateRangeRuleCustomizer via the
DateRangeRuleBeanInfo class. This is a standard JavaBeans
programming technique. The project contains two deployment
profiles: one produces a runtime JAR file with only the
DateRangeRule, the other produces a design time JAR file with
the BeanInfo and the Customizer for the rule. To use the date
validation rule in any Business Components project, just add a
library for these two JAR files, then visit the "Registered
Rules" panel under the "Business Components" section of the
project properties to (Add...) this test.rules.DateRangeRule as
one of the rules you want to use, andgive it the name
"DateRange"Once you've done that, the DateRange validator will
appear in the list for you to add to your entity objects on the
"Validation" panel of the Entity Object editor. The custom
editor panel allows you to pick the Start Date Attribute and the
End Date Attribute from the list of date-type attributes in your
entity object.
| | 27. | Serving a Filtered View Object Result as a Comma-Separated Values (CSV) File
This example illustrates a JSP page allowing the user to filter
the employee list using the ADF view object's built-in Query by
Example functionality (leveraging one of the techniques
described in my Creating
Search Pages with Both Fixed and Dynamic Criteria article on
OTN), and offers a button to download the set of employees as
currently filtered by the user as an Employees.csv
file. Notice that the BrowseEmployees and the EmployeesAsCSV
data actions are sharing a UIModel (not strictly necessary, but
wanted to illustrate that it's possible). The UI model contains
three iterator bindings over the EmpView1 view object
instance. The FindEmpView1Iterator is forced into find
mode by theline of code in the overridden prepareModel() method
of the BrowseEmployeesAction.javaand is used by the find fields
at the top of the page. The EmpView1Iterator is set to
have a range size of 5 and is used by the table display to show
5 employees at a time. The EmpView1 table bindingrelated to this
iterator only includes the Empo, Ename, Sal, and Deptno
attributes as shown in the table.The CSVEmpView1Iterator
is set to have a range size of -1 (to iterate all rows) and has
a related table binding that includes all the attributes. The
EmployeesAsCSV.jsp page illustrates how to render a CSV result
with a developer-determined file name that will appear in the
browsers "Save As.../Open With..." dialog.
| | 26. | Releasing an Application Module in Reserved Mode
This small example application illustrates the one line of code
necessary to indicate that your application module should be
released to the AM pool in reserved mode (described more in this
OTN whitepaper). This mode is not generally recommended --
we recommend using the default managed state release mode -- but
since customers sometimes ask about reserved mode for upward
compatibility, the TestPageAction.java class in this example
illustrates how to do it. If you run in debug mode, you'll
notice that the passivateState() and
activateState() methods in the HRModuleImpl class
are never called since passivation and activation is not
relevant to an application module used in reserved mode.
| | 25. | Programmatic Use of Application Module Pooling API 2005, Upd: 02-MAY-2007
This is a JDeveloper 10.1.3.2 update of the TestPoolServlet
example that used to ship with JDeveloper 9.0.4 and before. It
illustrate how to make correct, programmatic use of the
Application Module Pool in your own code if necessary, and how
to dump AM pool statistics programmatically.
| | 24. | Passing User-Entered Data in 'Non Database Block Fields' to Stored Procedure/Function
This example presents a very simple JClient panel that allows
the user to type into three "dummy fields" and contains two
different buttons that are bound to data control methods. Both
of these data control methods are implemented in the
ExampleModuleImpl class. It required no user coding on the
client to implement. The "non database block" view object was
created using the view object wizard, selecting the "Rows
Populated Programmatically, not Based on a Query" radio group on
Step 1 of the wizard (this choice is new in 10.1.2). Then I
added the transient attributes, defining their name, type, and
marking them to be updateable = always. The form was thencreated
using the ADF/JClient Panel Wizard, then the buttons were added
by dropping data control methods as buttons onto the panel. The
action bindings created to bind the buttons to the data control
methods have their "Requires Update Model" property set to
true. One of the data control methods invokes a stored
procedure, passing the user-entered values, and the other method
invokes a stored function, setting the function return value
into another "dummy field". This example illustrates several
interesting ideas. One is using a view object with only
transient attributes as what Oracle Forms users might think of
as a "Non-Database Block". There is a custom framework extension
class CustomAppModuleImpl.java that illustrates a simple
example of how to write generic framework code (like insuring
that a blank row exists in a "non-database block" view object)
based on whether or not a custom ViewObject property named
InsureEmptyRow is present or not. The NonDBBlock
view object in the sample contains such a custom property to
cause the generic functionality inherited from
CustomAppModuleImpl to kick in. The
CustomAppModuleImpl.java also contains some generic helper code
to simplify invoking stored procedures and functions that have
bind variables.
| | 23. | SmartPanel Prototype Demo
A customer asked me a few years ago to demonstrate how they
could define databound JClient panels using simple XML files as
a way to "design" the screens instead of designing them one by
one in the visual designer. I defined an XML Schema called
SmartPanel.xsd with a simple XML vocabulary of tags for
defining a data-bound panel with an HTML-table style layout, as
well as a few simple component types represented by tags named
input, label, display, poplist. The
SmartPanels project in the workspace contains the base
SmartPanel class, which the EmpPanel class in the
SmartTest project extends. The SmartPanel uses
theSmartBuilder classwhich implements a SAX filter to
dynamically build up the JClient binding objects based on the
XML elements found in the panel definitionfile, as well as the
Swing panel controls that are bound to them.The
EmpPanel.pnl file in the SmartTest project defines
the XML definition of the EmpPanel panel. If you visit
the Tools | Preferences... and go to the XML Schema tab, you can
add the SmartPanel.xsd file to the list of schemas your IDE is
aware of, and relate it to the .pnl file extension. Then
you can see how JDeveloper provides in-context,
XML-Schema-driven code-insight for the custom XML vocabulary
used to define the panels. Try commenting out the line in
EmpPanel.java that sets the local to "US" and uncomment
the line that sets the locale to Italian, then re-run. You'll
see all the prompts show up in Italian. If you select a new
department from the poplist, or select a new manager from the
poplist, you'll notice how the ADF Business Components reference
mechanism automatically refreshes the related information in the
panel to show the related new department name, and/or new
managers salary. It also causes the recalculation of the
calculated attribute showing the current employees salary as a
percentage of his/her managers salary. Also interesting is the
declarative attribute recalculation going on in the
EmpView view object. It extends a custom framework base
class named DeclarativeRecalculatingViewObjectImpl, and
the EmpView indicates a custom property named Recalc_Mgr
with a value of SalaryPercentageOfManager. This
declaratively causes the SalaryPercentageOfManager
attribute to get recalculated whenever the value of the Mgr
attribute gets changed, without having to writecustom Java code
in the EmpViewImpl class to handle
that. NOTE: I originally developed this example
in JDeveloper 9.0.3 and have not upgraded it to use any new ADF
binding features, but since we support upward compatibility for
9.0.3 JClient, it worked in 10.1.2 without any changes.
| | 22. | Getting the Formatted Version of an Attribute's Value
This small example contains one EmpView view object whose
Sal attribute has an associated format mask of
$0000.00. To see the format mask visit the view object
wizard, click on the Sal attribute, then see the "Control Hints"
tab in the editor. The Test.java class in the project
shows how to access the AttributeHints object associated
with any attribute definition,by calling getUIHelper() on it,and
call its getFormattedAttribute() method to get the
formatted value.
| | 21. | JTable of Emp Rows With In-Place JComboBox Showing Department Names
This example illustrates how to show the user a JTable with a
join of information from the EMP and DEPT tables, allowing the
user to click on the department name (e.g. RESEARCH) in the grid
and get an in-cell JComboBox for selecting anotherdepartmentby
name. There are three things going on in this demo of
interest. First, is that the EmpView view object includes the
Dept EO usage by reference, so that when the Emp.Deptno foreign
key attribute value is changed, the referenced department gets
automatically looked-up and changed accordingly. Secondly, the
demo does not display the Emp.Deptno attribute or the
Dept.Deptno attribute (named WorksInDeptno in the view), but
only the Dname attribute. Thirdly, the JTable used in the
PanelEmployees uses an on-the-fly override of the
editingStopped() and prepareEditor() methods.
| | 20. | Using JSTL to Refer to Value of Field in Following Row for Conditional Formatting
This example contains a single TestPage.jsp that shows a
pageable table of EMP table rows. It illustrates how to use the
varStatus attribute of the <c:forEach> tag
to refer to the loop index, and then use this as an array offset
into the array of rows in the current range to make a comparison
between the current row's Deptno value and the Deptno value of
the next row. In this case, if the values are different, it
formats the cells of the HTML table to have a CSS border along
their bottom edge to create a visual separation on the page.
| | 19. | Using a Transient Boolean Flag on a View Object to Mark and Filter Selected Rows
The EmployeeList view object in this example is an expert-mode
view object with no related entity. I've added a transient,
Boolean-valued Selected attribute and written some encapsulated
methods in the EmployeeListImpl.java class to support marking
the selected attribute for a row by employee number. The data
action event handling methods invoke custom application module
methods to process the checked checkboxes. The SelectedEmployees
page has an iterator binding based on the custom application
module method getSelectedEmployees() which internally uses the
getFilteredRows() API to return the subset of rows in the view
object's rowset which have their Selected attribute set to true.
| | 18. | Posting Multi-LevelXML Data Over HTTP to ADF Business Components
Run the XMLPosting project (requires using IE browser for XML
HTTP Posting functionality in the browser page for now). You can
edit the XML message that will be posted to the server for
handling by your ADF Application Module. It illustrates that you
can post any number of departments and employees in the XML
message. Those that are new will be inserted. Those theat are
existing will be updated. If you add a Status="Terminated"
attribute to an <Employee> element, it will get
deleted. Try updating an emp to have a salary lower than 100,
the business logic encapsulated in the entity objects is
triggered and errors are returned in an XML message for display
by the client. Try entering a salary that is more than 1000
times the length of the employee's name. This triggers an
example of an object-level validation rule that involved
multiple attributes in the rule. Try adjusting salaries of one
or more emps in a department such that the sum of their salaries
exceed 11,000. This triggers the failure of a more complex
validation rule. The demo also illustrates how, via inbound and
outbound XSLT transformation (supported in the ADF readXML() and
writeXML() API), the external XML format can be transformed from
anything into the canonical XML format that ADF Business
Compoments expects on the inbound, and vice versa on the output.
| | 17. | Deleting an Employee with Confirmation in a Web Application
It uses just two data pages and leverages the built-in
event-handling features of ADF described in the ADF
Data Binding Primer and ADF/Struts Overview. The pages use
the post-back pattern to handle their own events before
forwarding. You also might want to look at the web log article I
wrote on different
techniques for invoking multiple actions (as it happens,
related to Delete, but not specific to Delete). Things to notice
about the example: The "confirmDelete" action binding in the
employeeList page's binding container is mapped to the
setCurrentRowWithKey action so that it automatically fires when
the "confirmDelete" event is triggered. The "confirmDelete"
forward is then automatically selected to navigate to the
confirmation page. If you click the "Confirm Delete" link on the
confirmation page, then the onConfirmDelete method in the
EmployeeDeleteConfirmAction class fires, and then it executes
the delete, followed by a commit.
| | 16. | Deleting Multiple Employees Based on Selected Checkboxes
This exampleshows how to write a JSP page that proposes a
checkbox next to every employees name, and allows the user to
tick any number of checkboxes to delete all of those employees
when the (Delete) button is pressed. Key logic happens in the
application module method deleteMultipleEmpsByEmpno() which
accepts a String[] parameter of Empnos so we can directly pass
theString[]of selected checkbox Empno values from the web
container to the application module method. The data action
event handler onDeleteMultiple in the DeleteMultipleEmpsAction
class invokes the custom AM method.
| | 15. | Model One JSP Checkbox Example
This example illustrates a simple JSP page with no Struts
controller in the mix displaying a couple of checkboxes, and the
overridden updateModel() method in a custom lifecycle class to
customize the handling for the "unchecked" value of a checkbox.
| | 14. | Dynamic JDBC Credentials for Model 1 and Model 2 [10.1.3.3] 2006, Upd: 17-MAY-2007
After reading the OTN article How
To Support Dynamic JDBC Credentials, several customers asked
whether the same techniques will work outside of a Struts
context. The ADF related code to support dynamic credentials is
not dependent on Struts, but a tiny bit of the example code
referenced a "main.do" in a place that made it only work for
Struts. This example app illustrates the technique can work with
both Model 1 or Model 2, including both JSP/Struts and JSF. The
web.xml file for each ViewController project contains a context
parameter that define the login page to redirect to for that
particular web application. The JSF project contains a second
context parameter FacesURLPattern as well. Due to Bug#
5080057, setting the
jbo.ampool.sessioncookiefactoryclass property in the
configuration is not correctly saved to the bc4j.xcfg
file. So, in order to configure a custom session cookie factory
class as required to repurpose the code in this example in your
own projects, you'll need to hand-edit the bc4j.xcfg
file to insert the child element
<jbo.ampool.sessioncookiefactoryclass>test.DynamicJDBCSessionCookieFactory</jbo.ampool.sessioncookiefactoryclass>
inside the appropriate <AppModuleConfig> element for
the configuration in question. (NOTE: The version of this
workspace that works for JDeveloper 9.0.5 and 10.1.2 is still
available here).
| | 13. | Entity Object Based on View With Instead Of Triggers Avoiding Returning Into Clause
Illustrates the one-line of code needed in a custom entity
definition object to indicate to the ADF framework that you
don't want a particular entity object to use the RETURNING
INTO clause when it tries to refresh-on-insert or
refresh-on-update. The RETURNING INTO clause throws
database-level errors when used in some kinds of database views
having INSTEAD OF triggers. Also shows that you need at least
one attribute in the entity other than the rowid marked as
"Unique" to make the insert situation work correctly.
| | 12. | Forcing an Iterator Over a Generic Bean Collection to Be Refreshed
When working with the ADF Business Components data control, the
view objects and entity objects have event notification in place
that the ADF Business Components implementation of the ADF row
set iterator responds intelligently to. So, ADF iterators
working with ADF Business Components-based back-ends are always
up to date with changes made to the collections. If you are
working instead with data binding against simple Java classes
and do something in your code to update a
Collection-valued property, you need to manually
trigger the rebuild of the iterator. This sample illustrates the
line of code required to do that in the
ResultsAction.java custom data action class.
| | 11. | Using ViewObject writeXML and JSTL XML Tag Library
Illustrates how to use the ViewObject writeXML() method
to produce a multi-level XML message for an HR schema-based data
model having Departments -> EmployeesInDepartment ->
DirectReports->DirectReportJobHistory with a second detail
collection under Departments of Deparments ->
EmployeesJobHistory. This XML document is then set as a request
attribute so that the JSTL XML library can render the
multi-level information using XPath expressions. The sample
contains both Struts and Model 1 examples (requires the HR
schema).
| | 10. | ViewRow and EntityObject Polymorphism
Demonstrates the different levels of polymorphic query support
that we have in ADF Business Components. The TestClient
example uses an instance of a "People" VO but illustrates that
the client can cast "MenRow" rows to the MenRow interface
supporting a getManAttr(), and "WomenRow" rows can be
cast to a WomenRow interface to access a
getWomanAttr() method that is specific to women. ADF
Business Components supports two distinct kinds of polymorphism:
ViewRow polymorphism (which you setup at the application module
level) and EntityObject polymorphism (which you setup
on an individual VO). This example shows both kinds of
polymorphism at work, but they can be used independently.
| | 9. | Dynamically Binding to Dynamically Created View Object
Shows a "Tiny SQL*Plus"-like example allowing the user to type
in any SQL statement into a web page, and the implementation
illustrates how to programmatically construct binding objects in
order to render the results from this dynamically created view
object.
| | 8. | Call Stored Procedure From a DataAction or JClient Button
Shows the best practice technique for invoking a database stored
procedure encapsulated behind a custom
ApplicationModule method. Includes examples for
invoking it both from an ADF DataAction (in the
ViewController project) as well as a JClient button event
handler method (in the SwingClient project).
| | 7. | Router Data Action
Shows a generic, and simple, customization of the basic ADF
DataForwardAction to automatically use the
String-based result of a declaratively-invoked business
service method as the name of the Struts forward to use for
"next page" navigation.
| | 6. | Read XML Example
Simple command-line utilities that illustrates how to use the
ViewObject's readXML/writeXML API's. By
passing appropriate command line arguments, it will dump the XML
for a view object to a file, or read in an XML file and "ingest"
the contents in the file and apply inserts, updates, and deletes
(and engaging entity-object level business validation) as
appropriate.
| | 5. | Master/Detail/Detail/Detail
Illustrates a four-level master/detail/detail/detail data model
based on the HR schema (Regions -> Countries -> Locations
-> Departments) allowing the user to "Drill Down" from one
level to the next across four different web pages.
| | 4. | Deferred ViewLinks for Non Visible Panels
A JClient example illustrating how you can use API's on
ViewObject to dynamically "unwire" and "rewire" active view link
coordination to allow for smarter suppression of master/detail
view link coordination when you know (as the designer of the
GUI) that the details are not currently visible by the user.
| | 3. | Upload Text File and Image Example
Illustrates a simple, no-code-required example of how to support
file upload in a JSP page and save both text documents and
images into the database. Relies on using the Oracle Intermedia
database datatype ORDSYS.ORDDOC and
ORDSYS.ORDIMAGE and their corresponding ADF Business
Components domains that do the right thing to handle working
with them.
| | 2. | One Page Deferred Query Example
Shows how to use setMaxFetchSize(0) to prevent a view
object from executing before the page has a chance to capture a
bind variable value from the end-user.
| | 1. | Array of String Domain Example [10.1.3.1]
Illustrates binding an array of strings as the value of a view
object WHERE clause bind variable, leveraging the
Oracle database's CAST AS operator to achieve a
variable number of values in a SQL IN clause by
treating the values in the array as a nested table. Run the
CreateTableOfVarcharType.sql script before running the
example, which features example of using view objects with both
the Oracle Positional and Oracle Named bind variable styles. The
latter includes a workaround in the
EmpViewWithNamedBindingStyleImpl class' overridden
create() for Bug 5849504, where the view object editor
fails to correctly test the syntax of the SQL statement
involving an array-valued named bind variable and the
TABLE and CAST AS clauses.
|
|