This project contains an historical set of code samples relating to various versions of the Oracle Application Development Framework (ADF). Many of these samples where previously hosted on Java.net and will relate to various versions of ADF.
This repository is laid out with each sample expanded in it's own subdirectory under the root /src directory. This allows you to browse the code without downloading. Each sample is also available as a downloadable zip from the releases area
- 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; andDynamicCredentialsRichFaces.jws
uses the new ADF Faces Rich Client components that are new in 11g. Each project references the sameModel
project andFwkExtensions
project. The generic framework extension classes involved in implementing the solution live in theFwkExtensions
project. TheModel
project contains the simple ADFBC components used in the example: aTestModule
application module with a singleDeptView
VO instance of aDeptView
view object based on theDEPT
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 newErrorHandlerClass
attribute on the root<Application>
element of theDataBindings.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 theDMLException
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 aMETA-INF/adf-settings.xml
file in each client web project. Each project registers thetest.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 parameterFacesURLPattern
as well. Due to Bug# 5080057, setting thejbo.ampool.sessioncookiefactoryclass
property in the configuration is not correctly saved to thebc4j.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 thebc4j.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.
- 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:
- 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!
- 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.
- 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 theBrowseEmployees
backing bean is configured as theReturnListener
for the button. It calls arefreshCurrentPage()
helper method to accomplish the page refresh. It works in combination with setting thepartialSubmit
property and theuseWindow
properties totrue
on the (Add New Employee) button in the page. TheonSaveNewEmployee()
method is required for theActionListener
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.
- 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
- 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 JSFFacesMessage
in case theEmployeesResultsIterator
returns either no rows or too many rows (with the limit hard-coded for this example to 10). TheSearchPage
backing bean inherits from theBackingBeanBase
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). Therendered
attribute on theaf:table
showing the search results in theSearchPage.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).
- This example illustrates a
- ADFBC Application With No Database Connection [11.1.1.1, SCOTT schema] 01-SEP-2009
- This example illustrates a technique for creating an application module that does not use a database connection. The only reason you might want to do this is that you are exclusively using programmatic view objects and entity objects, which might be an infrequent scenario, but does come up from time to time. The example illustrates a number of lesser-used framework extension classes. The
NoDatabaseApplicationPoolImpl
is a custom application module pool implementation class. TheNonDatabaseConnectionStrategy
is a custom connection strategy class . TheCustomSessionImpl
is a custom session class, which returns a custom transaction handler factory. TheCustomTxnHandlerFactoryImpl
is a custom transaction handler factory used to return an instance of the customCustomTxnHandlerImpl
class, which is a custom transaction handler implementation. TheSessionClass
configuration property is set to the name of the custom session implementation class, which in turn bootstraps the custom transaction handler factory and custom transaction handler. ThePoolClassName
configuration property is set to the name of the custom application module pool implementation class. This class overrides theisSupportsPassivation()
method to return false, indicating to the runtime that this particular application module pool does not support passivation. Thejbo.ampool.connectionstrategyclass
configuration property is set to the name of the custom connection strategy class which overrides thecreateApplicationModule()
method to set some key properties in the environment hashmap before calling super. TheStaticVO
is a static view object that returns rows whose data is in theModelBundle.properties
file.
- This example illustrates a technique for creating an application module that does not use a database connection. The only reason you might want to do this is that you are exclusively using programmatic view objects and entity objects, which might be an infrequent scenario, but does come up from time to time. The example illustrates a number of lesser-used framework extension classes. The
- 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.
- ADFDetectWindowResize
- 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 namedconvertNumberMessageDetail
. In order to reference a resource bundle message, normally you would expect to be able to use anf: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 withloadBundle
are only available during the page rendering phase, but not during the validation phase. So, in order to drive theconvertNumberMessageDetail
from a message bundle, I needed to borrow some of the code from the JSF reference implementation'sloadBundleTag
class that exposes a resource bundle as a Map, and I put it in theAppliationMessageMap
managed bean class in this example. I've configured that to be a session-scoped managed bean and configured itsbasename
managed property to have the valueview.resources.JSFMessages
infaces-config.xml
. This allows me to reference my custom error message for "Field 2" in the demo, in itsf:convertNumber
tag'sconvertNumberMessageDetail
attribute using the EL expressionAppMessages.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.
- The
- ADFJSFSuccessFinished
- ADFJSFSuccessStart
- 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.
- ADFLoggingTemplates
- ADFMobileBrowsingThroughSwiping
- ADFMobileErrorHandling
- ADFMobileLocalDatabase
- ADFMobileRowCurrrency
- Passing Multiple Selected Keys from Tree, Table, and TreeTable to Application Module Method [11.1.1.6.0] 07-NOV-2008, Upd: 02-NOV-2011
- 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 theprocessSelectedEmployees()
andprocessSelectedDepartments()
methods are exposed on the client interface so they are available for declarative data binding in the data control palette. Notice they these accept ajava.util.Set
(which we expect at runtime to containoracle.jbo.Key
objects. The reason we're not using Java generics likeSet<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 aKey
and then using thefindByKey()
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 demoview1.jspx
andview2.jspx
. Start by looking at theview2.jspx
page, which includes a table ofDeptView
rows from the view object instance namedDepartments
. Importantly, notice that to enable the multi-select on the table three required steps have been taken: (1) TherowSelection
attribute is set to "multiple
", (2) theselectedRowKeys
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 customprocessSelectedDepartments
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. TheView2
backing bean is defined inadfc-config.xml
and rather than using a specific backing bean class for the View2 page, its using the generic helper classMultiSelectSupportBackingBean
. That bean conveniently contains a property namedmyTable
of typeRichTable
which is designed to be referenced by thebinding
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 thebinding
property of theaf:table
component in theview2.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 theselectedAdfRowKeys
Map-valued property of the backing bean, passing theView2.myTable
instance of the RichTable on that page as the map key. As you can see in theMultiSelectSupportBackingBean
class, theselectedAdfRowKeys
is an anonymous subclass ofjava.util.Hashmap
that overrides theget()
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. Theview1.jspx
page shows the same genericMultiSelectSupportBackingBean
class in use as the page'sView1
backing bean, and three different instances of method action bindings in the page definition forview1.jspx
are used to invoke theprocessSelectedEmployees()
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 theEmployeeHierarchy
view object instance in the data model is setup. Notice that theEmpView
view object defines a view criteria namedEmployeesWithNoManager
that finds employees that have aMgr
attribute equal to null. TheEmployeeHierarchy
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 theEmployeesWithNoManager
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 thetest.model.links.Manages
view link betweenEmpView
and itself, based on theEmpno->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 theDirectReports
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.
- 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
- ADFToyStoreJSF
- 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 Applicationof 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. ItsModel
project contains atest.Dept
entity object,test.DeptView
view object, and atest.AppModule
application module containing an instanceDeptView1
oftest.DeptView
. ItsViewController
project contains aDepartments.jspx
page with the data entry form. TheModel
project contains a ADFBC deployment profile to deploy the ADFBC components as a simple java archive. TheExtendsAndSubstitutes
workspace contains aExtendsProject
project which has imported thetest.Dept
entity from the simple ADFBC JAR archive created in the other workspace'sModel
project. It then has created an extended entity objectextendsproject.DeptEx
which extends thetest.Dept
entity, overrides itsLoc
attribute, and adds an attribute-level validator onLoc
to prevent the value from being the single, uppercase letter "X". TheExtendsProject.jpx
defines the component substitution metadata saying thatdept.Dept
should be substituted withextendsproject.DeptEx
. This metadata was defined using the Substitutions detail panel of the Business Components project properties. In addition, theExtends Project
contains a fileExtendsProject.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/>. TheExtendsProject
project contains another ADFBC deployment profile to deploy the extended components as a simple JAR archive file. Finally, theViewController
project adds the runtime Java VM argument in its Run/Debug profile of-DFactory-Substitution-List=ExtendsProject
to use theExtendsProject.jpx
file found in the classpath at runtime as the component substitution list. TheViewController
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 theDepartments.jspx
page and try to enter the value of "X" for theLoc
attribute of any row in theDeptView
view object's results and press (Commit). You'll see the validation error added by the substitutedextendsproject.DeptEx
component to know that the component substitutions are working.
- This example illustrates how to use the techniques outlined in section 25.10 Substituting Extended Components In a Delivered Applicationof the ADF Developer's Guide for Forms/4GL Developers to substitute extended components into a running application. The
- 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'sCAST AS
operator to achieve a variable number of values in a SQLIN
clause by treating the values in the array as a nested table. Run theCreateTableOfVarcharType.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 theEmpViewWithNamedBindingStyleImpl
class' overriddencreate()
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 theTABLE
andCAST AS
clauses.
- Illustrates binding an array of strings as the value of a view object
- Array of String Domain Example 11g
- 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 theSCORED_KEY
andSCORED_KEYS
types in the database. TheViewObjectImplWithScoredKeyBindVariable
framework extension class centralizes the code required to work with the bind variable of typeoracle.jbo.domain.Array
. In this case, its code is binding theSCORED_KEYS
type (which is aTABLE OF SCORED_KEY
) as an Array ofSCORED_KEY
types. Both theReadOnlyScoredEmployees
andEntityBasedScoredEmployees
view objects inherit this helper code from this class. ThesetScoredKeysArray()
method in the custom view object class of both view objects calls the helper methodnewScoredKeysArray()
in the superclass to create the Array of STRUCT and set the value of the view object's bind variable. It expects to receive aList
ofMap
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 theTestClient
class to see the results of joining in the static data with the EMP table.
- 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
- Using ViewAccessor to Perform Attribute-Level Validation [11.1.1.2] 11-JAN-2010
- This example illustrates two techniques to perform an attribute-level validation based on a view-accessor with a bind variable that needs to be bound to the value that is attempting to be set. For an entity-level validation, you can use a view accessor based list validator for this purpose. However, for the attribute-level use case - since you cannot refer to the
newValue
expression in the view accessor bind variable default Groovy expression - you need to either use a groovy expression validator, a Java method validator, or a custom validation rule. This workspace provides examples of the first and the last of these three options. The Java method validation alternative is left as an exercise to the reader. The Emp EO has two view accessors:CheckDivisibilityBy3
based on view object definitiontest.ValidationViewObject
, configured to have theVarModulo
value set to 3, andCheckDivisibilityBy7
based on the same view object, configured to have the VarModulo value set to 7 The attribute-level Groovy validator on theSal
attribute sets the value of theVarValue
bind variable on the view accessor, then executes the query. It returns value if the view accessor'sfirst()
function returns a non-null result (i.e. at least one row was found). The example also illustrates a more generic approach that doesn't rely on Groovy. I created a new, reusable validation rule calledAttrLevelViewAccessorValidator
. I've used an instance of it on theComm
attribute, declaratively configuring the validation rule beans two properties:attrNameToBindNewValueTo
= "VarValue" andviewAccessorName
= "CheckDivisibilityBy7". Run the AM in the tester, and verify that you must enter a Sal value that is divisible by 3 and a Comm value that is divisible by 7. Of course, the example view object would normally be a more interesting query with one or more bind variables going against a table other thanDUAL
, but this simple query hopefully will get the basic idea across. If the value being validated were the key attribute of the target view object, you could have used the "Key Exists" validator based on a view accessor instead. This approach is valid when the query you need to validate needs to lookup something that is not the key attribute in the target VO used for validation.
- This example illustrates two techniques to perform an attribute-level validation based on a view-accessor with a bind variable that needs to be bound to the value that is attempting to be set. For an entity-level validation, you can use a view accessor based list validator for this purpose. However, for the attribute-level use case - since you cannot refer to the
- 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, theGlobals
view object is a transient view object with no query, one updateable Number attribute namedDepartmentNumber
, and a max fetch size set to zero ("No Rows" setting on the "Tuning" panel). TheExampleModule
application module overrides the prepareSession() method to insure there is a blank row in the "Globals" view object instance. TheEmployees
view object has a named bind variableTheDeptno
that has a bind-variable-level custom metadata property namedVOAttributeReference
set to the valueGlobals.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, theCustomViewObjectImpl
's overriddenbindParametersForCollection()
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.
- This example illustrates a
- Conditionally Auto-Executing af:query Search Form Based on User Input [11.1.1.2] 31-DEC-2010
- This example illustrates how to conditionally trigger the automatic execution of an
<af:query>
component's search when certain conditions are true about the values the user has entered into the search form. Runview1.jspx
. After selecting a value forDname
andLoc
in the search form, the query is automatically executed without the user's having to press the (Search) button. TheView1Bean
is the backing bean for theview1.jspx
page in the example. The<af:query>
component'squeryOperationListener
property is set to an EL expression that "wires" it to fire theonQueryOperationPerformed
method in the backing bean. The backing bean's event handler code conditionally executes code if the query operation is a criterion update. It accesses the view criteria that is the model-layer object that is bound to the search form and peeks at the values in theDname
andLoc
view criteria items. If it notices that the user has filled in both criteria items, then it creates a newQueryEvent
and queue's it up for the same<af:query>
component on which the QueryOperationEvent is firing. To ensure that the search form renders theDname
andLoc
items in the search form with their autoSubmit property set to true, theautoSubmit
UI hint is set to true on bothDname
andLoc
attributes in theDeptView
view object.
- This example illustrates how to conditionally trigger the automatic execution of an
- 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 namedDeptViewNonEntityBased
which is a read-only, non-entity-based view object, and one namedTransientViewObject
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 thebeforeRollback()
andafterRollback()
method and commenting out the call tosuper
. For an entity-based view object, you need to override these two methods as well as call thesetClearCacheOnRollback()
method on theoracle.jbo.Transaction
interface, passingfalse
. 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 theTransientViewObject
is populated by theprepareSession()
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.
- 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
- 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.
- 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.
- BindingToDynamicViewObject
- 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.
- Binding SelectBooleanRadio to True/False Value in DB Row [11.1.1.5] 24-NOV-2011
- This example shows how to bind a "T"/"F" value to a data-driven set of selectOneRadio components. Run the
CreateTable.sql
script to create theDEPT_WITH_BOOLEAN
table, then runExample.jspx
. When you commit, the "T"/"F" value in theSELECTED
column in the table will reflect the change to the selected radio group button.
- This example shows how to bind a "T"/"F" value to a data-driven set of selectOneRadio components. Run the
- 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 aDepartments
view object instance of typeDeptView
. TheWorksInDeptLink
view link defines a view link accessor attribute namedEmpView
that is used by the tree binding to access the detail rowsets of employees for each department. TheDeptView
view object defines a custom method namedsetLowHighSalaryRangeForDetailEmployeesAccessorViewObject()
that is exposed on the view object's client interface. TheTestPage.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 theEmpView
. TheDeptViewImpl
class also contains an overriddencreateViewLinkAccessorRS()
method that applies the bind variable values to each view link accessor rowset created. Run theTestPage.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.
- This example illustrates a
- 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 namedAnotherInstanceOfQueryWithBindVarValue
(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 namedQueryWithBindVarValue1
of theEmpView
view object. This latter view accessor is used by the LOV definition on theEmpView
view object'sMgr
attribute. To try the application, run theSetUserMapValue.jspx
page, typeNameFilter
into thesetUserMapValue_key
field, and (for example) the letterS
into thesetUserMapValue_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 sameQueryWithBindVarValue
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 expressiontest.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.
- This example includes a
- Using a CheckBox in an Editable Table with Boolean/Button Binding [11.1.1.1, SCOTT schema] 13-JUL-2009
- This example illustrates how to use the button binding (also known as the boolean binding) in an ADF Table to declaratively handle data entry an attribute whose valid values are one of two choices representing true/false, on/off, yes/no, etc. The
CreateDeptWithFlagTable.sql
creates a variant of theDEPT
table namedDEPT_WITH_FLAG
that has one additionalFLAG
column whose valid values are "Y" or "N". TheDeptWithFlag
EO indicates a UI hint on itsFlag
attribute to indicate that it prefers to render as a "Checkbox". Dragging and dropping theDeptWithFlagView1
data collection from the data control palette as an "ADF Table", JDeveloper infers the correctselectBooleanCheckbox
control for theFlag
attribute. However, there is two additional (simple) steps required to make it work correctly in a table. First, using the overview editor for the pageDefinition, I created a new button binding named "Flag" for theFlag
attribute, indicating the values of "Y" for selected and "N" for unselected. With theview1PageDef
page definition as the active editor, I expanded theDeptWithFlagView1
tree binding, its nodeDefinition folder, and the AttrNames folder inside it to select theFlag
attribute of the tree binding node definition. Then, using the Property Inspector, I set the value of theBinds
property of thisFlag
attribute name element to "Flag" (without quotes), which references the name of the button binding created above.
- This example illustrates how to use the button binding (also known as the boolean binding) in an ADF Table to declaratively handle data entry an attribute whose valid values are one of two choices representing true/false, on/off, yes/no, etc. The
- 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 namedexample_pkg
used by the demo. This package contains a single proceduredo_something
which accepts a string parameter, number parameter, and date parameter and inserts these values into a new row in theEXAMPLE_PKG_TABLE
table. In the J2EE application, the stored procedure invocation is encapsulated inside the business service inside the custom application module methodcollectDataUsingStoredProcedure
. 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 theViewController
project was created by dragging thecollectDataUsingStoredProcedure
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 namedExamplePkgTable
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.
- The example illustrates how to create a JSF parameter form for calling a PL/SQL stored procedure. You'll need to run the supplied
- 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 ADFDataAction
(in the ViewController project) as well as a JClient button event handler method (in the SwingClient project).
- Shows the best practice technique for invoking a database stored procedure encapsulated behind a custom
- Reference View Object and View Row Methods from Groovy [11.1.1.1, SCOTT schema] 03-SEP-2009
- The
EmpView
view object in this example features two transient, Groovy calculated attributes. The attribute namedValueUsingVOFunction
references a custommyFunctionAtVOLevel()
method on theEmpViewImpl
class, while the attribute namedValueUsingVORowFunction
references a custommyFunctionAtVORowLevel()
method on theEmpViewRowImpl
class, in both cases passing in the value of theSal
attribute. The methods simply return the value passed in surrounded by either parenthesis or square brackets.
- The
- 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 thecreateViewRowAttrHints
method to return a new instance of theEmpViewRowAttributeHintsImpl
class (which extends the framework base classViewRowAttrHints
. In theEmpViewRowAttributeHintsImpl
class, notice that we've overridden thegetHint()
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 theHiredate
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 thegetLabel
API to customize the value of the "label" UI hint for the Job attribute. Run theTestPage.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 theSal
attribute appended to it.
- This example illustrates how to provide a custom view row attribute hints implementation. The
- 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 theprepareRender
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 theApp
managed bean to see what the user's preferred locale is. In the overriddenprepareRender
method, ifApp.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 callingsuper.prepareRender
. If it ends up changing the locale, it also forces any List Binding objects with a translatable label for their null entry (like "") 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 theApp.preferredLocale
to eitherENGLISH
orITALIAN
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, theAnotherPage.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 like3.45
is presented and edited using the locale-appropriate decimal symbol3,45
. The regular JSP pageRegularJSPPageNotUsingJSF.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.
- 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
- 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 theModel
project to create aSETTINGS
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, theSTATUS
column in theSETTINGS
table is defined asNUMBER(1)
with0
representing false and1
representing true. The example illustrates how you can introduce a transientBoolean
-valued attributeStatusAsBoolean
to work with the numerical true/false value as a Boolean. In the customSettingsViewRowImpl
row class, thegetStatusAsBoolean
andsetStatusAsBoolean
methods have been written to convert the numerical value to a boolean upon reading it and convert a boolean value to the correctNumber
value upon writing it. In the JSPX page in theViewController
project, theaf:selectBooleanCheckbox
is bound declaratively to theStatusAsBoolean
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 as0
or1
appropriately.
- 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
- 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 theCustomEntityImpl
class. Run the sample Form.java class and click on the (testConsistencyOfCurrentRow) button to try it out. ThetextConsistencyOfCurrentRow()
method is a custom method the view object's custom interface which gets the current row, then delegates to it'stestConsistency()
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.
- 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
- 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.
- Programmatically Manipulating a Table's QBE Filter Fields [11.1.1.1, SCOTT schema] 14-AUG-2009
- This example illustrates how to programmatically clear the
af:table
component's filter fields. Thetest.jspx
page'saf:table
component has itsbinding
property set to expose the UI component in theTestPage
backing bean as a property namedtable
. TheTestPage
bean has four button event handler methods that are referenced by the four different buttons on the page. One clears all table search fields, one clears only theDname
search field, the third method clears all the search fields and also queues an event to reexecute the table's query, and the fourth one programmatically populates selected search filter fields and reexecutes the table's query. The backing bean contains helper methods that illustrate how to access the table component's FilterableQueryDescriptor and the "Filter Criteria"Map
it contains. Clearing selected entries from this filter criteria map clears the corresponding search field in the UI. While not required to implement the search field manipulation, the example also illustrates how you can override the default QueryListener method to call customonTableQueryExecuted
query handler method which can include code before or after its invocation of the built-in query listener event handler method provided by the search binding object.
- This example illustrates how to programmatically clear the
- 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.
- 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.
- 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
- ControlBreakTable
- 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 aCustomErrorHandler
class that implements handling for informational messages. TheaddInformationMessageTest()
method in theAppModule
custom java class adds an informational message by using theaddWarning()
API, passing a custom subtype ofJboWarning
calledInformationalMessage
. Due to the way warnings are wrapped before they are passed to the custom error handler'sgetDisplayMessage()
method by the ADF framework, theInformationalMessage
constructor sets a value into the error parameters that theCustomErrorHandler
uses to recognize the warning subtype as an informational message. The overriddengetDisplayMessage()
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 thesetProperty()
andgetProperty()
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 thePage.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 theErrorClass
attribute on the root element of theDataBindings.cpx
file (which shows as theErrorClass
property of the root element in the Property Inspector.
- The base ADF product only distinguishes between warnings and errors, so there is no default way to get a JSF message with severity of
- 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 ofAccount
beans - to be passivated and activated correctly to the application module persistent state snapshot. It shows a combination of required aspects including implementing theXMLDomainWriter
andDomainInterface
interfaces, as well as containing apublic static getXMLDomainFactory()
method that returns an instance of a class that implements theXMLDomainReaderFactory
andXMLDomainFactory
interfaces. TheExampleTransientView
in the project is a transient view object with oneString
-valued attribute marked as the key attribute, and anotherListOfAccounts
attribute of typemodel.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'screate()
method contains the best practice code required for a transient view object that will be programmatically populated by creating and inserting rows. Run theTestClient
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.
- This example shows a custom
- 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.
- CustomBeanDCDefinition
- 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 anaf:table
component whoseselectionListener
property has been modified from the default EL expression dropped when the table was created, to instead call a selection listener method namedonTableSelectionChanged()
in theTestPage
backing bean. This default EL expression normally looks like#{bindings.*TableBindingName*.collectionModel.makeCurrent}
which declaratively "wires" the table selection event to invoke themakeCurrent()
method on theCollectionModel
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 theinvokeMethod()
helper method of theEL
helper class to call the default functionality with custom code before and after it. The EL helper class is in theFwkExtensions
project, which is marked as a project-level dependency.
- This example illustrates a
- 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. TheDeptno
attribute of theEmpView
defines an LOV that references a view accessor based onDeptView
. TheDeptView
view object has an additional SQL-calculated attribute namedExtraAttr
of typeBoolean
. The SQL expression for the attribute is just the quoted string 'FALSE'. There is a view criteria namedLOVSearchCriteria
defined onDeptView
and it includes view criteria items forDname
,Loc
, andExtraAttr
. TheExtraAttr
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'. TheDeptView
view object uses theCustomViewObjectImpl
class as its base framework class, and so theDeptViewImpl
custom view object class extends thatCustomViewObjectImpl
to inherit a few helper methods. The baseCustomViewObjectImpl
overrides thegetCriteriaItemClause()
framework API invoke two other methodsgetCriteriaItemClauseForDatabaseUse()
andgetCriteriaItemClauseForCache()
to customize the SQL fragment returned for a particular view criteria item. TheDeptViewImpl
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.
- 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
- 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 JHeadstartteam). The
CustomFacesPageLifecycle
class is registered in thefaces-config.xml
file as an application-scoped managed bean namedPageLifecycle
(the name is arbitrary, of course). TheCustomADFPhaseListener
class is registered in the "Life Cycle" section of thefaces-config.xml
as well. Its overriddencreatePageLifecycle()
method uses theEL
helper class to return the custom page lifecycle class using the methodEL.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 itsAction
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 theDname
af:inputText fields whoseValue
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 customizedMap
approach to effectively provide simple, one-argument callable methods. In this case, thegetAttributeBindingWrapper
map wraps theAttributeBinding
passed in as an argument. The second of the twoDname
inputText's shows that by wrapping the attribute binding in this way and setting theDisabled
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.
- This example illustrates an interesting technique (that I initially learned from the always-clever JHeadstartteam). The
- 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.
- 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.
- DataPushDynamicGraphs
- DataPushSampleFilter
- 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.
- 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.
- 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 simpleCustomEntityImpl
framework extension class on which both theDept
andEmp
entities in the sample are based. It's overriddencreate()
method tests for the presence of a custom attribute-level metadata property namedSequenceName
and if detected, populates the attribute's default value from the next number in that sequence using the same basic code as above. TheDept
entity defines the customSequenceName
property on itsDeptno
attribute with the valueDEPT_TABLE_SEQ
, while theEmp
entity defines that custom property on itsEmpno
attribute with the valueEMP_TABLE_SEQ
. The suppliedCreateDeptAndEmpTables.sql
script creates the tables and sequences for you.
- 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
- 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 editableEmployees
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 theModel
project includes three different instances of the sameEmployeeAllInfo
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 fileQueries.txt
included in theViewController
project contains a formatted version of the different queries. You can see in the query for theMinimalEmployeeInfo.jspx
page, that only theEMPLOYEES
table is included. In the query forMediumEmployeeInfo.jspx
you seeEMPLOYEES
,DEPARTMENTS
,EMPLOYEES
(a second time for the manager), andJOBS
. The query for the final page joins all of the tables.
- This example contains a single
- 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 thegetLoc()
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.
- 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
- DeleteEmpWithConfirm
- 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.
- 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.
- 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 theFindDepartments.jspx
page in this example use thequeryPerformed
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.
- The EL expressions used in the
- 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 theirimmediate
property to the valuetrue
which causes validation to be circumvented. There are two functionally-identical JSPX pages, one which programmatically callsresetValue()
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.
- This example contains a
- DRM004_AutoReduceSearch
- DRM005_CSSAnimations
- DRM007_RevealPanel
- DRM008_InputSliderMeasureSelector
- DRM009_ConveyorTabs
- DRM010_UKOUGMobile
- DRM011_MessagePrioritization
- DRM012_DeploymentPlan
- 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. Itsvalue
attribute is set to the EL expression#{DropdownListInTableChangingByRow.lovList[row.DepartmentId]}
. This syntax accesses a backing bean property namedlovList
and if that property is aMap
, then the EL resolver will call theget()
method on theMap
-valued property to access the entry with the key equal to the expressionrow.DepartmentId
inside the square brackets. By implementing thelovList
property in the backing bean as an anonymous subclass ofjava.util.HashMap
with an ovverriddenget(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.
- 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
- 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 theweb.xml
to map to the URL/DumpPoolStatistics
. TheDumpConnectionPoolStatisticsServlet
is configured in theweb.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 theEditEmps.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 theDumpConnectionPoolStatistics
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).
- This example illustrates a servlet that dumps application module pooling statistics and/or ADFBC database connection pooling statistics to the browser. The
- 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 thejbo.ampool.sessioncookiefactoryclass
property in the configuration is not correctly saved to thebc4j.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 thebc4j.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).
- 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
- 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 containsCreateTables.sql
andInsertData.sql
scripts that define and populate four simple tables:PARAMETER_FORM_DEFINITION
,PARAMETER_DEFINITION
,PARAMETER_CHOICES
, andPARAMETER_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. TheParameterFormItems
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 theParameterFormItems
view object and theParameterChoicesView
that enables a view link accessor attribute namedParameterChoices
in each row of theParameterFormItems
view object's results. In theViewController
project, you will find three pages. TheTestParameterForm.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 theDynamicParameterForm.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 theParameterFormItems
and its collection of available choices (via theParameterChoices
view link accessor attribute). The page definition for this page includes aninvokeAction
that triggers the firing of anExecuteWithParams
action binding when the page is not handling a post-back (RefreshCondition="#{adfFacesContext.postback==false}"
). This allows theParameterFormItems
view object'sTheFormId
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 theDisplayType
attribute of the parameter definition. The switcher determines whether to display the item as aninputText
, aselectOneChoice
(i.e. dropdown list), or aselectOneRadio
(i.e. radio group) depending on whether theDisplayType
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 namedUserValue
that has been added to theParameterFormValues
view object. TheShowUserEnteredValues.jspx
page renders the parameters along with the user-entered values, and theDynamicParameterForm.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 theParameterFormModule
to maintain the parameter form metadata that drives the parameter forms, adding a new form, new items, or new item choices as needed.
- This example illustrates one technique for implementing a dynamic, data-driven parameter form. The
- 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 additionalCITIES
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 theCascadingLists.jsp
page, when the driving list serves only to partition the set of choices in the dependent list. In that page, only theCountryId
is actually an attribute of theLocationsView
row. TheRegionId
of the selected region is not present. On the other hand, use the second style, represented by theCascadingListsUsingTwoListBindings.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 theCitiesView
includes both aRegionId
and aCountryId
attribute. TheCascadingLists.jsp
page allows creating, updating, and deleting locations. The page has a "Regions" dropdown list and a "Countries" dropdown list. The RegionsselectOneChoice
is bound using a navigation list binding, and the Countries selectOneChoice is bound using a normal (LOV-style) list binding. TheonRegionListChanged
backing bean method fires for theValueChangedEvent
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. TheinvokeAction
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. TheonCountryChanged
backing bean method fires for theValueChangeEvent
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 theRegionsIterator
to change based on the user's current selection, and since theCountries
view instance in the data model is an actively-coordinated detail view based on theRegions
master view, the changing of the current row in theRegions
view automatically coordinates theCountries
view to have the correlated set of countries for the new current region. TheCascadingListsUsingTwoListBindings.jspx
page uses two list bindings instead of having the driving this be based on a navigation list. TheRegionId
list gets its set of valid choices from theRegionsList
in the data model. TheCountryId
gets its set of valid choices from theCountriesListForRegion
view instance in the data model. This latter view instance is based on theCountriesListForRegion
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 useValueChangeListener
methods like the ones used in the other page. The difference in this example is what therefreshCountryListUnlessCountryChanging
invokeAction invokeAction executable in the page def is doing. In this page's page definition, this invokeAction causes anExecuteWithParams
action binding on theCountriesListForRegionIterator
to be triggered during theprepareRender
lifecycle phase whenever the user is not changing the country. Notice that this invokeAction is sequenced after the iterator binding forCitiesViewIterator
so that the value of the RegionId binding will reflect the up-to-date state of the currentCitiesView
row. ThatExecuteWithParams
action binding is configured to pass the value of the#{bindings.RegionId.inputValue}
as the value of theTheRegionId
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 theConditionalValidationPageController
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 theCountryId
binding to null if the user is changing the region poplist, detected based on the presence of the request-scopeRegionChanged
attribute mentioned previously. Also note that the example contains a group of classes in thetest.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. TheViewController
project in this example also implements the same custom error handling code as example# 107 and contains a slightly-modified routine in itsCustomFacesPageLifecycle
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!
- This sample works on the HR schema, but requires first running the supplied
- DynamicTabs1112
- DynamicTabs1212
- DynamicTabs11114
- 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()
. TheTestClient
program calls an application module's client interface method namedcreateViewObjectAndViewLinks()
. 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.
- 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
- 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 theDEPT
table, we assume that in addition to theDeptno
primary key's uniqueness that is declaratively enforced using the ADF UniqueKeyValidator, we also want to enforce the uniqueness of theDname
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". TheDeptDefImpl
class in this example implements anexistsByDname()
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 theFindDeptByUniqueDname
view object to test case-insensitively whether a row exists in theDEPT
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. TheDept
entity object class has an attribute-level method validator defined to trigger thevalidateDname()
method in theDeptImpl
class. This method gets the custom entity definition class and calls theexistsByDname()
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.
- This example illustrates how to implement an efficient existence check to enforce the uniqueness of a non-primary-key attribute. Using a
- Entity and View Object Based on Web Service [10.1.3]
- This example contains two separate workspaces
DeptADFBCWebService
andEntityAndViewBasedOnWebService
. The former contains two projects. The first is namedProject
and contains a simpleDeptService
application module, and a defaultDept
entity object, and entity-basedDeptView
view object. The application module has custom methods on its client interface likeretrieveDepartmentData()
,estimateCount()
,findDepartmentByDeptno()
,insertDepartment()
,updateDepartment()
,mergeDepartment()
, anddeleteDepartmentByDeptno()
. TheDeptService
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 theDeptADFBCWebService
workspace is aTests
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 suppliedCreateEmpAndDeptTables.sql
in theSCOTT
account. The WAR deployment profile in theProject
project deploys the web service to an external OC4J instance, which you can launch most easily by running thestart_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 URLhttp://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort
. Note that the web service unit test fixture makes use of a web service proxy class namedDeptServiceSoapHttpPortClient
that was generated using JDeveloper's Web Service Proxy wizard, using the WSDL URL ofhttp://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort?WSDL
The secondEntityAndViewBasedOnWebService
workspace contains anHRModule
application module, and default entity objects and view objects for theDEPT
andEMP
tables. TheDeptImpl.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, theDeptViewImpl.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 theHRModule
- and you make sure you have the webservice in the other workspace deployed and currently running - you can work with the data in theEmpView
andDeptView
view object instances. When the data is read for theDeptView
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.
- This example contains two separate workspaces
- 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.
- EntityAndViewBasedOnWebService
- 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 namedOnDnameOrLocChanged
. 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 theDeptImpl.java
class, you can see that I've added a call to thisOnDnameOrLocChanged()
method inside thesetDname()
andsetLoc
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 theDeptDefImpl.java
, you'll see generated methods toaddOnDnameOrLocChangedListener()
andremoveOnDnameOrLocChangedListener
. 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 theadd*EventName*Listener()
method. TheEmp
entity in the demo declaratively subscribes to theOnDnameOrLocChanged
event, indicating that the event should be delivered to all associatedEmp
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 theAppModule
application module and try changing the value of theLoc
orDname
attribute of a department, you can observe in the JDeveloper Log window that the associatedEmp
entities in that department receive the notification.
- This example illustrates one way to use the lightweight JavaBeans event publish/subscribe mechanism that ADF Business Components supports for entity objects. The
- 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. TheRETURNING INTO
clause throws database-level errors when used in some kinds of database views havingINSTEAD 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.
- 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
- Best Practice Approach for Invoking AM, VO, or VO Row Methods from a Backing Bean [11.1.1.1, SCOTT schema] 18-SEP-2009
- This example illustrates several interesting points about how the view-controller layer can use ADF action bindings to invoke custom methods exposed on the client interface of application modules, view objects, and view rows. Run the
ViewController
project to start the demo. Enter a string value and an integer value on theStartPage
and click the button to start theemp-task-flow
task flow, passing in values for the task flows two parametersstringTaskFlowParam
andintTaskFlowParam
. In theTestPage.jspx
that runs whenemp-task-flow
starts, the parameter values passed in appear in the title bar of the box at the top. Nine buttons in this page illustrate different combinations of invoking application module, view object, and view row methods using action bindings in the page's pageDefinition. For the methods that accept arguments, the nested elements inside the action binding (which you can see in the structure window) reflect the names of the method arguments and provide a declarative EL expression that ADF will evaluate when the action binding is executed to supply the method arguments. Three of the nine buttons are bound to action event handler methods in theTestPage
backing bean. This backing bean illustrates the best-practice technique to invoke methods on the AM, VO, or VO Row client interface, optionally providing some or all of the method arguments in code as well. In particular, it illustrates that you should NOT use theConfiguration.createRootApplicationModule()
API to access an application module in your backing bean. See this blog article for more info on why you should not use it in backing beans. For a bit more information on how theStartPage
captures and passes parameters to the task flow, read on. The initialStartPage.jspx
uses page definition variables namedpageDefStringVariable
andpageDefIntVariable
to declaratively provide temporary storage for the string- and int-valued parameters in the parameter form. These variables were added to the pageDefinition using the Structure window by selecting the variables node inside the executables section, and choosing *{ Insert inside variables > variable }*from the right-mouse menu. Also in the structure window for the page definition of the Start page, we created two attribute bindings to expose the values of the pageDefinition variables to the UI. One way to create these bindings is to select the bindings folder in the Structure window and choosing { Insert inside bindings > Generic Bindings > attributeValues }. The other way is to use the "Bindings" overview editor tab for the StartPage and click the Create Control Binding icon (green plus-sign) in the Bindingsbox on the left. When creating the bindings, choose the iterator binding namedvariables
and pick the pageDef variable name whose value you want to bind to as the attribute name. Theaf:inputText
fields in theStartPage
bind to this attribute bindings using the EL expressions#{bindings.pageDefStringVariable1.inputValue}
and#{bindings.pageDefIntVariable1.inputValue}
. The button on theStartPage
contains two nestedaf:setActionListener
components to assign the values of the pageDefinition variables collected from the user into two request-scope attributes. The value of#{bindings.pageDefStringVariable1.inputValue}
is assigned to#{requestScope.pageDefStringVariable}
, and similarly the value of#{bindings.pageDefIntVariable1.inputValue}
is assigned to#{requestScope.pageDefIntVariable}
. The task flow call activity namedemp-task-flow
in theadfc-config.xml
unbounded task flow is configured to assign the values of the task flow parameters from these request-scope attributes. ThestringTaskFlowParam
task flow parameter gets its value from the#{requestScope.pageDefStringVariable}
, while theintTaskFlow
param gets its value from the#{requestScope.pageDefIntVariable}
. As part of its parameter definitions, theemp-task-flow
itself defines pageFlowScope attributes that will hold the values of the task flow input parameters for the duration of the task flow. ThestringTaskFlowParam
parameter value is stored in the attribute#{pageFlowScope.stringTaskFlowParam}
while theintTaskFlowParam
is stored in the attribute#{pageFlowScope.intTaskFlowParam}
. Any pages or backing beans that execute in the context of this task flow can reference the parameter values using these same EL expressions. As noted above, the action bindings in the page definition are configured to reference these pageFlowScope attributes using EL to declaratively pass their values as method arguments to the invoked method.
- This example illustrates several interesting points about how the view-controller layer can use ADF action bindings to invoke custom methods exposed on the client interface of application modules, view objects, and view rows. Run the
- ExplodedTreeBindingAccessedByIterator
- 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 theModel
project, The technique involves: (1) exposing thegetPostedAttribute()
API aspublic
in aCustomEntityImpl
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 overriddencreate()
method of theCustomViewObjectImpl
class, and (3) returning the original value of the appropriate underlying entity attribute usinggetPostedAttribute()
in an overriddengetAttributeInternal()
method of theCustomViewRowImpl
class. TheDept
entity is configured to use theCustomEntityImpl
and theDeptView
view object is configured to use theCustomViewObjectImpl
component class and theCustomViewRowImpl
row class. In theViewController
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 theDeptView
and making changes to theDname
and orLoc
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.
- Section 9.9 How to Access Original Attribute Values in the ADF Developers Guide for Forms/4GL Developers explains the
- 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.
- FaceletsAndSetPropertyListener
- Filter a Tree Showing Necessary Parent Nodes for Matches [11.1.1.1, SCOTT schema] 15-SEP-2009
- The
EmpView
view object in this example features a WHERE clause with a "reverse"CONNECT BY
expression to identify parent employee rows that match theEname
search criteria. TheSTART WITH
clause filters employees in a case-insensitive way based on the value of thevarEname
bind variable. The built-inExecuteWithParams
operator for theEmpView
was dropped onto the page as a parameter form to declaratively apply the user's search filter and re-execute the query. TheEmpViewImpl
custom view object class overrides the framework'screateViewLinkAccessorRS()
method in order to set the value of thevarEname
bind variable from theEmpView1
view instance in the data model to also be set on the framework-created view link accessor view object, as well as on any view link accessor rowsets created. This "cascades" the value of the bind variable to the nested queries appropriately. In the page definition for theFilteredTreeShowingInterimNodes.jspx
page, the automatically-createdExecuteWithParams_varEname
page definition variable has a custom label hint associated with it to define the prompt that will appear next to the search field. Last but not least, theTracingViewObjectImpl
framework extension class instruments thebindParametersForCollection()
method to dump useful information about each query executed. TheEmpView
view object specifies this class as its framework base class.
- The
- 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 itsAction
property set todialog:selectDepartment
and has itsuseWindow
property set totrue
so that it invokes a modal, popup dialog containing the pageSelectDepartment.jspx
. The commandButton on that page contains a nestedaf: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.) TheonReturnFromSelectDepartmentDialog
return listener method in theEditDepartment
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.
- The
- 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 thebindParametersForCollection
method to conditionally uppercase any String-valued bind variable parameter values that happen to have a custom metadata property namedUppercase
set on them in their bind variable definition. You can use the view object editor to inspect the bind variable namedTheName
on both theDeptView
andEmpView
view objects to see that they both have thisUppercase
custom metadata property set. Both of these view object specifyCustomViewObjectImpl
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 whoseEname
starts with the letter "s" (entered in lowercase, too).
- This example illustrates a framework extension class
- 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
MyViewRowImpl
framework extension class that will achieve that. TheDeptView
view object in the example indicates that it should use theMyViewRowImpl
class as its view row implementation class. TheDept
entity object supplies default values for itsLoc
andDname
attributes, and theDeptView
view object specifies a further view-object-attribute-level default value for theLoc
attribute as well. You can use the ADF Business Components tester to try creating a new row to observe the behavior.
- 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
- Further Filtering View Link Accessor RowSets at Runtime [10.1.3.1] 08-FEB-07
- The
test()
method in theTestModule
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 runtimeWHERE
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 theTestClient.java
class to see the results of thetest()
method in action.
- The
- 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.
- 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.
- GlassfishExtension
- 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
- 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 theDepartments
view object instance. TheDeptView
view object definition on which this view instance is based, is viewlinked to theEmpView
view object with a view link accessor namedEmployeesInDepartment
. The tree binding in the page definition is configured with two rules in order to show theDname
attribute for theDeptView
rows, to "drill down" into theEmpView
details for eachDeptView
row using theEmployeesInDepartment
view link accessor attribute, and to display theEname
attribute for eachEmpView
in the tree. The tree control has anid
ofmyTree
so that the panelGroup component surrounding the employee detail information can have itspartialTriggers
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 therendered
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. ThenodeStamp
facet of the tree component includes answitcher
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 expressionnode.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 theDeptView
view object, and a string of "test.model.EmpView
" for the nodes coming from theEmpView
view object. In order to avoid using these "raw" view definition names as theswitcher
component's facet names, we introduce atreeLevel
map in theExample
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 thefaces-config.xml
file using the JSF managed bean facility. ThefacetName
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 theDeptNode
switcher facet as a outputText, whileEmpView
nodes render using the contents of theEmpNode
facet as a commandLink. The command link is configured to have its action listener invoke the declarative action bindingsetCurrentRowInEmployeesIteratorWithKey
which is the name of the action binding in the page definition that uses the built-insetCurrentRowWithKey
operation against theEmployeesIterator
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 theExample
backing bean, theonTreeNodeDisclosed
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. TheonClickEmployeeCommandLink
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 itsimmediate
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.]
- The
- 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.
- Using a Headless Taskflow to Perform Work in an Autononmous Transaction [11.1.1.5] 24-NOV-2011
- This example illustrates a technique to use a "headless" taskflow -- that is, one without any view activities -- like a subroutine call. The
perform-isolated-work
bounded task flow in the example has its Data Control Scope set to "isolated" so that the work it performs is done in a separate transaction. Run theMain.jspx
page to try the demo. Theexample-dept-region
bounded task flow includes a button on itsExampleDept.jsff
page that navigates to a task flow call activity in the taskflow to perform the work done by the isolated "subroutine" call. Theperform-isolated-work
includes a method call activity that invokes theperformAppModuleLevelWork()
client interface method in theAppModule
application module. This method accepts an integer representing the department number to modify, and a String representing the value that department'sLoc
attribute should be updated to, then it commits the changes. The taskflow accepts parameters which it passes into this method call. Theaf:commandButton
includes two nestedaf:setPropertyListener
components to assign values to therequestScope.deptno
andrequestScope.locValue
attributes which are referenced by the task flow call to pass these values into the task flow. The page is configured to pass the current row'sDeptno
value, and to pass the literal value 'Q
' as the value to assign to theLoc
attribute in the current row. The net effect is that clicking the button will update the current department row to have the value 'Q
' as itsLOC
column value (in a separate transaction. The checkbox in the page controls whether or not the Router activity will declaratively refresh theDeptView1Iterator
iterator in the page, or not, upon returning from the task flow method call. If you leave the box unchecked, you can observe the effect of the update committed by a separate transaction by attempting to update the current row in the UI after having clicked the button. You'll see an error that "Another user has change the row with primary key ...". If you perform the refresh, you'll see that the requery causes theLOC
value updated in the separate transaction to be reflected in the web page. The custom PagePhaseListenerCalledTaskflowErrorReporterPagePhaseListener
, which is configured in theadf-settings.xml
file, ensures that any exception thrown in the nested taskflow gets reported to the binding container of the page that is marked as an exception handler activity. To see this exception reporting in action, use SQLPlus to lock the row in the DEPT table corresponding to the current row in the web page. Then, when clicking on the button to perform the work in the isolated transaction, you'll see a "Row Already Locked" exception in the UI.
- This example illustrates a technique to use a "headless" taskflow -- that is, one without any view activities -- like a subroutine call. The
- 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 stringADDED 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 itsbeforeActionPerformed()
method that sets the maximum fetch size back to unlimited (-1) and sets the where clause parameter value by position.
- This example contains a DeptView view object having the where clause
- 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).
- 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 namedSelected
has been added. TheView
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 thesetTransactionModified()
method to avoid dirtying the transaction unless the transaction related to the underlying application module is actually dirty. The companionMyCustomDataControlFactoryImpl
is required to instantiate the custom data control class, and theDataBindings.cpx
file references the fully-qualified class name of the custom data control factory class in theFactoryClass
property of the<BC4JDataControl>
element in the<dataControlUsages
section of that file. Run thePanel1
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 thesetSelected()
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.
- 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
- 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 pageTestPage.xsql
to format the data in the iterator using XML/XSLT techniques. TheTestPage.xsql
uses the custom XSQL action classtest.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 afilter-mapping
for the*.xsql
URL pattern, (2) theDataBindings.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 theADFPhaseListener
that is registered to be used by the Faces infrastructure). This makes sure that the request-scopedbindings
attribute is correctly set to reference the current page's runtime binding container.
- This example illustrates a
- 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 theCreateTable.sql
script in thaeModel
project to create theIMAGE_TABLE
table. See theREADME.TXT
file in theViewController
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.
- This example illustrates a simple browse page and edit/upload page for images stored in an Oracle table column of type
- 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 likepanelGroup
. 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 FacesaddPartialTarget
API. I initially created the graph tag by creating a regular (i.e. non-JSF) JSPX page, and dropping theEmployeesInDepartment
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 theGraph
tag'sdata
attribute to reference the renamed graph binding. Finally, I edited the chart's visual properties by double-clicking on theBIGraphDef1.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 calledTotalComp
which simply is the sum of theSal
andComp
attributes to provide an employees total compensation. Notice that you can edit theSal
orComm
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. TheEmp
entity in theModel
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.
- 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
- 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.
- Data-Driven af:selectOneChoice List Bound to a Managed Bean Property [11.1.1.1, SCOTT schema] 17-SEP-2009
Page1.jspx
in this example illustrates how to bind anaf:selectOneChoice
dropdown list to a session-scope managed bean property#{myBean.selectedDepartment}
. Rather than using an ADF list binding (which is designed to target a row attribute or page definition variable), instead we create a table binding in the page definition (DeptView1
) that is bound to theDeptView1Iterator
iterator binding and which exposes the attributes we want to use for the label and value in the list of valid choices (Dname
andDeptno
, respectively). Nested inside theaf:selectOneChoice
anaf:forEach
loops over theList
-valuedrangeSet
property that the table/range binding exposes, and create the select list items based on the data in the rows of theDeptView1Iterator
(which is bound to the default rowset of theDeptView1
view object instance in theAppModule
application module.
- 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.
- 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.
- Method Action Invoking Managed Bean Method Without Making Bean a DataControl [11.1.1.5] 24-NOV-2011
- This example illustrates how to configure an ADFM method binding to invoke a managed bean method without having to turn the bean into a data control. Turning a bean into a data control just to invoke a bean method on it is one of the most common mistakes I see ADF developers doing. The
MyBean
bean is registered in theadfc-config.xml
file and the method action binding in the page def forview1.jspx
references the bean using theInstanceName
property of the binding. Note that the EL expression you provide needs to use the older-style with the dollar-sign rather than the pound-sign. Run the page in the example and click the only button in the page. You'll see the message "Foo" print out in the log window.
- This example illustrates how to configure an ADFM method binding to invoke a managed bean method without having to turn the bean into a data control. Turning a bean into a data control just to invoke a bean method on it is one of the most common mistakes I see ADF developers doing. The
- 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.
- 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
- 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 theDemoModule
in the ADF Business Components browser and double-click on theEmployees
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 theAllDepartments
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 theDepartmentId
. 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.
- This example illustrates an
- 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
. TheStaff
view object is an entity-based view object based on theUser
entity object that has a WHERE clause to retrieve only the users having aUSER_ROLE
is either'technician'
or'manager'
. TheProductExpertiseAreas
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 theProduct
entity object as its primary entity usage, and hasExpertiseArea
as a secondary, reference entity usage. It defines a named bind variableBind_UserId
that is consciously named exactly the same as the system bind variable the framework will add for the view link betweenStaff
andProductExpertiseAreas
(based on theUserId
). That view link has a customized view link SQL clause to allow theUSER_ID
to beNULL
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 theProductExpertiseAreas
view object will have a non-nullExpertiseArea
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, theExpertiseArea
entity row part will be a blank entity row. To simplify the client, we introduce a transientBoolean
-valued attribute on theProductExpertiseAreas
view object namedHasExpertise
. We override thegetHasExpertise()
andsetHasExpertise()
methods in the view row class to handle retrieving and setting this transient attribute. The setter method handles either creating a newExpertiseArea
instance corresponding to the currentuserId
andprodId
combination, or removing an existing entity row, depending on whetherHasExpertise
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 BooleanHasExpertise
property, and the functionality works the same in JSF, JSP, or Swing. TheViewController
project contains a simple JSF page that displays a table containing aselectBooleanCheckbox
bound directly to theHasExpertise
attribute. In other words, it is not using a specialtableSelectMany
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.
- 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
- 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 itstransaction
property set tonew-transction
to indicate that it should only be used as a top-level task when no other current transaction is in effect. Themodify-employee
task flow has itstransaction
property set torequires-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. Thecreate-department
task flow has itstransaction
property set torequires-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 theViewController
project. The home page has links that start either thecreate-department
task flow, or themanage-employees
task flow. As part of the task of managing employees, creating or editing an employee calls themodify-employee
task flow. While modifying an employee, if you need to create a new department, thecreate-department
task flow is called. The 'Cancel' return actions of themodify-employee
andcreate-department
are configured to have therestore-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 namedrowState
andvalueChanged
that are enabled due to the use of theCustomViewRowImpl
framework extension class in theFrameworkExtensions
project. TheCustomViewObject
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). TheCustomEntityImpl
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 customPostAfterAccessors
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. TheEmp
entity in the example is configured with that property in order to cause a new, referencedDept
entity instance to post first.
- This example illustates three bounded task flows that use different declarative transaction options. The
- 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.
- Non-Linear Navigation in Details Page [11.1.1.7] 14-AUG-2013
- This example illustrates a technique to allow a details region to navigate in a non-linear fashion among the results identified in a search region on a previous page. Both the search page and the details page uses the same
EmployeesView
view definition, but we use two distinct instances so that ADFBC can optimize the SELECT list for both use cases. The search page only shows theEmployeeId
,LastName
, andFirstName
of the employee, so only those three columns are selected from the database. In the details page, allEmployeesView
columns are bound to UI components (and reflected in page definition attribute bindings) exceptfor theManagerId
andCommissionPct
fields, so theSELECT
list reflects this extended set of fields. TheEmployeesView
view object is marked to have SQLMode = "Declarative" so that ADFBC can calculate its runtimeSELECT
list based on the attributes bound in the current page definition. All of theEmployeesView
attributes except for the primary keyEmployeeId
are marked withIsSelected='false'
(labeled in the design time user interface as "Selected in Query" = false. This allows the declarative SQLMode view object mechanism to prune these attributes out of theSELECT
list when they are not needed by the current page. The pageDef of the View2 page fragment contains a "RequeryDetail" action binding in the View2.jsff page's pageDef This is wired to the built-in action "ExecuteWithParams" The value of the VO's bind parameter comes from the EL expression#{bindings.SummaryEmployeeId.inputValue}
. ThisSummaryEmployeeId
Attributes binding to the View2 pagedef to more easily bind to the EmployeeId attribute value in the current row of the summary VO instance's iterator binding The default activity of theemployee-details
taskflow invokes this "RequeryDetail" action binding to execute the detail query when the task flow first starts. The DataBindings.cpx file is configured so that this method activity uses the same pageDef as the "View2" view activity that it forwards to. This is important so that the VO is executed in the context of the pageDef that has all the attribute bindings that will inform ADFM/ADFBC of what attributes to select. A ValueChangeListener in the View2.java backing bean to execute the "RequeryDetail" action binding Notice that when you run theHome.jspx
page, you can perform a search in the summary page to identify a set of desired results. Clicking on the (Details) button takes you to the details page. On the details page you can use the selectOneChoice "navigation list" at the top to navigate the current row in theSummaryEmployeesView
VO instance's result set. The ValueChangeListener in the View2 backing bean executes the "RequeryDetail" action binding to re-execute the detail query with the new bind variable value related to the new current row in the SummaryEmployeesView. If you click the (Summary) button, you return to the summary page with the current row reflecting the current row you had see in the details. In order to prevent any implicit executeQuery calls on theDetailEmployeesView
view object instance, we have set theRefresh
property of theDetailEmployeesViewIterator
iterator binding in theview2
page's pageDef to the value of "never". Since the default taskflow activity and the backing bean value change listener are already configured to (re)execute the VO query when we need it to, we do not need or want any implicit query execution to be performed (otherwise the VO might be executed with a null bind variable value and "waste" a trip to the database only to have no rows returned). TheTracingViewObjectImpl
class logs the queries being executed to more easily see the declarative-mode SQL SELECT list pruning optimization at work.
- This example illustrates a technique to allow a details region to navigate in a non-linear fashion among the results identified in a search region on a previous page. Both the search page and the details page uses the same
- Avoid Adding a New Row to a Table Until Its Valid [11.1.1.2] 26-DEC-2009
- This example illustrates an approach to prevent a newly-created row from getting automatically added to a view object's rowset (shown in a table) until it passes all validation rules. Typically a newly-created row will be added to a rowset for any view object based on the same entity object. This example contains a framework extension class for entity objects
NotifyChangeOnValidatedEntityImpl
and a framework extension class for view objectsOnlyAddNewRowIfValidViewObjectImpl
. The entity framework extension class overrides thevalidateEntity()
framework method to send an attribute change notification after the entity object successfully passes validation. The view object framework extension class exposes getter and setter methods for a boolean property namedonlyAddNewRowIfValid
and the overriddenrowQualifies()
method ensures that a new row does not qualify for inclusion in the view object's rowsets unless it is valid. TheAppModuleImpl
class overrides theprepareSession()
method to set the property on theDeptView1
view object instance. To run the demo, run theview1.jspx
page. Click (Create) to create a new row. A data entry form appears at the top of the page. To cause a validation error to occur, leave the fields blank, or try entering aDname
value of upper-caseX
and aLoc
value of upper-caseY
. Notice that until the row validates, it's not added into the table.
- This example illustrates an approach to prevent a newly-created row from getting automatically added to a view object's rowset (shown in a table) until it passes all validation rules. Typically a newly-created row will be added to a rowset for any view object based on the same entity object. This example contains a framework extension class for entity objects
- 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.
- 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 methodenableDetailsForViewInstances()
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. TheExampleModule
application module extends this base class, and exposes the method on its client interface. In theViewController
project, theCustomJSFPageLifecycle
class overrides theprepareModel()
method to augment this phase of page processing to add a call to the abovementionedenableDetailsForViewInstances()
method, passing in a list of view instances corresponding to the iterator bindings in the current page's binding container. Another framework extension classCustomViewObjectImpl
overrides theexecuteQueryForCollection()
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 themaxFetchSize
for the view object to zero, calling the super, then restoring the originalmaxFetchSize
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 theCustomViewObjectImpl
class overrides thebindParametersForCollection
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
, andThirdPage.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 namedenable.optimizations
. TheExampleModule
comes with two different configurations, one that has this parameter enabled, and the other where its disabled. By selecting theDataBindings.cpx
file in theViewController
project, and selecting theExampleModuleDataControl
node under thedataControlUsages
section in the Structure Window, you can use the Property Inspector to set theConfiguration
property to toggle between using theExampleModuleLocal
configuration where the optimizations are disabled and theExampleModuleLocalOptimizationsEnabled
configuration where the optimizations are enabled. The example is configured by default to use the configuration that has the optimizationsenabled. 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. TheThirdPage
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 forEmpDetails5
involves setting theCacheResults
property tofalse
on its iterator binding. This causes the framework to perform aclearCache
on the view object at the end of the request. Requerying theEmpDetails6
iterator is done using aninvokeAction
in the page definition, bound to anExecuteQuery
action binding. ThisinvokeAction
has aRefreshCondition
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 theCurrentTime
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.
- 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
- 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 theDeptViewWithBindVariable
. 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 theclearFilterOnDeptView()
or thefilterDeptViewByDname()
on the application module's custom interface. Try tacking on an additionaldname
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 Facesaf:switcher
component to conditionally present the results in a table or in a form depending on how many results are identified by the query.
- 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
- 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 theOPTIONAL_REQUIRED_TEST
table, run theTestPage.jspx
to see that when a row has itsRowType
attribute set to the valueA
then theValueA
inputText component renders, while if itsRowType
attribute is instead set to the valueB
then theValueB
inputText field renders. These fields set theshowRequired
property totrue
to show the required field indicator to the end-user even though the underlyingValueA
andValueB
attribute are not marked as mandatory. The conditional mandatory validation is performed in theTestEntity
entity object using entity-level method validators. The radio group UI component is marked to have itsautoSubmit
property true, and theValueChangeListener
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 theConditionalValidationPageController
- 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 theControllerClass
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'srendered
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 itspartialTriggers
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.
- This example illustrates how to validate and render conditionally-required attributes. After running the included
- 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 NonDBBlockview 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.
- 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 agetManAttr()
, and "WomenRow" rows can be cast to aWomenRow
interface to access agetWomanAttr()
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) andEntityObject
polymorphism (which you setup on an individual VO). This example shows both kinds of polymorphism at work, but they can be used independently.
- Demonstrates the different levels of polymorphic query support that we have in ADF Business Components. The
- 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.
- 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
- 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 aninvokeAction
combined with anExecute
operation binding (and appropriate settings for theRefresh
andRefreshCondition
properties of theinvokeAction
) 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. TheAnotherPage.jspx
, to which you can navigate fromDepartments.jspx
, contains twoaf:commandLink
components that navigate back to theDepartments.jspx
page. One of those links uses a nested,af:setActionListener
component to declaratively set the value of the request-scope attribute namedrefreshFlag
to the valuetrue
. The presence of this flag attribute causes theinvokeAction
mentioned above to force a requery of the rows. TheDeptView
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 anaf:table
and have a range size ofN
set on your iterator binding to show onlyN
rows per page, then the estimated row count query will be used since the table component needs that count to build its paging control. TheDepartmentsProgrammatic.jspx
page is nearly identical to theDepartments.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. TheDepartmentsAlwaysRequestOnPageEntry.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, theDepartmentsTimedAutoRefresh.jspx
page illustrates how to use the combination of anaf:poll
component and anExecute
action binding to refresh the page without user intervention every 5000 milliseconds (i.e. 5 seconds). Notice that theaf:poll
component has anid
attribute set to the value "timer
" and that anaf:outputText
on the page as well as theaf:table
UI components list this "timer
" id in theirpartialTriggers
property so that they will be partial-page refreshed to "repaint" any updated results. Theaf: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 theExecute
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 theDepartmentsIterator
using the built-in operation namedExecute
.
- This example contains four JSF pages that each show a table of department rows. The
- 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'sCOUNTRIES
table. Run theProgrammaticScroll.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.
- The
- 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 Executablessection 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.
- Declaratively Toggling Display of PanelBox Based on Radio Group Value [10.1.3]
- This example illustrates a simple JSF page with a
selectOneChoice
and aselectOneRadio
, each with its respective value bound to anInteger
-valued backing bean property. Theswitcher
controls use the respective property value to toggle the display of an appropriate PanelBox, and thepartialTriggers
property setup on the containingpanelGroup
component causes the panel to repaint when the value of the respective selectOneXXX component changes.
- This example illustrates a simple JSF page with a
- 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).
- 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.
- Simple command-line utilities that illustrates how to use the ViewObject's
- 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.
- 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.
- 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 theResultsAction.java
custom data action class.
- 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
- 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.
- 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 thehandleWarning()
notification when any business components warning is signalled in custom code. As illustrated in theDeptImpl
class in the example, you signal a warning by constructing an instance of theJboWarning
class and passing it to theaddWarning()
method of theApplicationModule
. To distinguish between a warning and a purely information message, the example introduces a subclassInformationalMessage
that extendsJboWarning
and thehandleWarning()
method in theCustomFacesPageLifecycle
class reports the warning as aFacesMessage
with the appropriate severity. To experiment with the demo, run theTestPage.jspx
page and try entering the value "ERROR
" for theDname
field. That will cause an attribute-level validation to fail for that attribute. If you instead enter aDname
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.
- 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
- Performing Custom View Criteria Item Search Form Validation [11.1.1.2] 26-DEC-2009
- This example illustrates a framework extension class for View Objects that enforces additional custom validation on a view criteria's items such that the user cannot try to "outsmart" a selectively-required view criteria item having the "STARTS_WITH" operator by entering a leading wildcard operator (
%
or_
). It also shows how you might force the end user to provide at least three leading non-wildcard characters in the search criteria so that the index on the selectively-required column is more selective and hence more performant. To try the demo, run theTestPage.jspx
. Try submitting the search form without entering any of the selective-required criteria items (Ename
andJob
in our example). You'll see an error asking the user to provide a value for at least one of those fields. If you try to provide a search value like%
and click (Search), you'll get a custom exception saying that your search cannot start with a wildcard. If you enter two letters likesm
(to find employeeSMITH
) and click (Search), you'll get a different error telling you to please enter at least three characters.
- This example illustrates a framework extension class for View Objects that enforces additional custom validation on a view criteria's items such that the user cannot try to "outsmart" a selectively-required view criteria item having the "STARTS_WITH" operator by entering a leading wildcard operator (
- 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 theEmployees
view object. It consciously chooses to avoid performing client-side required-field validation by notsetting therequired
property of theinputText
controls (which defaults tofalse
). Instead, it sets theshowRequired
property of the components to the same EL expression that would normally be used by the client-siderequired
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. TheViewController
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.1of 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 thegetComponentClientId
method on theFacesCtrlAttrsBinding
object to retrieve the Faces component client id in order to construct aFacesMessage
that is specifically related to a given UI component, (2) the use of the ADF FacesLabeledFacesMessage
class to create aFacesMessage
that remembers the label of the component to which it's associated, and (3) the special-case handling ofAttrSetValException
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 thevalidateModelUpdates()
method in theCustomFacesPageLifecycle
class in order to call a helper methodforceValidationOfNewRowWithAllNullMandatoryAttributes()
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 theTestHomePage.jspx
you can running two different standalone create forms by clicking on an appropriate command button. TheCreateNewEmployeePage.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. TheCreateNewEmployeePageUsingAMMethodViaEntity.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 valueXXXXX
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 theviewcontroller.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 theCreateNewEmployeePage
and theCreateNewEmployeePageUsingAMMethodViaEntity
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 thegetComponentClientId()
function of theFacesCtrlAttrsBinding
returns null if the binding has not previously "seen" a non-null value during the session as well as the fact that theFacesCtrlListBinding
does not support agetComponentClientId()
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.
- The
- 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 calledDepartments
. 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 eachDeptView
row's view link accessor attribute, producing separateEmpView
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 usualEMP
andDEPT
tables calledDEPT_RANK
andEMP_WITH_RANK
. The latter table contains one additional column namedEMP_RANK
which is used to order the employees in a given department. You should run the includedCreateTables.sql
script in your SCOTT account before trying the demo. A few interesting points that the demo shows off is the use of the genericTableSupportBean
which exposes some useful properties to the EL expression language likeselectedNodeRowIterator
andselectedNodeRowKey
. The method action bindings in the page definition for theTreePage.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 theDeptView
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.
- 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
- 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.
- 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 nameddcParam
andrsiParam
(where 'rsi' is short for RowSetIterator). The example includes four other ADF Swing panels that then reuse theEmployeePanel
, each passing in appropriate values for thedcParam
andrsiParam
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 theEmployeePanel
automatically appears there as a reusable component. When you drag/drop theEmployeePanel
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'sdcParam
andrsiParam
parameters. In this way, you can reuse the same panel with different view objects. You'll see a special "page" binding appear in the Executablessection of the including panel's page definition, along with metadata capturing the EL expressions you've entered. The example features aPanel1
panel that reusesEmployeePanel
to display the results of the data collection namedEmpView1
inTestModule1DataControl
. APanel2
panel reuses theEmployeePanel
panel bound to the data collection namedAllEmployees
in theTestModule2DataControl
, based on a different application module. ThePanel3
panel illustrates that you can reuse theEmployeePanel
for a data collection that is a view-linked detail view object instance, in particular theEmployeesInDepartment
data collection in theTestModule2DataControl
. And finally, thePanel4
panel shows that you can reuse theEmployeesPanel
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 namedEmployeesReadOnly
in theTestModule2DataControl
, an instance of the non-entity-based (and hence read-only) view object of the same name.
- The
- Router Data Action
- Shows a generic, and simple, customization of the basic ADF
DataForwardAction
to automatically use theString
-based result of a declaratively-invoked business service method as the name of the Struts forward to use for "next page" navigation.
- Shows a generic, and simple, customization of the basic ADF
- 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 thelistEmployee.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 theControllerClass
property of theeditEmployeePageDef
XML file is configured declaratively to use the custom page controllerRedirectJBO35007ExceptionToAnotherPagePageController
(in thebug.controller
package) to handle the JBO-35007 and redirect to aproblem.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 theControllerClass
property of theeditEmployeePageDef
to be instead the name of theSetRequestScopeAttributeFlagForJBO35007PageController
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.
- This example illustrates how to use a custom page controller class to override the
- 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 theaf:tableSelectOne
component youraf: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 youraf:table
and anaf:panelForm
that displays additional information about the selected row in the table. The secret lies in configuring thepartialTriggers
property of the component that you want to be updated when the table selection changes. In the example, you see that I'd assigned anid
ofmyTable
to theaf:table
component, and on theaf:panelForm
component I've listedmyTable
as one of the component id's that should trigger a partial-page request "repaint" (of theaf:panelForm
). To allow you to experiment with toggling theautoSubmit
property of thetableSelectOne
on or off at runtime, I've configured a simpleSessionSettings
session-scoped managed bean that has a single property nameduseAutoSubmit
. By setting thevalue
property of theaf: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 theaf:tableSelectOne
component'sautoSubmit
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 anid
value oftableAutoSubmitControl
to the checkbox, and listed thattableAutoSubmitControl
component id in thepartialTriggers
property of theaf: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, thepanelForm
to the right is updated to reflect the values of the new current row. The (testCurrentRow) button is a bound declaratively to thetestCurrentRow()
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 thegetDeptView1().getCurrentRow()
method call inside that method already "sees" the new current row (and prints out itsDeptno
value to the console).
- 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
- Set Binding to Attr Value from Selected SelectBooleanRadio Button in Data-Driven Button Group [11.1.1.5] 24-NOV-2011
- This example illustrates an approach to render a data-driven set of selectBooleanRadio buttons and to set a binding with a selected attribute value from the row corresponding to the radio button the user selects. A set of SelectBooleanRadio components in a group can be thought of as a list of boolean flags, where ADF Faces will ensure that only one of the radio buttons flag will be true in a particular group. I've setup the af:iterator to map the stamped out SelectBooleanRadio components to a Map<Integer,Boolean> using the af:iterator's status variable's index value as the key into this map. The SelectBooleanRadioHelper class encapsulates a Map<Integer,Boolean> of the true/false flags for the selectRadioBoolean controls in a group. It also handles updating the value of a binding (whose name you pass in the constructor) with the value of an attribute (whose name you pass in the constructor) when ADF Faces puts a true value into the map, indicating that the currently selected row. The example is using two pageDef variables
currentSelectedValue1
andcurrentSelectedValue2
as temporary storage for the chosen attribute value from the selected row. The corresponding attribute bindingscurrentSelectedValue1Binding
andcurrentSelectedValue2Binding
are bound to these variables. Where these attribute bindings are being used in the demo, you could use any attribute binding that represented where you wanted to set the current value of the selected radio group.
- This example illustrates an approach to render a data-driven set of selectBooleanRadio buttons and to set a binding with a selected attribute value from the row corresponding to the radio button the user selects. A set of SelectBooleanRadio components in a group can be thought of as a list of boolean flags, where ADF Faces will ensure that only one of the radio buttons flag will be true in a particular group. I've setup the af:iterator to map the stamped out SelectBooleanRadio components to a Map<Integer,Boolean> using the af:iterator's status variable's index value as the key into this map. The SelectBooleanRadioHelper class encapsulates a Map<Integer,Boolean> of the true/false flags for the selectRadioBoolean controls in a group. It also handles updating the value of a binding (whose name you pass in the constructor) with the value of an attribute (whose name you pass in the constructor) when ADF Faces puts a true value into the map, indicating that the currently selected row. The example is using two pageDef variables
- 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. TheEmpView
view object includes theEmp
entity object as its primary entity usage, as well as theDept
entity object as a secondary, reference entity usage, in order to display the relatedLoc
value for the department to which the current employee is assigned. TheDeptno
is bound to aaf:selectOneChoice
component whoseautoSubmit
property has been set totrue
. This causes a PPR postback whenever the end-user changes the value of the list. TheLoc
field is displayed as a read-onlyaf:inputText
, and has itspartialTriggers
property set to the value of the id of theaf:selectOneChoice
component ("DeptnoPoplist
") that should trigger the partial page re-paint of the thatLoc``af:inputText
component. When you run the page notice that if you navigate between rows in theEmpView
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-enabledDeptno
poplist, then the value of the correspondingLoc
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 thePPRDemo
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.
- This examples contains a single JSF page with an
- 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.csvfile. 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 CSVEmpView1Iteratoris 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.
- Initialize Task Flow by Setting View Object Bind Vars from Parameters [11.1.1.1, SCOTT schema] 03-SEP-2009
- This example illustrates how to to use an
ExecuteWithParams
built-in operation dropped onto a task flow method call activity that is marked as the default activity to initialize the task flow by setting some view object bind variable values based on task flow parameters passed in from the caller. TheTestTaskFlow.jspx
page has two buttons that are configured to invoke the bounded task flow namedshow-employees-for-dept
, passing in the value of the department number whose employees should be visualized. The task flow defines a parameter namedp_deptno
whose value is stored into the pageFlowScope attribute namedp_deptno
using the EL expression#{pageFlowScope.p_deptno}
. TheExecuteWithParams
operation for theEmployeesByDepartment
view object instance (of typeEmpView
) was dropped onto a method call activity that has been set as the task flow's default activity. TheEmployeesByDepartment
view object instance has been configured in the application module data model panel to declaratively apply the view criteria namedByDepartment
, so when you drop theExecuteWithParams
operation for this view object instance, the list of appropriate bind variables appears in the dialog. ThevarDeptno
bind variable's EL expression is configured on theExecuteWithParams
binding in the page definition to the expression#{pageFlowScope.p_deptno}
to pickup the value to assign the bind variable from the task flow parameter passed in. If you right-click on the method call activity and choose "Go to Page Definition" notice that theEmployeesByDepartmentIterator
iterator binding'sRefresh
property is configured to the valuenever
to avoid the ADF framework's performing any implicit refreshing of the iterator binding before the action binding has a chance to set the view object bind variables.
- This example illustrates how to to use an
- 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.
- 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.
- Signal RowInconsistentException Correctly Across Activation/Passivation [11.1.1.6] 12-MAR-2013
- This example illustrates an approach to ensure that the RowInconsisentException is correctly signalled even if the AM used by the second user has undergone passivation and activation since the first user changed the row. First, it's important to understand the potential problem. Assume that two users U1 and U2 query up the DEPT row with DEPTNO=10. User U1 modifies the Dname in that row and commits. At this point user U2 is looking at a "stale" value in the page in her browser. User U2 proceeds to make her edit and clicks (Commit). In an ADF page implemented in the typical way, the user will correctly get a warning that "Another user has changed the row" as long as U2's application module has not undergone passivation and activation. If instead application load forces ADF to activate the AM's passivated state to service user U2's (Commit)-button click request, then the change made by user U2 is silently committed, potentially overwriting the changes that user U1. This occurs because the act of activating the AM state reads in current DB values of the queried rows, which now reflect the changes made by user U1 instead of the values that are in user U2's current browser page. The solution involves using a change indicator attribute and including that change indicator attribute in the web page as a hidden field. In the example, the
Dept
entity object is based on theDEPT_WITH_OBJ_VERSION
table. This is the standardDEPT
table to which has been added a single, additionalNUMBER
column namedOBJECT_VERSION
. TheObjectVersion
attribute in theDept
entity is marked as a 'Change Indicator' attribute, and it's also marked as a 'History Column' of type 'version number'. The history column setting tells ADF to automatically set the value of this column to 1 in a newly created row, and to increment the version number each time the row is modified and saved. The change indicator setting tells ADF to compare only the value of this attribute in order to determine whether the row has been changed by another user or not. In the absence of a change indicator attribute, ADF must compare the values of all persistent attributes which can take longer. Theview1.jspx
page uses thetr:inputHidden
component to include theObjectVersion
attribute value in the page. By doing this, the object version of the row being edited by user U2 will be submitted to the server along with the other attribute values, and it will be used to compare against theObjectVersion
attribute value of the row being edited. Since these values differ, theRowInconsistentException
is thrown as desired. Try re-enabling the AM Pooling to convince yourself that the technique will work under normal circumstances as well. To run the example, start by running theCreateTables.sql
script to create theDEPT_WITH_OBJ_VERSION
table. Then run theview1.jspx
page. Once the page appears in your default browser, copy the URLhttp://localhost:7101/SignalRowInconsistent/faces/view1
and paste it into a different browser. For example, if Google Chrome is your default browser, paste it into Firefox or Internet Explorer. This will allow you to test having two distinct browser users using your application. Both browsers should be looking at the row for DEPTNO=10. In the first browser window, update the value ofDname
and click (Commit). Now the second browser is looking at a "stale" value for theDname
. In this second browser, update the value ofLoc
and click (Commit). The user gets the expected error "Another user has changed the row with primary key oracle.jbo.Key[10]". TheAppModule
application module in the example has its 'Enable Application Module Pooling' configuration setting (jbo.ampool.doampooling) set to false for testing purposes. Your application module will never have this pooling setting disabled in production, but it is useful for testing the activation-safety of your application module by stress-testing the passivation/activation on each HTTP request.
- This example illustrates an approach to ensure that the RowInconsisentException is correctly signalled even if the AM used by the second user has undergone passivation and activation since the first user changed the row. First, it's important to understand the potential problem. Assume that two users U1 and U2 query up the DEPT row with DEPTNO=10. User U1 modifies the Dname in that row and commits. At this point user U2 is looking at a "stale" value in the page in her browser. User U2 proceeds to make her edit and clicks (Commit). In an ADF page implemented in the typical way, the user will correctly get a warning that "Another user has changed the row" as long as U2's application module has not undergone passivation and activation. If instead application load forces ADF to activate the AM's passivated state to service user U2's (Commit)-button click request, then the change made by user U2 is silently committed, potentially overwriting the changes that user U1. This occurs because the act of activating the AM state reads in current DB values of the queried rows, which now reflect the changes made by user U1 instead of the values that are in user U2's current browser page. The solution involves using a change indicator attribute and including that change indicator attribute in the web page as a hidden field. In the example, the
- 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.
- 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
- 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 theModel
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 ofContact
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 aContact
is changed, theContact
'supdated
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 theRowSet
of data being managed by theRowSetIterator
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 theCacheResults
property is explicitly set tofalse
, which is not the case in this example!) and then rebuilds theRowSet
ofRow
objects that wrap the actual data beans -Contact
beans in this example. TheseRow
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 theexecuteQuery()
in backing bean code, while the latter using a combination of anExecute
action binding related to the method iterator and aninvokeAction
executable whoseRefresh
andRefreshCondition
properties have been set to control the ADF lifecycle phase during which theExecute
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 thefindContactsByName(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 thenameSearch
that the end-user might apply to filter the results is kept in the session-scopedUserInfo
managed bean so it can be referenced by the method action on both theListPage.jspx
and theEditPage.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. TheFwkExtensions
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. TheFindOrMergePage.jspx
illustrates an example of performing data binding to a method result that returns a singleContact
bean instead of a collection of beans (List), using the helper methodexecuteQueryForMethodIterator
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 theFindOrMergePage
can make updates as well as add new rows, theaf:commandLink
on the page sets the requestScope flag to signal to theListPage
to refresh its data on navigating there.
- This example illustrates a simple JSF application that allows you to list, edit, add, and remove contacts. The
- 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_Mgrwith a value of SalaryPercentageOfManager. This declaratively causes the SalaryPercentageOfManagerattribute 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.
- 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 theparse()
andformat()
methods to implement the parsing and formatting of a United States social security number whose format is000-00-0000
. The default number formatter does not work with this format mask as is because the JDKDecimalFormat
class on which it's based doesn't correctly support that format mask as you might expect. You'll need to run the providedCreateEmpWithSocialSecurityNumber.sql
script to create a version of theEMP
table with an additionSSN
column to store the social security number as a numerical value. The Emp entity object sets the custom property namedSsn_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 companionEmpImplMsgBundle.java
message bundle class. TheCustomDCErrorHandler
class in theFwkExtensions
project contains logic that sets the attribute information on theDataCreationException
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 theTestPage.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.
- This example includes a
- 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 callsetSortBy()
on the iterator binding's underlying view object instance instead of the default of callingsetOrderByClause()
. 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. TheViewController
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 theDataBindings.cpx
file. TheCountryList
view object retrieves its data from the companionCountryList.properties
file. When you run theCountryList.jspx
page, try clicking the table headings to sort ascending or descending by theCountryCode
or theDescription
. 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. TheNoDatabaseConnectionApplicationPoolImpl
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 classNoDatabaseConnectionDatabaseTransactionFactory
is configured to be used by setting theTransactionFactory
property of the configuration, and it creates an instance of the customNoDatabaseConnectionDBTransactionImpl2
class which overrides thedoRollback()
method to do nothing.
- This example illustrates a technique to override the
- SortingFilteringByChoiceDisplayValue
- SplitterTest
- 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 Tracearticle. 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.
- 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 theModel
project specify theoracle.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. TheListOfMapsDataProviderViewObjectImpl
framework extension class implements a programmatic view object whose data is populated from ajava.util.List
ofjava.util.Map
objects. TheCSVFileViewObjectImpl
extendsListOfMapsDataProviderViewObjectImpl
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, themodel.States
view object reads its data from themodel/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 theViewController
project allow you to try out master/detail display of the programmatically retrieved data.
- 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
- 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
, andHighSal
. 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 theOnPageLoadBackingBeanBase
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. TheSearchPage.java
backing bean overrides theonPagePreRender()
method to set the values of the search field bindings to the value of the saved processScope attributes of the same names. TheControllerClass
property of the search page's page definition references the backing bean as its page phase listener using the EL expression#{SearchPage}
. ThesetActionListener
components on the buttons in the search page declaratively set the values of the processScope variables.
- This example illustrates a simple search page over an EmpView view object with three named bind variables
- 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.
- 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
- 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.
- 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.
- 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.
- 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 customEntityImpl
class (used by theEmp
EO in the project) which increments the appropriate insert, update, or delete counter in its afterCommit() method.
- 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
- 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.
- Two Approaches to Referencing Controller-layer Session State in VO Bind Variables [11.1.1.2] 16-DEC-2009
- This example illustrates two different approaches to referencing controller layer state inside the default value expression of a view object's bind variable. One typical example is to reference the name of the logged-in user (which in the past web applications would store in a Web session attribute), however since you can use the
adf.context.securityContext.userName
groovy expression to reference the username of the logged-in user when using ADF Security, I choose a slightly-different example of storing a code representing the user's favorite color. The ViewController project contains aUserInfo
bean with a singlefavoriteColor
property. This bean is registered in theadfc-config.xml
file as a session-scoped managed bean, and using the JSF managed property feature, the default value ofemgreen
is injected into the bean at creation time. TheModel
project contains two view objects that each contain a bind variable namedVarFavoriteColor
whose default value we'd like to come from the current value of the aforementioned UserInfo managed bean'sfavoriteColor
property. There are two basic approaches: one will appeal more to those who cherish the cleanest logical separation of view/controller and model layers. The other appeals more to developers who like to use the "simplest thing that works" (as long as it's not bad practice). TheExampleVO2
VO instance in the AM data model is of typeExampleVOUsingADFContextSessionInfoInBindVariable
. This view object'sVarFavoriteColor
bind variable references the groovy expressionadf.context.sessionScope.UserInfo.favoriteColor
and represents the "simplest thing that works" approach. This takes advantage of the fact thatADFContext
object abstracts access to the four interesting scopes that might be relevant during runtime of an ADF application:applicationScope
,sessionScope
,viewScope
, andrequestScope
. When running in the web container, these scopes map onto the obvious matching scopes that you are familiar with from the view/controller layer. When running outside the web container, the ADFContext provides a default implementation of these scopes as a set of static maps that are useful for regression testing purposes. TheTest
class in theTesting
project illustrates making use of theADFContext.getSessionScope()
to setup the session-level information the view object is expecting to find at runtime. TheExampleVO
in the AM's data model is of typeExampleVOUsingControllerSuppliedUserDataHashtableInfoInBindVariable
. This view object's bind variable of the same name references the groovy expressionadf.userSession.userData.FavoriteColor
. In this implementation that defines the more clear separation of view/controller layer and business tier - which is the one I personally prefer and recommend - the ADFBC session's userData map is used to store information that the view object's bind variable will reference. In a customized data control implementation class (CustomDCJboDataControl
), thebeginRequest
method is overridden to invoke asetSessionFavoriteColor()
method on theExampleModule
client interface to pass in the value of theUserInfo.favoriteColor
into the business tier. The application module stores this information in the user data map, and makes that information activation/passivation-safe by overriding thepassivateState()
andactivateState()
methods. The custom data control is configured by setting the fully-qualified name of theCustomDCJboDataControlFactory
class in theExampleModuleDataControl
entry'sFactoryClass
property in theDataBindings.cpx
file (in thedataControlUsages
section). On each request, the view/controller layer passes this information into the business layer, and theExampleVOUsingControllerSuppliedUserDataHashtableInfoInBindVariable
view object references its value from the userData map. Notice thesetDefaultValuesForSessionLevelFavoriteColor()
method in theExampleModuleImpl
class. This is invoked in an overriddenprepareSession()
method to assign a reasonable default value to both of the favoriteColor elements if their value is currently null. This would ensure that both approaches would work if the respective view object were called from a service or a test client that didn't provide any specific value at runtime. In theTesting
project, theTest
class illustrates how you can write a standalone regression test (just a simple Java class in this example, not a JUnit test) which mimics the view/controller layer calling of the setSessionFavoriteColor() API in the one case, and which populates a "mock" sessionScope UserInfo bean with afavoriteColor
property to make the other view object find its expected information. As mentioned above I prefer the approach that uses the userData hash table set explicitly via an application module method, however at least now you have a good example of both techniques in action so you can decide for yourself which you prefer.
- This example illustrates two different approaches to referencing controller layer state inside the default value expression of a view object's bind variable. One typical example is to reference the name of the logged-in user (which in the past web applications would store in a Web session attribute), however since you can use the
- Programmatically Displaying Task Flows in the ADF UI Shell [11.1.1.2] 26-DEC-2009
- This is a ready-built version of the UI Shell demo application that you can build yourself by following the step-by-step tutorial Oracle User Interface Shell. It illustrates various programmatic ways to open a task flow in the ADF UI Shell. Try the demo by running the
First.jspx
page. Each of the links in the "Choose your activity" area open a separate task flow in a tab in the UI shell. Clicking a second time on a link will activate an existing task flow tab if it already exists, rather than opening a second instance of the same task flow. TheSecond.jspx
page (to which you can navigate by clicking on the "Second" tab) illustrates menu items under the "Action" menu that each opens a distinct task flow. In this case, clicking a second time on a given menu item will open additional instances of the same task flow in the shell if one/some happen to already be open. It also illustrates toolbar icons that perform shell functions. The [1] icon opens the same task flow as the first menu item. The [2] icon marks the current tab as being "dirty". If you try to close a dirty tab, you'll see a warning dialog. The [3] icon marks a tab as not-dirty. TheThird.jspx
page illustrates opening task flows as the only content in the shell (i.e. no tabs). It also shows that a button in one task flow can open a taskflow in the shell.
- This is a ready-built version of the UI Shell demo application that you can build yourself by following the step-by-step tutorial Oracle User Interface Shell. It illustrates various programmatic ways to open a task flow in the ADF UI Shell. Try the demo by running the
- 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.
- 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 thepartialTriggers
attribute) that causes a click on the (Create) button or the (Delete) button to enable the same two buttons. The expression used in thedisabled
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.
- 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
- 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.
- 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 theCreateTables.sql
script to drop and create the simpleUPLOADED_FILES
table. Then, run theUploadFileToBlob.jspx
page. Note that the page uses theaf:form
container with itsusesUpload
attribute set totrue
. Also notice that theinputFile
control is bound to the backing bean property namedfileInputComponent
, allowing the backing bean to reference the UI component programmatically. ThevalueChangeListener
on theinputFile
is mapped via EL to theonFileUploaded()
method in the backing bean. That method accesses theExampleModule
client interface of theExampleModule
application module, and invokes thesaveUploadedFile()
method on it. It passes in the file name, and aBlobDomain
class representing the contents of the uploaded file. The (Upload File) button'saction
property is mapped via EL to theonUploadFileButtonClicked()
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.
- 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
- 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 theCreateTables.sql
script to drop and create the simpleUPLOADED_FILES
table. Then, run theUploadFileToClob.jspx
page. Note that the page uses theaf:form
container with itsusesUpload
attribute set totrue
. Also notice that theinputFile
control is bound to the backing bean property namedfileInputComponent
, allowing the backing bean to reference the UI component programmatically. ThevalueChangeListener
on theinputFile
is mapped via EL to theonFileUploaded()
method in the backing bean. That method accesses theExampleModule
client interface of theExampleModule
application module, and invokes thesaveUploadedFile()
method on it. It passes in the file name, and aClobDomain
class representing the contents of the uploaded file. The (Upload File) button'saction
property is mapped via EL to theonUploadFileButtonClicked()
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.
- 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
- 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
andORDSYS.ORDIMAGE
and their corresponding ADF Business Components domains that do the right thing to handle working with them.
- 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
- Use AutoRefresh VO in Shared AM with Optimized Polling to Show Latest Data in a Table [11.1.1.2] 26-DEC-2009
- This example illustrates how to use an Auto-Refresh view object in a shared application module to display the latest database changes in a table without eagerly requerying the view object. The
DeptView
view object has itsAutoRefresh
property set totrue
and theModel
project defines a shared application module instance namedAppModule
on the Business Components > Application Module Instances panel of the project properties. TheAppModuleDataControl
entry in thedataControlUsages
section of theDataBindings.cpx
file in theViewController
project has been configured to use theAppModuleShared
configuration so that the UI works with a shared application module instance. As an optimization, theDeptView
view object overrides theprocessDatabaseChangeNotification()
method to keep track of theSystem.currentTimeMillis()
in a local member field. The view object'sgetLastRequery()
is exposed on the client interface and is accessed by theDepartmentPage
backing bean's via a method action binding. That bean'sonPollTimerExpired()
method only bothers to add the table UI component as a partial target if the time the view object was last requeried is greater than the time the table was last PPR'd (which it tracks in a viewScope attribute). To try the demo, run theDepartments.jspx
page. If you'd like try accessing the same page from several different browsers (e.g. Firefox, Internet Explorer, Chrome) to simulate multiple, distinct user sessions. In SQL Plus (or the JDeveloper SQL Developer worksheet window) try insert, updating, or deleting rows in theDEPT
table and committing the changes. Sometime in the next 15 seconds, the different browser user's should update to reflect the changes automatically.
- This example illustrates how to use an Auto-Refresh view object in a shared application module to display the latest database changes in a table without eagerly requerying the view object. The
- Validating Exactly One Detail Row of a Given Type [11.1.1.1, Custom schema] 04-NOV-2009
- This example illustrates two techniques for validating that a parent entity contains exactly one composed child entity of a given type. Start by running the
CreateTables.sql
script to create theEMAIL_MESSAGE
andEMAIL_MESSAGE_RECIPIENTS
tables. The example is a simple "Create an Email" application that allows you to create a new email message and add one or more recipients. Each recipient is of a particular RecipientType (P
=Primary,C
=CC,B
=BCC). The rule being enforced is that there must be exactly one recipient of type "Primary". The validation is performed by an entity-level Script Expression validator on the parentEmail
entity object. This validator uses Groovy code to work with a view accessor namedValidateOnePrimary
which is of typeEmailRecipientsView
and has the design-time-applied view criteria namedPrimaryRecipient
(criteria mode "Both") applied to it. This view criteria filters based on theMessageId
and theRecipientType='P'
. The view accessor is configured to pass the value of the currentEmail
entity'sId
attribute as the value of the view criteria'sVarMessageId
bind variable. Notice that the script validator allows multiple error messages to be defined. The validator's Groovy script executes the view accessor's query, raises one error usingadf.error.raise(*MESSAGE_KEY*)
if there are no rows returned and another error if more than one row is returned. If the email and its recipients validate successfully, then they are saved to the tables, but note that no real email is sent anywhere. The default expression for theEmailRecipient.RecipientType
attribute uses an alternative approach to the view accessor in order to conditionally assign the default recipient type for a newly createdEmailRecipient
entity. The default expression isEmail.Recipients.count("RecipientType == 'P' ? 1 : null") == 0 ? 'P' : 'C'
which accesses the parent email message using the reverse association accessor namedEmail
then accesses its rowset of recipients by references that email entity'sRecipients
association accessor attribute. Since the value of that expression is aRowSet
we can use one of the built-in rowset, in-memory aggregation functions to calculate thecount
of the childEmailRecipient
entity instances which have aRecipientType
equal toP
. Thecount()
rowset aggregate function evaluates its String argument as a Groovy expression in the context of each row in the rowset over which it iterates. If the expression evaluates to null, then the count does not include that row. If the expression evaluates to non-null, then that row is counted. Finally, it uses a ternary expression so that if the count ofEmailRecipient
instances havingRecipientType
equals toP
is zero, then it returns the default value ofP
, otherwise it returns the default value ofC
to represent a recipient being copied on the mail. TheEmail
entity object includes theMessageText
attribute of typeClobDomain
, and both theEmail.SenderEmail
andEmailRecipient.RecipientEmailAddress
attributes use a custom domain typeEmailAddress
which validates the format of an email address. TheNewMailMessage.jsff
page fragment uses the special<f:converter converterId="oracle.genericDomain"/>
component to enable JSF to work properly with these three domain-valued attributes. TheMailServer
application module defines the custom methodcreateNewMailAndPrimaryRecipient()
which creates a new email message and the first email recipient row. The method is exposed on the client interface so that the default method call activity of thecreate-new-email
bounded task flow can invoke it declaratively to prepare the service layer for the creation of a new email. TheCustomViewObjectImpl
class implement a generic feature to conditionally have rows in a view object's default rowset be inserted at the end. For view objects using this framework extension class as their base class, the feature "kicks in" if the VO has the "InsertRowsAtEnd" custom property set to some non-null value like "true". TheEmailRecipientsView
in the example uses this framework extension class as its base class and has this custom property set. To run the example, run theTestPage.jspx
. You'll need to login as either useruserone
orusertwo
, both of whose password iswelcome1
. Click on the button to create an "email" and then click (Send) to test the validation.
- This example illustrates two techniques for validating that a parent entity contains exactly one composed child entity of a given type. Start by running the
- 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. TheCustomViewObjectImpl
class adds the dynamic attribute in its overriddencreate()
method. TheCustomViewRowImpl
class overrides thegetAttributeInternal()
method to return the desired value for the dynamic attribute. TheEmp
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. Theuntitled1.jspx
page in the ViewController project has a ADF Faces table and references the dynamicValid
attribute to highlight invalid rows in yellow using some appropriate EL expressions in theinlineStyle
attribute of the fields in the table. Theuntitled1PageDef.xml
file had to be hand-modified to include the dynamicValid
attribute in the AttrList of theEmpView
table binding so that the EL expression used above of#{row.Valid}
would be resolvable. And finally, theUntitled1PageController
class is registered as a custom page controller for theuntitled1.jspx
page (by setting theControllerClass
attribute at the root of the page def XML document. This custom controller overrides the default way that thevalidateModelUpdates()
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.
- This example illustrates an framework extension approach for adding a dynamic attribute named
- 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 aUSER_INFO
table withUSERNAME
andPASSWORD
columns. As a trivial example of a entity object String-valued attribute stored in encoded format, the correspondingUserInfo
entity object assumes that itsPassword
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 aCustomEntityImpl
framework extension class, which theUserInfo
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 namedEncodeValue
, which theUserInfo
entity'sPassword
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.
- 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
- 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 aDeptView
view object to feature aWHERE
likeDEPTNO IN (:TheDeptNo)
but you need theIN
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 theCreateTypeAndFunction.sql
script to create theNUM_TABLE
type and theIN_NUMBER_LIST()
function. The function accepts a comma-separate string argument and returns aNUM_TABLE
as its result. This allows theCommaSeparatedListOfDeptno
bind variable in the example'sDeptView
view object to be of type String. The view object'sWHERE
clause looks likeDEPTNO IN (SELECT * FROM TABLE( CAST ( in_number_list(:CommaSeparatedListOfDeptno) as num_table) ) )
. Run theAppModule
in the tester can try entering values like "10" and "10,40" for the bind variable to see it in action.
- This example illustrates a simpler way to achive a variable
- 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 namedMasterView
and the other namedListBasedOnTableFunction
. The former is a simple SELECT from DUAL that unions two rows of dummy data. The first row has the value "D" for itsLIST_TYPE
column, and the second row has the value "E". TheListForMasterRow
view link defines a link between the master viewsListType
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". TheListBasedOnTableFunction
view object defines a named bind variableBind_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 theGET_NAME_VALUE_LIST()
PL/SQL function whose invocation it wraps in aTABLE()
operator to treat the table-valued function result as if it were a table of data. TheCreateTypesAndFunctions.sql
script in the Model project creates theNAME_VALUE_TYPE
object type, theNAME_VALUE_LIST
type, and theGET_NAME_VALUE_LIST()
function. The function is written to return a list of (Dname,Deptno) pairs from theDEPT
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. TheViewController
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). TheSwingView
project contains a simplePanel1
panel with a similar Swing tree control showing the same thing.
- This example contains two read-only view objects in its
- 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.
- 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 thexmltype()
constructor to treat that XML text as an XML document. Then it uses thexmlsequence()
operator to treat the results ofextract()
-ing the<ROWSET>/<ROW>
elements from the XML document as individual rows of source data. Finally, it uses thetable()
operator in combination with theextractValue()
operator to retrieve the data values from each row of<ROW>
fragments, breaking out aDEPTNO
,DNAME
, andLOC
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.
- This example contains a
- 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).
- Illustrates how to use the ViewObject
- Simple JClient Panel Binding to JavaBean DataControlMethod 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.
- 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.
- Shows how to use
- 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 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.