Saved searches
Use saved searches to filter your results more quickly
Cancel Create saved search
Sign up Reseting focus
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
This repository has been archived by the owner on Apr 15, 2021. It is now read-only.
oracle / adf-samples Public archive
Various code samples published by Oracle relating to the Oracle Application Development Framework (ADF)
License
Notifications You must be signed in to change notification settings
oracle/adf-samples
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Go to file
Folders and files
Last commit message
Last commit date
Latest commit
History
View all files
Repository files navigation
adf-samples Repository
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.
Layout
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
List of Samples
- 11g Dynamic JDBC Credentials for Model 1, Struts, Trinidad, and ADF Faces Rich Client [11.1.1.0.0] 06-AUG-2008
- This is an 11g production update of one of my most frequently downloaded examples (Dynamic JDBC Credentials, #14). There are four separate workspaces, one for each of the supported ways you might build a web application using ADF: DynamicCredentialsNoController.jws is a "Model 1" style application with no controller layer; DynamicCredentialsStruts.jws is Struts-based; DynamicCredentialsTrinidad.jws is a 10.1.3 ADF Faces application that's been migrated to use the Apache Trinidad components; and DynamicCredentialsRichFaces.jws uses the new ADF Faces Rich Client components that are new in 11g. Each project references the same Model project and FwkExtensions project. The generic framework extension classes involved in implementing the solution live in the FwkExtensions project. The Model project contains the simple ADFBC components used in the example: a TestModule application module with a single DeptView VO instance of a DeptView view object based on the DEPT table in the SCOTT schema. While updating the example for 11g, I took the liberty of using two new features that allowed me to simplify and streamline the implementation. The first of these was using the new ErrorHandlerClass attribute on the root element of the DataBindings.cpx file in each of the client web projects in order to register a custom ADFM error handler implementation ( test.DynamicJDBCErrorHandlerImpl ). This error handler is designed to notice the DMLException thrown by a failed database connection attempt (due to incorrect username/password combination), and it throws that particular exception rather than simply caching it on the binding container. The second new feature employed is the ability to register a global customization to the ADF Page lifecycle by using a META-INF/adf-settings.xml file in each client web project. Each project registers the test.DynamicJDBCPagePhaseListener in order to conditonally execute some custom logic before the ADF "prepare model" phase of the lifecycle. This custom logic references the data controls in the current page definition, causing them to be checked out of the AM pool (if they were not already checked out during the current lifecycle) before the JSF page rendering begins. This allows the error handling code to catch the failed connection attempt in time to redirect the user to the login page before the rendering phase begins. The web.xml file for each ViewController project contains a context parameter ( RedirectToLogin ) that defines the login page to redirect to for that particular web application. The JSF project contains a second context parameter FacesURLPattern as well. Due to Bug# 5080057, setting the jbo.ampool.sessioncookiefactoryclass property in the configuration is not correctly saved to the bc4j.xcfg file. So, in order to configure a custom session cookie factory class as required to repurpose the code in this example in your own projects, you'll need to hand-edit the bc4j.xcfg file to insert the child element test.DynamicJDBCSessionCookieFactory inside the appropriate element for the configuration in question.
- 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!
- 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.
- This example illustrates one technique for causing the current page, containing a "Browse Employees" table, to refresh upon returning from a popup dialog wherein the user has added a new employee. The onReturnFromDialog() in the BrowseEmployees backing bean is configured as the ReturnListener for the button. It calls a refreshCurrentPage() helper method to accomplish the page refresh. It works in combination with setting the partialSubmit property and the useWindow properties to true on the (Add New Employee) button in the page. The onSaveNewEmployee() method is required for the ActionListener on the (Save New Employee) button since we want to conditionally return from the dialog, only when no errors occur during the execute operation on the "Commit" action binding. Using the declarative , 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 a SearchPage.jspx built using the technique described in section 18.3.5 How To Create Search and Results on the Same Page of the ADF Developer's Guide for Forms/4GL Developers that has been enhanced with a small amount of backing bean code that customizes the ADF page lifecycle to add a JSF FacesMessage in case the EmployeesResultsIterator returns either no rows or too many rows (with the limit hard-coded for this example to 10). The SearchPage backing bean inherits from the BackingBeanBase class as described in section 10.5.4.3 Using Custom ADF Page Lifecycle to Invoke an onPageLoad Backing Bean Method of the Dev Guide (simplified slightly by using my favorite EL helper class). The rendered attribute on the af:table showing the search results in the SearchPage.jspx uses an EL expression to cause the table to render only when the number of rows found is between 1 and the maximum allowed (10).
- 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. The NonDatabaseConnectionStrategy is a custom connection strategy class . The CustomSessionImpl is a custom session class, which returns a custom transaction handler factory. The CustomTxnHandlerFactoryImpl is a custom transaction handler factory used to return an instance of the custom CustomTxnHandlerImpl class, which is a custom transaction handler implementation. The SessionClass 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. The PoolClassName configuration property is set to the name of the custom application module pool implementation class. This class overrides the isSupportsPassivation() method to return false, indicating to the runtime that this particular application module pool does not support passivation. The jbo.ampool.connectionstrategyclass configuration property is set to the name of the custom connection strategy class which overrides the createApplicationModule() method to set some key properties in the environment hashmap before calling super. The StaticVO is a static view object that returns rows whose data is in the ModelBundle.properties file.
- 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.
- The af:convertNumber tag supports a number of attributes that allow you to customize the detail error message when conversion fails. For the basic number conversion failure, this attribute is named convertNumberMessageDetail . In order to reference a resource bundle message, normally you would expect to be able to use an f:loadBundle tag in your page to define a variable for a Map of the resource bundle strings, and then reference the message using an EL expression like # . The complication is that the resource bundles loaded with loadBundle are only available during the page rendering phase, but not during the validation phase. So, in order to drive the convertNumberMessageDetail from a message bundle, I needed to borrow some of the code from the JSF reference implementation's loadBundleTag class that exposes a resource bundle as a Map, and I put it in the AppliationMessageMap managed bean class in this example. I've configured that to be a session-scoped managed bean and configured its basename managed property to have the value view.resources.JSFMessages in faces-config.xml . This allows me to reference my custom error message for "Field 2" in the demo, in its f:convertNumber tag's convertNumberMessageDetail attribute using the EL expression AppMessages.messages.NOT_A_NUMBER . To see the custom error message, try typing a value like "adf" into Field 2 and clicking (Submit). You can run the demo with your browser set to prefer "Italian [it]" to see the custom error message translated in Italian.
- 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.
- A common requirement in pages containing table, tree, or treeTable components is to allow the user to select multiple rows and then carry out some operation on the selected rows. This example illustrates the best-practice declarative approach to accomplish this. First of all, notice that the code that processes the rows is correctly encapsulated inside the AppModule application module's custom java class, and that both the processSelectedEmployees() and processSelectedDepartments() methods are exposed on the client interface so they are available for declarative data binding in the data control palette. Notice they these accept a java.util.Set (which we expect at runtime to contain oracle.jbo.Key objects. The reason we're not using Java generics like Set in the method signature is that the ADFBC client interface mechanism does not yet support using generics in the method signature. The implementation of these methods processes the set passed in, casting each object in the set to a Key and then using the findByKey() on the appropriate view object instance in the data model to find the row by its key and then act on it. There are two pages in the demo view1.jspx and view2.jspx . Start by looking at the view2.jspx page, which includes a table of DeptView rows from the view object instance named Departments . Importantly, notice that to enable the multi-select on the table three required steps have been taken: (1) The rowSelection attribute is set to " multiple ", (2) the selectedRowKeys attribute has been removed, and (3) the selectionListener has been removed. Steps (2) and (3) are automatically setup to support single-row selection and must be removed whenever you enable multiple row selection in the table, or else the multiple selection will not work correctly. The custom processSelectedDepartments method was dropped from the Data Control Palette onto the page as a button, and the EL expression for the method argument is set to $ which makes use of a generic helper backing bean that the ViewController project includes to simplify working with multiple selection in tables, trees, and treeTables. The View2 backing bean is defined in adfc-config.xml and rather than using a specific backing bean class for the View2 page, its using the generic helper class MultiSelectSupportBackingBean . That bean conveniently contains a property named myTable of type RichTable which is designed to be referenced by the binding property of a page containing a RichTable where you'd like to perform some processing on its multiple-selection. In fact, if you look at the binding property of the af:table component in the view2.jspx page, you'll see that it's set to this property using the expression # . So the $ expression used as the parameter value of the declarative method action binding accesses the selectedAdfRowKeys Map-valued property of the backing bean, passing the View2.myTable instance of the RichTable on that page as the map key. As you can see in the MultiSelectSupportBackingBean class, the selectedAdfRowKeys is an anonymous subclass of java.util.Hashmap that overrides the get() method to perform a custom operation when the EL expression evaluator tries to access the map's properties. In effect, this pattern allows us to introduce something that works like a custom function that accepts one argument into our EL expressions. In this case, the argument is the UI component for which you'd like a Set of selected Keys. The view1.jspx page shows the same generic MultiSelectSupportBackingBean class in use as the page's View1 backing bean, and three different instances of method action bindings in the page definition for view1.jspx are used to invoke the processSelectedEmployees() custom method with the appropriate UI component passed as the "argument" to the EL expression to reference the Set of selected Keys. A last thing to note about the example is how the EmployeeHierarchy view object instance in the data model is setup. Notice that the EmpView view object defines a view criteria named EmployeesWithNoManager that finds employees that have a Mgr attribute equal to null. The EmployeeHierarchy view object instance was added to the data model in the application module editor, then I used the (Edit) button just above the Data Model tree to edit that view object instance to apply the EmployeesWithNoManager view criteria to it. This means that initially the view object will only show employees with no manager (e.g. KING). Then, due to the presence of the test.model.links.Manages view link between EmpView and itself, based on the Empno->Mgr relationship, the direct reports of the employees with no manager will appear as children in the tree and treeTable due to the related tree binding rules that uses the DirectReports view link accessor attribute to access the nested child collections of direct reports rows at each recursive level. Notice as well that there are no view link instances required in the data model to work with the tree or treeTable since the related tree bindings use the view link accessor attributes to get detail information, and not data model view instances linked via view link instances in the data model. I highly recommend reading section 35.1.3 Understanding View Link Accessors Versus Data Model View Link Instances to help understand the important distinction.
- 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. Its Model project contains a test.Dept entity object, test.DeptView view object, and a test.AppModule application module containing an instance DeptView1 of test.DeptView . Its ViewController project contains a Departments.jspx page with the data entry form. The Model project contains a ADFBC deployment profile to deploy the ADFBC components as a simple java archive. The ExtendsAndSubstitutes workspace contains a ExtendsProject project which has imported the test.Dept entity from the simple ADFBC JAR archive created in the other workspace's Model project. It then has created an extended entity object extendsproject.DeptEx which extends the test.Dept entity, overrides its Loc attribute, and adds an attribute-level validator on Loc to prevent the value from being the single, uppercase letter "X". The ExtendsProject.jpx defines the component substitution metadata saying that dept.Dept should be substituted with extendsproject.DeptEx . This metadata was defined using the Substitutions detail panel of the Business Components project properties. In addition, the Extends Project contains a file ExtendsProject.cpx to workaround bug 6629321, whose contents can be anything as long as it is a well-formed XML file. In the example, the workaround file contains the single element . The ExtendsProject project contains another ADFBC deployment profile to deploy the extended components as a simple JAR archive file. Finally, the ViewController project adds the runtime Java VM argument in its Run/Debug profile of -DFactory-Substitution-List=ExtendsProject to use the ExtendsProject.jpx file found in the classpath at runtime as the component substitution list. The ViewController project also includes a project-level library defined to include the two simple Java archive files for the extended components. To see the effect of the substituted components, run the Departments.jspx page and try to enter the value of "X" for the Loc attribute of any row in the DeptView view object's results and press (Commit). You'll see the validation error added by the substituted extendsproject.DeptEx component to know that the component substitutions are working.
- Illustrates binding an array of strings as the value of a view object WHERE clause bind variable, leveraging the Oracle database's CAST AS operator to achieve a variable number of values in a SQL IN clause by treating the values in the array as a nested table. Run the CreateTableOfVarcharType.sql script before running the example, which features example of using view objects with both the Oracle Positional and Oracle Named bind variable styles. The latter includes a workaround in the EmpViewWithNamedBindingStyleImpl class' overridden create() for Bug 5849504, where the view object editor fails to correctly test the syntax of the SQL statement involving an array-valued named bind variable and the TABLE and CAST AS clauses.
- This example illustrates an approach to take an array of structured information and bind it into a view object query as one of the tables in order to produce a database join between the static information and the database data. The context in which this example arose was that a service call was returning a list of ranked/scored primary keys, that then needed to be joined with the database table to which the primary keys referred in order to produce a friendly display for end-users that includes more descriptive information about the ranked rows. You'll need to run the CreateTypes.sql script before using the demo to create the SCORED_KEY and SCORED_KEYS types in the database. The ViewObjectImplWithScoredKeyBindVariable framework extension class centralizes the code required to work with the bind variable of type oracle.jbo.domain.Array . In this case, its code is binding the SCORED_KEYS type (which is a TABLE OF SCORED_KEY ) as an Array of SCORED_KEY types. Both the ReadOnlyScoredEmployees and EntityBasedScoredEmployees view objects inherit this helper code from this class. The setScoredKeysArray() method in the custom view object class of both view objects calls the helper method newScoredKeysArray() in the superclass to create the Array of STRUCT and set the value of the view object's bind variable. It expects to receive a List of Map objects, expecting each Map in the List to contain Map keys "Score" and "Key". The view objects both use the JDBC positional binding style, indicating the (zero-based) integer position of the bind variables as additional metadata in order to still work with the bind variable as a named bind variable in the view object API's. Run the TestClient class to see the results of joining in the static data with the EMP table.
- 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 definition test.ValidationViewObject , configured to have the VarModulo value set to 3, and CheckDivisibilityBy7 based on the same view object, configured to have the VarModulo value set to 7 The attribute-level Groovy validator on the Sal attribute sets the value of the VarValue bind variable on the view accessor, then executes the query. It returns value if the view accessor's first() 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 called AttrLevelViewAccessorValidator . I've used an instance of it on the Comm attribute, declaratively configuring the validation rule beans two properties: attrNameToBindNewValueTo = "VarValue" and viewAccessorName = "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 than DUAL , 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 a CustomViewObjectImpl framework extension class that adds an interesting feature to any view objects that extend it. It allows such view objects to have named bind variables whose value will be automatically derived from an attribute in the current row of another view object. In the example, the Globals view object is a transient view object with no query, one updateable Number attribute named DepartmentNumber , and a max fetch size set to zero ("No Rows" setting on the "Tuning" panel). The ExampleModule application module overrides the prepareSession() method to insure there is a blank row in the "Globals" view object instance. The Employees view object has a named bind variable TheDeptno that has a bind-variable-level custom metadata property named VOAttributeReference set to the value Globals.DepartmentNumber . Alternatively, the implementation supports setting the view object bind variable to an expression at the view instance level by setting an application module custom property named *ViewInstanceNAme*_*BindVariableName*_VOAttributeReference . This allows you to use the same view object multiple times and have different automatic value expressions for different view object instances. At runtime, the CustomViewObjectImpl 's overridden bindParametersForCollection() method detects any named bind variables with such a custom property set, evaluates the value of the indicated attribute in the current row of the named view object instance, and automatically binds that evaluated value for the bind variable's value. The view object's query has a WHERE clause that accommodates the value of the bind variable bind both NULL or non-NULL. When you run the JSF page, type in a department number and click (Execute) to narrow the list down to only those departments.
- This example illustrates how to conditionally trigger the automatic execution of an component's search when certain conditions are true about the values the user has entered into the search form. Run view1.jspx . After selecting a value for Dname and Loc in the search form, the query is automatically executed without the user's having to press the (Search) button. The View1Bean is the backing bean for the view1.jspx page in the example. The component's queryOperationListener property is set to an EL expression that "wires" it to fire the onQueryOperationPerformed 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 the Dname and Loc view criteria items. If it notices that the user has filled in both criteria items, then it creates a new QueryEvent and queue's it up for the same component on which the QueryOperationEvent is firing. To ensure that the search form renders the Dname and Loc items in the search form with their autoSubmit property set to true, the autoSubmit UI hint is set to true on both Dname and Loc attributes in the DeptView view object.
- This example illustrates a technique to avoid having a view object's queried rows cleared on rollback. There are three view objects in the project, one named DeptView which is an entity-based view object, one named DeptViewNonEntityBased which is a read-only, non-entity-based view object, and one named TransientViewObject that is programmatically populated and not based on a query. For read-only SQL-based view objects and transient view objects, you can prevent a rollback from clearing the view row cache by overriding both the beforeRollback() and afterRollback() method and commenting out the call to super . For an entity-based view object, you need to override these two methods as well as call the setClearCacheOnRollback() method on the oracle.jbo.Transaction interface, passing false . Note that this technique applies only to queried rows and not to newly added rows. This is due to the fact that during a rollback, as noted in the state diagram in section 9.2.5 Understanding Entity Objects Row States of the ADF Developer's Guide for Forms/4GL Developers, any entity object with 'New' status is removed (which transitions its status to 'Dead'). Note that the TransientViewObject is populated by the prepareSession() method of the application module, and that on its "Tuning" panel in the view object editor it is set to never query rows by using the "No Rows" setting in the "Retrieve From Database" section. This is equates to declaratively setting the max fetch size of the view object to zero.
- 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.
- 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.
- 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.
- 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 the DEPT_WITH_BOOLEAN table, then run Example.jspx . When you commit, the "T"/"F" value in the SELECTED column in the table will reflect the change to the selected radio group button.
- This example illustrates a TestPage.jspx with a tree binding based on a Departments view object instance of type DeptView . The WorksInDeptLink view link defines a view link accessor attribute named EmpView that is used by the tree binding to access the detail rowsets of employees for each department. The DeptView view object defines a custom method named setLowHighSalaryRangeForDetailEmployeesAccessorViewObject() that is exposed on the view object's client interface. The TestPage.jspx includes a declaratively-bound parameter form for invoking this method, passing in values for a low-salary and high-salary range. This method accesses the view object instance that the system creates at runtime to support the view link accessor accesses, and sets the values of the two named bind variables defined by the EmpView . The DeptViewImpl class also contains an overridden createViewLinkAccessorRS() method that applies the bind variable values to each view link accessor rowset created. Run the TestPage.jspx page and enter values for the low and high salary range you want to see for employees in the tree. For more information on the difference between the view object instances in the application module's data model and the system-created view object instance used to provide the view link accessor attribute rowset, see 27.1.3 Understanding View Link Accessors Versus Data Model View Link Instances.
- Referencing UserData Map Values from View Object Bind Variables in Groovy [11.1.1.0, SCOTT schema] 27-JAN-2009
- This example includes a SessionHelper class to simplify referencing entries in the ADFBC session's userData map from the Groovy expressions providing the default values for bind variables. The user data map is referenced via EL expressions in the two JSPX pages, and it is referenced in Groovy bind variable expressions in two places: (1) at the AM data model level for the VO instance named AnotherInstanceOfQueryWithBindVarValue (which you can see by selecting the VO instance in the Data Model list and clicking the (Edit) button, and (2) on the view accessor named QueryWithBindVarValue1 of the EmpView view object. This latter view accessor is used by the LOV definition on the EmpView view object's Mgr attribute. To try the application, run the SetUserMapValue.jspx page, type NameFilter into the setUserMapValue_key field, and (for example) the letter S into the setUserMapValue_value field, and click (setUserMapValue). The table in the page updates to show an example of a data model view object instance using the bind variable value from the userData Map. Clicking on the (GoTo Page Referencing Session Value in LOV Bind Var) button takes you to a page where the search form shows that the view accessor's rowset (based on the same QueryWithBindVarValue view object) is using the bind variable value from the userData map as well. The Groovy expressions that access the userData map use the helper class via the expression test.model.SessionHelper.userData(adf.object).NameFilter . A future release of ADF will make it simpler to reference the ADFBC session object without the need for a helper class.
- 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 the DEPT table named DEPT_WITH_FLAG that has one additional FLAG column whose valid values are "Y" or "N". The DeptWithFlag EO indicates a UI hint on its Flag attribute to indicate that it prefers to render as a "Checkbox". Dragging and dropping the DeptWithFlagView1 data collection from the data control palette as an "ADF Table", JDeveloper infers the correct selectBooleanCheckbox control for the Flag 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 the Flag attribute, indicating the values of "Y" for selected and "N" for unselected. With the view1PageDef page definition as the active editor, I expanded the DeptWithFlagView1 tree binding, its nodeDefinition folder, and the AttrNames folder inside it to select the Flag attribute of the tree binding node definition. Then, using the Property Inspector, I set the value of the Binds property of this Flag attribute name element to "Flag" (without quotes), which references the name of the button binding created above.
- The example illustrates how to create a JSF parameter form for calling a PL/SQL stored procedure. You'll need to run the supplied CreatePLSQLPackages.sql script to create the PL/SQL package named example_pkg used by the demo. This package contains a single procedure do_something which accepts a string parameter, number parameter, and date parameter and inserts these values into a new row in the EXAMPLE_PKG_TABLE table. In the J2EE application, the stored procedure invocation is encapsulated inside the business service inside the custom application module method collectDataUsingStoredProcedure . It accepts one string parameter, one number parameter, and one date parameter. Internally the method calls the stored procedure using the helper routine described in section 25.5.2 Invoking Stored Procedure with Only IN Arguments of the developer's guide. This custom application module method is published on the client interface as described in section 8.4.1 How to Publish Custom Service Methods to Clients. The JSPX page in the ViewController project was created by dragging the collectDataUsingStoredProcedure from the Data Control Palette and dropping it onto the page as an ADF Parameter Form. The page defintion variables get automatically cleared after each page submit due to a navigation rule that redirects back to the same page. The table below the input form was created by dropping the data collection named ExamplePkgTable from the Data Control Palette as a read-only table. Both the view object attributes and the page definition variables are leveraging ADF UI control hints to supply translatable prompts and format masks.
- Shows the best practice technique for invoking a database stored procedure encapsulated behind a custom ApplicationModule method. Includes examples for invoking it both from an ADF DataAction (in the ViewController project) as well as a JClient button event handler method (in the SwingClient project).
- The EmpView view object in this example features two transient, Groovy calculated attributes. The attribute named ValueUsingVOFunction references a custom myFunctionAtVOLevel() method on the EmpViewImpl class, while the attribute named ValueUsingVORowFunction references a custom myFunctionAtVORowLevel() method on the EmpViewRowImpl class, in both cases passing in the value of the Sal attribute. The methods simply return the value passed in surrounded by either parenthesis or square brackets.
- This example illustrates how to provide a custom view row attribute hints implementation. The EmpViewRow class overrides the createViewRowAttrHints method to return a new instance of the EmpViewRowAttributeHintsImpl class (which extends the framework base class ViewRowAttrHints . In the EmpViewRowAttributeHintsImpl class, notice that we've overridden the getHint() API to conditionally return a value for user-defined attribute hints named "mindate" and "maxdate". These hints are coded to look at the value of the Hiredate in the current row, and return a date String that represents three days before that date for "mindate" and three days after that date for "maxdate". The class also overrides the getLabel API to customize the value of the "label" UI hint for the Job attribute. Run the TestPage.jspx and try to edit a "Hiredate" value. You'll see that the date picker only allows you to change the date to a date that is within a span of three days before to three days after the current value. This occurs due to the UI component's referencing the custom "mindate" and "maxdate" hints appropriately. Also, you'll notice that the label for the "Job" field is the default label with the value of the Sal attribute appended to it.
- This example illustrates a technique to allow the user to toggle the preferred UI locale between English and Italian by pressing a button in the UI. The CustomFacesPageLifecycle class is a custom ADF Faces page lifecycle class that overrides the prepareRender phase of the ADF page lifecycle to adjust the locale of the JSF UI View Root (from which the current user's preferred locale is derived for the rest of ADF at runtime). For more details about how its configured in the project see 10.5.4.1 Globally Customizing the ADF Page Lifecycle of the ADF Developer's Guide for Forms/4GL Developers. It references the App managed bean to see what the user's preferred locale is. In the overridden prepareRender method, if App.preferredLocale is different from the current UI View Root's locale, then the method sets the locale of the view to the preferred locale before calling super.prepareRender . If it ends up changing the locale, it also forces any List Binding objects with a translatable label for their null entry (like "") to have their list of valid values recalculated so the null entry will render in the new current locale. The TestPage.java backing bean sets the value of the App.preferredLocale to either ENGLISH or ITALIAN depending on the button you click. Notice that the JSF resource-bundle-based message strings change, as well as the ADF BC component UI hints that supply the strings for the table column titles and field prompts. Also, the AnotherPage.jspx page allows the user to change the value of a transient number attribute that was added to the entity object. The format mask of #0.00 is specified as part of the UI control hints at the entity object level and you can see that when in Italian a number like 3.45 is presented and edited using the locale-appropriate decimal symbol 3,45 . The regular JSP page RegularJSPPageNotUsingJSF.jspx in the project illustrates how a regular JSP page might test and set the JSF managed bean that holds the user's preferred locale setting. This might be interesting to understand if you are trying to allow the user to set their preferred language from a regular JSP acting as a login page in an otherwise-JSF-based application.
- This example illustrates a simple technique for supporting an editable checkbox in an ADF Faces table to allow toggling a persistent status flag on or off. Before running the example JSPX page, run the CreateTable.sql script in the Model project to create a SETTINGS table with three rows of example data. Since SQL does not have a native boolean datatype to use for the type of a column in a table, the STATUS column in the SETTINGS table is defined as NUMBER(1) with 0 representing false and 1 representing true. The example illustrates how you can introduce a transient Boolean -valued attribute StatusAsBoolean to work with the numerical true/false value as a Boolean. In the custom SettingsViewRowImpl row class, the getStatusAsBoolean and setStatusAsBoolean methods have been written to convert the numerical value to a boolean upon reading it and convert a boolean value to the correct Number value upon writing it. In the JSPX page in the ViewController project, the af:selectBooleanCheckbox is bound declaratively to the StatusAsBoolean attribute in the current row using the EL expression # . When you run the page, try changing the state of the checkboxes and clicking (Commit). Then from SQL*Plus, you can verify that the changed boolean checkbox states have been correctly saved as 0 or 1 appropriately.
- A customer asked how he could test whether an unmodified entity instance is consistent or not with the corresponding row in the database without having to first modify/lock the row and without updating the entity cache with the new values. These particular requirements meant that he couldn't use the built-in features that perform this comparison for you. This example illustrates a possible generic solution to this by constructing an on-the-fly, read-only view object to fetch the values of the persistent attributes in the entity and comparing their values with the current entity attributes. See the testConsistency method in the CustomEntityImpl class. Run the sample Form.java class and click on the (testConsistencyOfCurrentRow) button to try it out. The textConsistencyOfCurrentRow() method is a custom method the view object's custom interface which gets the current row, then delegates to it's testConsistency() method mentioned above. NOTE: this solution could be optimized by comparing only a "change indicator" column in the entity if it is marked and it also doesn't do any special treatment for LOB attributes whose comparisons you generally want to avoid due to their overhead.
- 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 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.
- This example illustrates how to programmatically clear the af:table component's filter fields. The test.jspx page's af:table component has its binding property set to expose the UI component in the TestPage backing bean as a property named table . The TestPage 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 the Dname 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 custom onTableQueryExecuted 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 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.
- 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.
- The base ADF product only distinguishes between warnings and errors, so there is no default way to get a JSF message with severity of INFO . This example includes a CustomErrorHandler class that implements handling for informational messages. The addInformationMessageTest() method in the AppModule custom java class adds an informational message by using the addWarning() API, passing a custom subtype of JboWarning called InformationalMessage . Due to the way warnings are wrapped before they are passed to the custom error handler's getDisplayMessage() method by the ADF framework, the InformationalMessage constructor sets a value into the error parameters that the CustomErrorHandler uses to recognize the warning subtype as an informational message. The overridden getDisplayMessage() method in the error handler class detects whether the exception is an informational warning, and if it is, it adds an informational message to the FacesContext. It uses the setProperty() and getProperty() API of the JboWarning object to set a flag it can use to detect whether the exception has already been reported by this custom mechanism. This is required because ADF will invoke the getDisplayMessage() two times for each exception reported, later only one of which gets reported to the user. Run the Page.jspx to try the example. To see an error be reported, enter a salary of 5002 and click (Next). To try a warning, enter a salary of 5001 and click (Next). To see an informational message, click the (addInformationMessageTest) button. Notice that the custom error handler class is declaratively configured via the ErrorClass attribute on the root element of the DataBindings.cpx file (which shows as the ErrorClass property of the root element in the Property Inspector.
- This example shows a custom ListOfAccounts domain that implements the necessary interfaces to allow its contents - a list of Account beans - to be passivated and activated correctly to the application module persistent state snapshot. It shows a combination of required aspects including implementing the XMLDomainWriter and DomainInterface interfaces, as well as containing a public static getXMLDomainFactory() method that returns an instance of a class that implements the XMLDomainReaderFactory and XMLDomainFactory interfaces. The ExampleTransientView in the project is a transient view object with one String -valued attribute marked as the key attribute, and another ListOfAccounts attribute of type model.types.common.ListOfAccounts , our custom domain. Both of these attributes are marked as updateable and have their "passivate" property set to true. This view object's create() method contains the best practice code required for a transient view object that will be programmatically populated by creating and inserting rows. Run the TestClient class to exercise the creation of two rows in the transient view, passivating the transient state, releasing the application module, acquiring a new application module, activating the passivated state, and iterating the transient rows again.
- 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.
- This example illustrates a TestPage.jspx page with an af:table component whose selectionListener property has been modified from the default EL expression dropped when the table was created, to instead call a selection listener method named onTableSelectionChanged() in the TestPage backing bean. This default EL expression normally looks like # which declaratively "wires" the table selection event to invoke the makeCurrent() method on the CollectionModel of the table binding. In order to preseve the default data binding functionality that reacts to the table selection change, this backing bean method uses the invokeMethod() helper method of the EL helper class to call the default functionality with custom code before and after it. The EL helper class is in the FwkExtensions project, which is marked as a project-level dependency.
- This example shows a technique to include a checkbox in a declaratively-defined LOV's search form which toggles on or off a custom SQL fragment's being applied to the search. In this simple example, we use the checkbox to allow the user to limit the LOV search results to only include departments whose id is a multiple of 20 (or not). The ViewController project includes a simple view1.jspx page with a default ADF Form dropped for the EmpView. The Deptno attribute of the EmpView defines an LOV that references a view accessor based on DeptView . The DeptView view object has an additional SQL-calculated attribute named ExtraAttr of type Boolean . The SQL expression for the attribute is just the quoted string 'FALSE'. There is a view criteria named LOVSearchCriteria defined on DeptView and it includes view criteria items for Dname , Loc , and ExtraAttr . The ExtraAttr has the following UI hints defined: Label Text is set to 'Show Only Multiples of 20?'; Tooltip Text is set to some helpful text, and Control Type is set to 'Checkbox'. The DeptView view object uses the CustomViewObjectImpl class as its base framework class, and so the DeptViewImpl custom view object class extends that CustomViewObjectImpl to inherit a few helper methods. The base CustomViewObjectImpl overrides the getCriteriaItemClause() framework API invoke two other methods getCriteriaItemClauseForDatabaseUse() and getCriteriaItemClauseForCache() to customize the SQL fragment returned for a particular view criteria item. The DeptViewImpl class overrides these two methods so that if the view criteria is "LOVSearchCriteria" and the view criteria item is "ExtraAttr" and beging asked for the fragment to use for database filtering, then we return the SQL fragment "MOD(DEPTNO,20)=0" if the value of the view criteria item is Boolean.TRUE, otherwise we return the harmless "1=1" predicate. For the in-memory cache fragment, we override the other method and return "1=1". Run the form, click the dropdown list on the combobox and click on the "Search. " link to access the popup LOV dialog. You'll see that if you check the checkbox, then only departments whose id's are multiples of 20 appear in the list, otherwise they are not restricted by this additional (custom) criteria.
- This example illustrates an interesting technique (that I initially learned from the always-clever JHeadstartteam). The CustomFacesPageLifecycle class is registered in the faces-config.xml file as an application-scoped managed bean named PageLifecycle (the name is arbitrary, of course). The CustomADFPhaseListener class is registered in the "Life Cycle" section of the faces-config.xml as well. Its overridden createPageLifecycle() method uses the EL helper class to return the custom page lifecycle class using the method EL.get("#") . Why would you want to do this, you ask? The TestPage.jspx illustrates two simple examples (and there may be more). The (Some Button) on the page has its Action property set to the EL expression # , illustrating that the custom lifecycle class (being EL-accessible) can have global helper routines like an action listener method. Another example is the Dname af:inputText fields whose Value property is set to the EL expression # . This shows that the helper routines in the custom page lifecycle class can leverage a customized Map approach to effectively provide simple, one-argument callable methods. In this case, the getAttributeBindingWrapper map wraps the AttributeBinding passed in as an argument. The second of the two Dname inputText's shows that by wrapping the attribute binding in this way and setting the Disabled property to true, you can get an inputText that shows as a disabled field instead of a read-only label which is the default rendering of read-only inputText fields.
- 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.
- 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.
- 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.
- 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.
- Section 9.4.1.2 Eagerly Defaulting an Attribute Value from a Database Sequence from the ADF Developer's Guide explains the two lines of code you would add to an overridden create() method of your entity object to programmatically populate its primary key attribute from a sequence at row-creation time. Even though this is only a couple of lines, if many of your entity objects have sequence-valued primary key attributes and you are not using database-trigger-assigned sequence values (described in section 6.6.3.8 Trigger-Assigned Primary Key Values from a Database Sequence), then you might be interested in a more generic, metadata-driven solution. This example illustrates a simple CustomEntityImpl framework extension class on which both the Dept and Emp entities in the sample are based. It's overridden create() method tests for the presence of a custom attribute-level metadata property named SequenceName and if detected, populates the attribute's default value from the next number in that sequence using the same basic code as above. The Dept entity defines the custom SequenceName property on its Deptno attribute with the value DEPT_TABLE_SEQ , while the Emp entity defines that custom property on its Empno attribute with the value EMP_TABLE_SEQ . The supplied CreateDeptAndEmpTables.sql script creates the tables and sequences for you.
- This example contains a single EmployeeAllInfo view whose SQL mode is set to use the new-in-11g setting of 'Declarative'. It contains one editable Employees entity usage, and six additional reference entity usages showing related information about the employee's department, the department's manager, the department's location, the department's region, the employee's job, and the department's country. When a view object is in declarative mode, its SQL statement is determined at runtime instead of at design time. Attributes in the view object can have their Selected in Query property set to false, and these attributes will only be selected if they are referenced by the page definition for the current page, otherwise they will be left out of the query. When multiple entity usages are involved, if all the attributes from a given entity usage are left out of the query, then the ADFBC runtime "prunes" that table related to that entity usage out of the query and does not perform that join. The application module in the Model project includes three different instances of the same EmployeeAllInfo view object. You can observe the different runtime queries performed by the three different JSPX pages by looking in the log while performing a search in each page. The file Queries.txt included in the ViewController project contains a formatted version of the different queries. You can see in the query for the MinimalEmployeeInfo.jspx page, that only the EMPLOYEES table is included. In the query for MediumEmployeeInfo.jspx you see EMPLOYEES , DEPARTMENTS , EMPLOYEES (a second time for the manager), and JOBS . The query for the final page joins all of the tables.
- 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 # attribute, and on the value of a # attribute. The # flag is set declaratively using an on the (Create) button in the Browse.jspx page. The example works by using a backing bean property to "decorate" the normal Loc attribute binding. If certain conditions are true, then the getLoc() method in the backing bean returns the value of the session variable instead of returning the normal value of the Loc binding. Try setting the session value to some value, then experiment with clicking on the different buttons in the browse page to show the defaulting occurring or not occurring as inidicated on the button labels. We adopt this approach instead of trying to programmatically set the binding immediately to the conditional controller-layer default value so that we don't cause the new row to change from its initialized status to a "new" status (which will add it to the rowset. See section 10.4.4 What You May Need to Know About Create and CreateInsert in the developer's guide for more information on this.
- 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.
- 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.
- The EL expressions used in the rendered property of several components in the FindDepartments.jspx page in this example use the queryPerformed property of the search binding to conditionally hide the results table until the user has performed a query. In addition, the same property is used to conditionally show an 'Enter some criteria. ' message or a 'No departments found' message as appropriate. For more information about the declarative options the search binding supports, see the section entitled 'Changes to search form binding default behavior since Technology Preview 4' in the JDeveloper 11g release notes.
- This example contains a DEPT -based view object presented in both a table and a form display. The (Create), (Delete), and (Rollback) buttons are set to have their immediate property to the value true which causes validation to be circumvented. There are two functionally-identical JSPX pages, one which programmatically calls resetValue() on the Faces UI components in the backing bean to cause their values to be refreshed, and the other which uses the to accomplish the same thing declaratively.
- 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 tag that's generating the set of choices for the selectOneChoice dropdown list in each row of the table. Its value attribute is set to the EL expression # . This syntax accesses a backing bean property named lovList and if that property is a Map , then the EL resolver will call the get() method on the Map -valued property to access the entry with the key equal to the expression row.DepartmentId inside the square brackets. By implementing the lovList property in the backing bean as an anonymous subclass of java.util.HashMap with an ovverridden get(Object key) method, we can intercept the attempt to access the Map entry with the key of the current row's department id, and instead have its value come from an invocation to an application module method that returns the correct set of employee choices for that current department. Not a totally obviously technique, but I've included further comments in the code that explain more of the implementation details.
- This example illustrates a servlet that dumps application module pooling statistics and/or ADFBC database connection pooling statistics to the browser. The DumpPoolStatisticsServlet is configured in the web.xml to map to the URL /DumpPoolStatistics . The DumpConnectionPoolStatisticsServlet is configured in the web.xml to map to the URL /DumpConnectionPoolStatistics . In contrast to using a JSP page to dump these statistics, using servlets configured this way instead avoids engaging the ADF Binding Filter, the ADF Faces filter, or the ADF Faces servlet when viewing pooling statistics. Run the EditEmps.jspx and click (Next) or (Previous) a few times. Then click the "DumpPoolStatistics" and/or "DumpConnectionPoolingStatistics" links in the page to open a new browser window with the pooling statistics. Recall that if your ADF application using J2EE datasources instead of a JDBC URL connection, then you will be using your application server's connection pool instead of the ADFBC connection pool. In that case, the database connection pooling statistics won't appear using this mechanism. CAVEAT: the connection pools are named using the fully-qualified JDBC connection credentials, which includes the password. We recommend using the DumpConnectionPoolStatistics servlet with care in a production environment and not leaving the configured permanently (unless you protect access to it with a password using HTTP authentication).
- After reading the OTN article How To Support Dynamic JDBC Credentials, several customers asked whether the same techniques will work outside of a Struts context. The ADF related code to support dynamic credentials is not dependent on Struts, but a tiny bit of the example code referenced a "main.do" in a place that made it only work for Struts. This example app illustrates the technique can work with both Model 1 or Model 2, including both JSP/Struts and JSF. The web.xml file for each ViewController project contains a context parameter that define the login page to redirect to for that particular web application. The JSF project contains a second context parameter FacesURLPattern as well. Due to Bug# 5080057, setting the jbo.ampool.sessioncookiefactoryclass property in the configuration is not correctly saved to the bc4j.xcfg file. So, in order to configure a custom session cookie factory class as required to repurpose the code in this example in your own projects, you'll need to hand-edit the bc4j.xcfg file to insert the child element test.DynamicJDBCSessionCookieFactory inside the appropriate 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).
- This example illustrates one technique for implementing a dynamic, data-driven parameter form. The Database project in the workspace contains CreateTables.sql and InsertData.sql scripts that define and populate four simple tables: PARAMETER_FORM_DEFINITION , PARAMETER_DEFINITION , PARAMETER_CHOICES , and PARAMETER_FORM_ITEM_SET . See the database diagram in that project for a visual view of how they are related. The insert data script populates some sample data for two parameter forms named "Form1" and "Form2", each of which has some collection of parameters in its form item set. The ParameterFormItems view object queries the list of parameters for a given parameter form by its form id, which is passed in as a named bind variable ( TheFormId ). There is a view link defined between the ParameterFormItems view object and the ParameterChoicesView that enables a view link accessor attribute named ParameterChoices in each row of the ParameterFormItems view object's results. In the ViewController project, you will find three pages. The TestParameterForm.jspx page allows you to select any of the defined parameter forms and test it by setting the # attribute to the parameter form you've selected and navigating to the DynamicParameterForm.jspx page. That page is the real meat of the example. It includes a ADFM tree binding to expose the hierarchical collection of data for the ParameterFormItems and its collection of available choices (via the ParameterChoices view link accessor attribute). The page definition for this page includes an invokeAction that triggers the firing of an ExecuteWithParams action binding when the page is not handling a post-back ( RefreshCondition="#" ). This allows the ParameterFormItems view object's TheFormId named bind variable to be declaratively set to the value in the # attribute that defines which data-driven parameter form to show. The page defines uses an to iterate over the parameter form items. Inside this loop, it uses an based on the value of the DisplayType attribute of the parameter definition. The switcher determines whether to display the item as an inputText , a selectOneChoice (i.e. dropdown list), or a selectOneRadio (i.e. radio group) depending on whether the DisplayType of each parameter is ' I ', ' S ', or ' R ' respectively. In the case of rendering the parameter as a dropdown list or radio group, an inner accesses the nested collection of available choices defined to populate the list. The last part of the example involves understanding where the user's entered values are posted and stored. This is handled by a transient view object attribute named UserValue that has been added to the ParameterFormValues view object. The ShowUserEnteredValues.jspx page renders the parameters along with the user-entered values, and the DynamicParameterForm.java backing bean class contains code that illustrates how you would access the values of the users parameter item values in the backing bean if needed. For extra credit, you can use the ADF Business Components Tester on the ParameterFormModule to maintain the parameter form metadata that drives the parameter forms, adding a new form, new items, or new item choices as needed.
- This sample works on the HR schema, but requires first running the supplied CreateAndPopulateCitiesTable.sql script to create and populate an additional CITIES table that it uses. The sample includes two JSF pages, illustrating two different styles of cascading poplists you might need to implement. Use the first style, represented by the CascadingLists.jsp page, when the driving list serves only to partition the set of choices in the dependent list. In that page, only the CountryId is actually an attribute of the LocationsView row. The RegionId of the selected region is not present. On the other hand, use the second style, represented by the CascadingListsUsingTwoListBindings.jspx when both the driving list and the dependent list have to update the value of an attribute in the row being edited. In that page, a row in the CitiesView includes both a RegionId and a CountryId attribute. The CascadingLists.jsp page allows creating, updating, and deleting locations. The page has a "Regions" dropdown list and a "Countries" dropdown list. The Regions selectOneChoice is bound using a navigation list binding, and the Countries selectOneChoice is bound using a normal (LOV-style) list binding. The onRegionListChanged backing bean method fires for the ValueChangedEvent of the Regions dropdown, and simply sets a request-scoped attribute to signal that the user has changed the regions choice. This is a sign they want to be editing the the current row to be a country in a different region. The invokeAction in the page definition invokes an application module method during the renderModel phase ( Refresh="renderModel" ) if the request-scoped property just mentioned is not set. The onCountryChanged backing bean method fires for the ValueChangeEvent of the Countries dropdown, setting a different request-scoped attribute to signal that the user has changed the country choice. Since the navigation list causes the current row in the RegionsIterator to change based on the user's current selection, and since the Countries view instance in the data model is an actively-coordinated detail view based on the Regions master view, the changing of the current row in the Regions view automatically coordinates the Countries view to have the correlated set of countries for the new current region. The CascadingListsUsingTwoListBindings.jspx page uses two list bindings instead of having the driving this be based on a navigation list. The RegionId list gets its set of valid choices from the RegionsList in the data model. The CountryId gets its set of valid choices from the CountriesListForRegion view instance in the data model. This latter view instance is based on the CountriesListForRegion view defintion that uses a named bind variable ( TheRegionId ) in order to filter the list of countries by a region id supplied as a parameter. The lists use ValueChangeListener methods like the ones used in the other page. The difference in this example is what the refreshCountryListUnlessCountryChanging invokeAction invokeAction executable in the page def is doing. In this page's page definition, this invokeAction causes an ExecuteWithParams action binding on the CountriesListForRegionIterator to be triggered during the prepareRender lifecycle phase whenever the user is not changing the country. Notice that this invokeAction is sequenced after the iterator binding for CitiesViewIterator so that the value of the RegionId binding will reflect the up-to-date state of the current CitiesView row. That ExecuteWithParams action binding is configured to pass the value of the # as the value of the TheRegionId parameter of the view object. This ensures that the whenever the page is displayed the country list correctly reflects the current region. Both pages' page definition references the ConditionalValidationPageController class as described in section 10.5.4.2 Customizing the Page Lifecycle for a Single Page of the ADF Dev Guide in order to avoid validating the row if the page request was caused due to the auto-submit of the Regions or the Country poplists. Also, this custom page controller overrides the prepareRender() method to conditionally set the CountryId binding to null if the user is changing the region poplist, detected based on the presence of the request-scope RegionChanged attribute mentioned previously. Also note that the example contains a group of classes in the test.view.bug5930745 package to workaround Bug# 5930745 that causes a JSF selectOneChoice control to incorrectly display a blank entry when the value of a ADFM List Binding is null and it has registered exceptions. The ViewController project in this example also implements the same custom error handling code as example# 107 and contains a slightly-modified routine in its CustomFacesPageLifecycle class for "dirtying" the first updateable, mandatory attribute binding found to have a null value. This avoids skipping validation when the user tries to save the row without changing any values. **NOTE:**fortunately all of this becomes easy and declarative in JDeveloper/ADF 11g!
- This example illustrates the code necessary to programmatically create view definitions at runtime for dynamically-created SQL-based view objects to avoid the runtime DESCRIBE overhead that is associated with using the simpler API createViewObjectFromQueryStmt() . The TestClient program calls an application module's client interface method named createViewObjectAndViewLinks() . That method constructs two view objects instances and a view link between them. Then, the client code finds and iterates through the results of these view objects. Since we programmatically define the names and data types of the view object's attributes, ADF will not need to perform a runtime DESCRIBE (involving a round-trip to the database) to discover that information at runtime.
- This example illustrates how to implement an efficient existence check to enforce the uniqueness of a non-primary-key attribute. Using a Dept entity object based on the DEPT table, we assume that in addition to the Deptno primary key's uniqueness that is declaratively enforced using the ADF UniqueKeyValidator, we also want to enforce the uniqueness of the Dname attribute value. For the sake of argument, we assume we'd like the value to be unique in a case-insensitive way so that we won't allow one department called "Sales" while another is named "SALES". The DeptDefImpl class in this example implements an existsByDname() method following the technique outlined in section 9.6.2 Implementing an Efficient Existence Check of the ADF Developer's Guide for Forms/4GL Developers. This routine on the custom entity definition class uses the FindDeptByUniqueDname view object to test case-insensitively whether a row exists in the DEPT table with the supplied department name. If it doesn't exist in the database, it then searches the entity cache to detect whether perhaps another new instance created in the current transaction might already be using the candidate department name value, too. The Dept entity object class has an attribute-level method validator defined to trigger the validateDname() method in the DeptImpl class. This method gets the custom entity definition class and calls the existsByDname() method, returning true if the candidate department name does not already exist. See section 9.3.1 How to Create an Attribute-Level Method Validation for more information on creating an attribute-level method validator. You can use the ADF Business Components tester to verify that it's impossible to insert two departments with the same department name.
- This example contains two separate workspaces DeptADFBCWebService and EntityAndViewBasedOnWebService . The former contains two projects. The first is named Project and contains a simple DeptService application module, and a default Dept entity object, and entity-based DeptView view object. The application module has custom methods on its client interface like retrieveDepartmentData() , estimateCount() , findDepartmentByDeptno() , insertDepartment() , updateDepartment() , mergeDepartment() , and deleteDepartmentByDeptno() . The DeptService application module has been published as a J2EE Web Service as described in section 33.4 Publishing Application Modules as Web Services of the ADF Dev Guide. The second project in the DeptADFBCWebService workspace is a Tests project that contains JUnit tests to test both the application module's local client interface as well as testing the deployed web service. The tests should all succeed if you have run the supplied CreateEmpAndDeptTables.sql in the SCOTT account. The WAR deployment profile in the Project project deploys the web service to an external OC4J instance, which you can launch most easily by running the start_oc4j batch file (or shell script) in the ./jdev/bin subdirectory of your JDeveloper installation home directory. After deploying, you can test the web service by pointing your browser at the URL http://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort . Note that the web service unit test fixture makes use of a web service proxy class named DeptServiceSoapHttpPortClient that was generated using JDeveloper's Web Service Proxy wizard, using the WSDL URL of http://localhost:8888/DepartmentServices/DeptServiceSoapHttpPort?WSDL The second EntityAndViewBasedOnWebService workspace contains an HRModule application module, and default entity objects and view objects for the DEPT and EMP tables. The DeptImpl.java has overridden appropriate methods in a way similar to what is described in section 26.4 Basing an Entity Object on a PL/SQL Package API of the ADF Dev Guide to have this Dept entity based on a web service. Similarly, the DeptViewImpl.java class has overridden appropriate methods, similar to the technique described in section 27.8.4 How to Create a View Object on a REF CURSOR of the guide. When you use the Business Components Tester to test the HRModule - and you make sure you have the webservice in the other workspace deployed and currently running - you can work with the data in the EmpView and DeptView view object instances. When the data is read for the DeptView it will pull it in from the underlying web service. If you update the data for an existing department, create a new department, or delete an existing department, the changes are saved back using the web service in the other workspace. Also try using simple view criteria in the tester to search for department rows in the DeptView. That should work, too.
- 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 # 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.
- This example illustrates one way to use the lightweight JavaBeans event publish/subscribe mechanism that ADF Business Components supports for entity objects. The Dept entity in the project has published an event named OnDnameOrLocChanged . When you define a new event on the Publish tab of the Entity Object Editor, you indicate zero or more entity attributes that will be delivered as part of the event "payload" to any subscribed listeners. The event name is user-defined and your code decides when it will fire by calling the automatically generated method of the same named as the event. In this case, looking in the DeptImpl.java class, you can see that I've added a call to this OnDnameOrLocChanged() method inside the setDname() and setLoc methods. When you publish an event, in addition to the generated method used to fire the event, JDeveloper also generates code into a custom Entity Definition class for the entity publishing the event. If you look in the DeptDefImpl.java , you'll see generated methods to addOnDnameOrLocChangedListener() and removeOnDnameOrLocChangedListener . Other entities that want to subscribe to the event can do so programmatically by looking up the entity definition object of the publishing entity, casting it to the more specific custom entity definition class name, and then calling the add*EventName*Listener() method. The Emp entity in the demo declaratively subscribes to the OnDnameOrLocChanged event, indicating that the event should be delivered to all associated Emp entities based on a particular association that relates it to the publishing entity. Note that the method to be invoked to receive the notification must have a signature that matches the number, type, and order of the attributes delivered in the payload of the published event. Otherwise, you can choose to have the event only delivered to entities that have programmatically registered to receive the event using the methods mentioned above. If you test the AppModule application module and try changing the value of the Loc or Dname attribute of a department, you can observe in the JDeveloper Log window that the associated Emp entities in that department receive the notification.
- Illustrates the one-line of code needed in a custom entity definition object to indicate to the ADF framework that you don't want a particular entity object to use the RETURNING INTO clause when it tries to refresh-on-insert or refresh-on-update. The RETURNING INTO clause throws database-level errors when used in some kinds of database views having INSTEAD OF triggers. Also shows that you need at least one attribute in the entity other than the rowid marked as "Unique" to make the insert situation work correctly.
- 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 the StartPage and click the button to start the emp-task-flow task flow, passing in values for the task flows two parameters stringTaskFlowParam and intTaskFlowParam . In the TestPage.jspx that runs when emp-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 the TestPage 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 the Configuration.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 the StartPage captures and passes parameters to the task flow, read on. The initial StartPage.jspx uses page definition variables named pageDefStringVariable and pageDefIntVariable 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 named variables and pick the pageDef variable name whose value you want to bind to as the attribute name. The af:inputText fields in the StartPage bind to this attribute bindings using the EL expressions # and # . The button on the StartPage contains two nested af:setActionListener components to assign the values of the pageDefinition variables collected from the user into two request-scope attributes. The value of # is assigned to # , and similarly the value of # is assigned to # . The task flow call activity named emp-task-flow in the adfc-config.xml unbounded task flow is configured to assign the values of the task flow parameters from these request-scope attributes. The stringTaskFlowParam task flow parameter gets its value from the # , while the intTaskFlow param gets its value from the # . As part of its parameter definitions, the emp-task-flow itself defines pageFlowScope attributes that will hold the values of the task flow input parameters for the duration of the task flow. The stringTaskFlowParam parameter value is stored in the attribute # while the intTaskFlowParam is stored in the attribute # . 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.
- Section 9.9 How to Access Original Attribute Values in the ADF Developers Guide for Forms/4GL Developers explains the getPostedAttribute() API you can use to access the value of any attribute as it existed at the beginning of the current transaction. This example illustrates a technique for exposing that API in a generic way to the ADF binding layer so that your application pages can display that original value to the end-user. This could come in handy to allow the user to visually review their pending changes in the transaction before finally confirming to save the changes with a (Commit) button. In the Model project, The technique involves: (1) exposing the getPostedAttribute() API as public in a CustomEntityImpl framework extension class since otherwise the method would be protected, (2) automatically adding a "shadow" attribute named *OrigAttrName*_orig for each attribute in the view object (in the overridden create() method of the CustomViewObjectImpl class, and (3) returning the original value of the appropriate underlying entity attribute using getPostedAttribute() in an overridden getAttributeInternal() method of the CustomViewRowImpl class. The Dept entity is configured to use the CustomEntityImpl and the DeptView view object is configured to use the CustomViewObjectImpl component class and the CustomViewRowImpl row class. In the ViewController project, the technique involves referencing the " _orig " attribute names in the EL expressions for the values of certain UIComponents. Try navigating through multiple rows in the DeptView and making changes to the Dname and or Loc attributes in any of them. As you scroll back and forth before issuing the final transaction commit, you will notice that the previous value of the changed attributes appear next to your modified values wherever you've modified them.
- 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.
- The EmpView view object in this example features a WHERE clause with a "reverse" CONNECT BY expression to identify parent employee rows that match the Ename search criteria. The START WITH clause filters employees in a case-insensitive way based on the value of the varEname bind variable. The built-in ExecuteWithParams operator for the EmpView was dropped onto the page as a parameter form to declaratively apply the user's search filter and re-execute the query. The EmpViewImpl custom view object class overrides the framework's createViewLinkAccessorRS() method in order to set the value of the varEname bind variable from the EmpView1 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 the FilteredTreeShowingInterimNodes.jspx page, the automatically-created ExecuteWithParams_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, the TracingViewObjectImpl framework extension class instruments the bindParametersForCollection() method to dump useful information about each query executed. The EmpView view object specifies this class as its framework base class.
- The EditDepartment.jspx page in the example allows the user to edit a row in the DEPT table. A button on that page has its Action property set to dialog:selectDepartment and has its useWindow property set to true so that it invokes a modal, popup dialog containing the page SelectDepartment.jspx . The commandButton on that page contains a nested af:returnActionListener component whose value is provided by the EL expression # . That will evaluate to the string format of the current row's key (described in more detail in section 10.5.6 Understanding the Difference Between setCurrentRowWithKey and setCurrentRowWithKeyValue of the ADF Developer's Guide for Forms/4GL Developers.) The onReturnFromSelectDepartmentDialog return listener method in the EditDepartment backing bean shows how to process the selected key value returned from the dialog and to set that row as the current row for editing, followed by forcing the calling page to refresh.
- This example illustrates a framework extension class CustomViewObjectImpl that overrides the bindParametersForCollection method to conditionally uppercase any String-valued bind variable parameter values that happen to have a custom metadata property named Uppercase set on them in their bind variable definition. You can use the view object editor to inspect the bind variable named TheName on both the DeptView and EmpView view objects to see that they both have this Uppercase custom metadata property set. Both of these view object specify CustomViewObjectImpl as their base class in inherit this new, generic functionality that is metadata-driven. To experiment with the example, run the application module and enter a department name is lower/mixed case like "research". Then click on the ":id" icon of the detail Employees view instance and try filtering the employees to ones whose Ename starts with the letter "s" (entered in lowercase, too).
- 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. The DeptView view object in the example indicates that it should use the MyViewRowImpl class as its view row implementation class. The Dept entity object supplies default values for its Loc and Dname attributes, and the DeptView view object specifies a further view-object-attribute-level default value for the Loc attribute as well. You can use the ADF Business Components tester to try creating a new row to observe the behavior.
- The test() method in the TestModule in this example illustrates the important point discussed in section 27.1.3 Understanding View Link Accessors Versus Data Model View Link Instances of the ADF Developer's Guide for Forms/4GL Developers. It highlights how the view link accessor rowset is based on a distinct, system-created view object instance as compared with the developer-created view linked detail view object instance in the data model, despite the fact that they are both instance based on the same base view object definition EmpView . The code shows adding an additional runtime WHERE clause filter to the view link accessor rowset by accessing its view object instance, and then performs a similar task on the data model detail view object instance to show they are indepdent. Run the TestClient.java class to see the results of the test() method in action.
- 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.
- 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.
- 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
- The Example.jspx page in this workspace illustrates a tree based on the Departments view object instance. The DeptView view object definition on which this view instance is based, is viewlinked to the EmpView view object with a view link accessor named EmployeesInDepartment . The tree binding in the page definition is configured with two rules in order to show the Dname attribute for the DeptView rows, to "drill down" into the EmpView details for each DeptView row using the EmployeesInDepartment view link accessor attribute, and to display the Ename attribute for each EmpView in the tree. The tree control has an id of myTree so that the panelGroup component surrounding the employee detail information can have its partialTriggers property set to that id. This way, any user interaction with the tree control will repaint the panelGroup and everything inside it. Since we want to be able to conditionally toggle the rendered property of the panelBox on and off, combined with the fact that you cannot trigger a partial page refresh event for a UI component that is not rendered, we need to introduce this wrapping panelGroup component to be a stable UI component in the page on which to configure the partial page updating. The nodeStamp facet of the tree component includes an switcher component to conditionally render the tree nodes based on the current level of the tree. The current level of the tree is determined by referencing the expression node.hierType.viewDefName which allows us to access the fully-qualified view definition name of the hierarchy type (representing the tree binding rule) of the current node. This will return a string of " test.model.DeptView " for the nodes in the tree coming from the DeptView view object, and a string of " test.model.EmpView " for the nodes coming from the EmpView view object. In order to avoid using these "raw" view definition names as the switcher component's facet names, we introduce a treeLevel map in the Example backing bean to map the view definition name to a logical facet name. The entries in this map <("" test.model.DeptView ", " DeptNode "), (" test.model.EmpView ", " EmpNode ")>are configured declaratively in the faces-config.xml file using the JSF managed bean facility. The facetName property of the switcher is set to the EL expression " # " which resolves to the logical facet name corresponding to the view definition name of the current node in the tree, via this map. In other words, DeptView nodes render using the contents of the DeptNode switcher facet as a outputText, while EmpView nodes render using the contents of the EmpNode facet as a commandLink. The command link is configured to have its action listener invoke the declarative action binding setCurrentRowInEmployeesIteratorWithKey which is the name of the action binding in the page definition that uses the built-in setCurrentRowWithKey operation against the EmployeesIterator iterator binding. This action binding is configured to pass the value of the EL expression " # " as the one parameter this built-in operation requires. It is the stringified row key of the current node in the tree that the user has clicked on. In the Example backing bean, the onTreeNodeDisclosed method is configured as the tree's disclosureListener. It has a bit of code to set the set of expanded tree nodes to be only the currently selected node, as well as a line of code that hides the employee information panel box by setting its rendered property to false. The onClickEmployeeCommandLink is configured as the action of the commandLink in the tree and it includes one line of code that shows the employee info panel box. This panelbox includes a panelForm that shows the employee detail information and allows the user to edit the salary. In order to avoid the tree interaction from posting data, it has its immediate property set to true. This way, any user change to the form is saved only if the user explicitly clicks on the (Save) button. Last, but not least, the commandLink includes a nested resetActionListener component to ensure that the editable UI components on the page "pull" or "reset" their bound values after the partial page request caused by clicking on the tree. This ensures that the Sal field on the employee detail panel is always correctly showing the value of the current employees salary. [NOTE: An 11g version of this example that has been migrated to use the Apache Trinidad components is available here.]
- 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.
- 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 the Main.jspx page to try the demo. The example-dept-region bounded task flow includes a button on its ExampleDept.jsff page that navigates to a task flow call activity in the taskflow to perform the work done by the isolated "subroutine" call. The perform-isolated-work includes a method call activity that invokes the performAppModuleLevelWork() client interface method in the AppModule application module. This method accepts an integer representing the department number to modify, and a String representing the value that department's Loc attribute should be updated to, then it commits the changes. The taskflow accepts parameters which it passes into this method call. The af:commandButton includes two nested af:setPropertyListener components to assign values to the requestScope.deptno and requestScope.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's Deptno value, and to pass the literal value ' Q ' as the value to assign to the Loc 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 its LOC column value (in a separate transaction. The checkbox in the page controls whether or not the Router activity will declaratively refresh the DeptView1Iterator 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 the LOC value updated in the separate transaction to be reflected in the web page. The custom PagePhaseListener CalledTaskflowErrorReporterPagePhaseListener , which is configured in the adf-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 contains a DeptView view object having the where clause **dname like upper('%'||:0||'%')** , that is a "zeroth" bind variable using the Oracle-style positional bind variable notation. The Panel1.java class was created by dropping a JScrollPane followed by dropping the DeptView1 view object instance as a Table from the data binding palette onto that JScrollPane. The "Go!" button was dropped from the data control palette as an Execute button to cause the query to execute. The field accepting the parameter is just an unbound JTextField named jTextField1. There is code added in two places in Panel1.java that is highlighted with the string ADDED CODE in the comment preceding it. The first added code short-circuits the initial execute query by setting the underlying view object's maximum fetch size to zero (0) initially, just before the call to refreshControl(). The second added code adds an ActionBindingListener to the action binding named "Execute" that got created when we dropped the "Execute" action from the data control palette. That listener has a couple of lines of code in its beforeActionPerformed() method that sets the maximum fetch size back to unlimited (-1) and sets the where clause parameter value by position.
- 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).
- At the ADF Model data binding layer, there is no distinction between attributes that are transient or persistent. When any attribute's value is changed through an ADFM binding, the ADFM-layer transaction is marked as dirty. This can have the unwanted side-effect of enabling the JClient navigation bar's Commit and Rollback buttons even if the only thing the end-user did was to change the value of a transient field, potentially leading to end-user confusion. This JClient example illustrates a DeptView to which an additional transient Boolean attribute named Selected has been added. The View project in the example illustrates a custom ADF Business Components data control class ( MyCustomADFBCDataControl ) that extends the default ADFBC data control class ( JUApplication ). The custom version overrides the setTransactionModified() method to avoid dirtying the transaction unless the transaction related to the underlying application module is actually dirty. The companion MyCustomDataControlFactoryImpl is required to instantiate the custom data control class, and the DataBindings.cpx file references the fully-qualified class name of the custom data control factory class in the FactoryClass property of the element in the Selected? checkbox toggles the value of the transient flag, as visible by the message that the setSelected() method in the custom view row class prints to the console, but the JClient toolbar does not enable the Commit or Rollback buttons until you actually modify some persistent attributes.
- This example illustrates a TestPage.jspx with a button whose action navigates to an XSQL page TestPage.xsql to format the data in the iterator using XML/XSLT techniques. The TestPage.xsql uses the custom XSQL action class test.view.xsql.ADFViewObject that is identical to the one that appeared in the ADF Toy Store Demo, only refactored to live in a different package. The interesting things to note about getting this example to work are: (1) The web.xml file defines a filter-mapping for the *.xsql URL pattern, (2) the DataBindings.cpx has been modified in the code editor to contain an additional page mapping entry for the /TestPage.xsql path so ADF knows what page definition you want to use for that page, and (3) by insuring that the URL requesting the page contains the "/faces/" prefix in the path, this triggers the handling of the request by the Faces Servlet (and indirectly the ADFPhaseListener that is registered to be used by the Faces infrastructure). This makes sure that the request-scoped bindings attribute is correctly set to reference the current page's runtime binding container.
- This example illustrates a simple browse page and edit/upload page for images stored in an Oracle table column of type ORDImage . Run the CreateTable.sql script in thae Model project to create the IMAGE_TABLE table. See the README.TXT file in the ViewController project for some of the manual steps that were necessary to create the working example since JDeveloper 10.1.3 does not currently offer automatic design-time support for ORDImage attributes, even though the runtime support is there as the example illustrates.
- 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 tag inside the JSF page by wrapping it with an tag. In addition, to allow this non-JSF component to still be updated dynamically (AJAX-style) you further wrap the tag by a panel like panelGroup . The backing bean for the page illustrates how to allow an updateable UIComponent in a table to trigger partial page rendering for other elements in the page by programmatically calling the ADF Faces addPartialTarget API. I initially created the graph tag by creating a regular (i.e. non-JSF) JSPX page, and dropping the EmployeesInDepartment data collection from the Data Control Palette as a Graph, then I copied the graph tag and its corresponding tag namespace to the page I wanted to include it in. Lastly, I then copied the Graph binding into the page definition of the target page, and ensured that its binding id was unique. After renaming the graph binding to be unique, I updated the EL expression in the Graph tag's data attribute to reference the renamed graph binding. Finally, I edited the chart's visual properties by double-clicking on the BIGraphDef1.xml node in the navigator and using the graph definition editor, the Structure Window, and the Property Inspector. Also of interest is that the chart binding is setup to graph a transient entity object attribute called TotalComp which simply is the sum of the Sal and Comp attributes to provide an employees total compensation. Notice that you can edit the Sal or Comm values in the table and the graph dynamically updates. You can also use the navigation list or the (Next) / (Previous) buttons to change the department, and the graph updates to reflect the employees in the current department. The Emp entity in the Model project uses the generic, automatic attribute recalculation logic explained in section 26.8 Implementing Automatic Attribute Recalculation of the ADF Developers Guide for Forms/4GL Developers, and implemented in the SRDemo Sample ADFBC Version.
- 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.
- Page1.jspx in this example illustrates how to bind an af:selectOneChoice dropdown list to a session-scope managed bean property # . 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 the DeptView1Iterator iterator binding and which exposes the attributes we want to use for the label and value in the list of valid choices ( Dname and Deptno , respectively). Nested inside the af:selectOneChoice an af:forEach loops over the List -valued rangeSet property that the table/range binding exposes, and create the select list items based on the data in the rows of the DeptView1Iterator (which is bound to the default rowset of the DeptView1 view object instance in the AppModule application module.
- 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.
- 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.
- 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 the adfc-config.xml file and the method action binding in the page def for view1.jspx references the bean using the InstanceName 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 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.
- 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
- This example illustrates an EmployeesView view object that queries employees from the HR schema. It contains four levels of reference entity usages, showing for the current employee: (1) the name of the Department they work in, (2) the StreetAddress of the Location of that Department , (3) the Country name in which that location resides, and (4) the Region name in which that country resides. Run the DemoModule in the ADF Business Components browser and double-click on the Employees view object instance to see its data. Experiment with changing the DepartmentId foreign key attribute of an existing employee to notice that all four levels of reference information correctly synchronize. You can use the AllDepartments view object instance to remind yourself of what some valid department id numbers are, and you can use the four-level master/detail-coordinated view object instances ( Regions -> Countries -> Locations -> Departments ) to understand better what to expect when changing the DepartmentId . The trick to having this multi-level reference information synchronization work correctly is that at each level the foreign key attribute referencing the next level is included in the view object's attribute list. Notice that the attributes whose names start with "PK" in the view object have a Display control hint set to "Hide", so the ADF Business Components browser hides them.
- This example illustrates a very model-centric approach for managing the rows in an intersection table of a many-to-many relationship using a multi-select table. It is based on the tables in the SRDemo schema USERS , PRODUCTS , EXPERTISE_AREAS . The Staff view object is an entity-based view object based on the User entity object that has a WHERE clause to retrieve only the users having a USER_ROLE is either 'technician' or 'manager' . The ProductExpertiseAreas is an entity-based, expert-mode view object whose SQL statement is crafted to use outer joins to return exactly one row for each available product. The view object has the Product entity object as its primary entity usage, and has ExpertiseArea as a secondary, reference entity usage. It defines a named bind variable Bind_UserId that is consciously named exactly the same as the system bind variable the framework will add for the view link between Staff and ProductExpertiseAreas (based on the UserId ). That view link has a customized view link SQL clause to allow the USER_ID to be NULL so that the detail rowset retains a row for every product, even when the current user does not have expertise for that product currently. Due to the outer join, rows retrieved retrieved in the ProductExpertiseAreas view object will have a non-null ExpertiseArea entity row part when the current user has expertise area in that product. Conversely, if the current user does not have expertise in a given product, the ExpertiseArea entity row part will be a blank entity row. To simplify the client, we introduce a transient Boolean -valued attribute on the ProductExpertiseAreas view object named HasExpertise . We override the getHasExpertise() and setHasExpertise() methods in the view row class to handle retrieving and setting this transient attribute. The setter method handles either creating a new ExpertiseArea instance corresponding to the current userId and prodId combination, or removing an existing entity row, depending on whether HasExpertise is being toggled on or off. Implementing a model-centric solution gives three interesting benefits: (1) You can test and debug the complete functionality just using the ADF Busines Components Tester, (2) UI can just bind a checkbox to the Boolean HasExpertise property, and the functionality works the same in JSF, JSP, or Swing. The ViewController project contains a simple JSF page that displays a table containing a selectBooleanCheckbox bound directly to the HasExpertise attribute. In other words, it is not using a special tableSelectMany component in its selection facet. The checkbox is just a part of the "data" in each row. Note: This example uses the SRDEMO schema from the SRDemo sample application.
- This example illustates three bounded task flows that use different declarative transaction options. The manage-employees task flow has its transaction property set to new-transction to indicate that it should only be used as a top-level task when no other current transaction is in effect. The modify-employee task flow has its transaction property set to requires-existing-transaction to indicate that it only makes sense to be called as part of an existing transaction (but cannot be called on its own), since it requires parameters to work correctly. The create-department task flow has its transaction property set to requires-transaction which allows it to be used either as a top-level transactional flow, or else as a part of another task flow with a transaction already in effect. To run the example, run the ViewController project. The home page has links that start either the create-department task flow, or the manage-employees task flow. As part of the task of managing employees, creating or editing an employee calls the modify-employee task flow. While modifying an employee, if you need to create a new department, the create-department task flow is called. The 'Cancel' return actions of the modify-employee and create-department are configured to have the restore-save-point property set to true so that, if they are not the task flow that is controlling the transaction, then they will use savepoints to allow canceling any pending work performed in that flow without rolling back the entire transaction. Experiment with performing some changes and doing different combinations of (OK) and (Cancel) buttons to see the effect of the nested transaction support. Before deciding to save or cancel all changes you have made to employees, you can see the modified rows' data in italics in the table, with the modified attributes in bold/italic. This display is facilitated by the use of custom row-specific attribute hints named rowState and valueChanged that are enabled due to the use of the CustomViewRowImpl framework extension class in the FrameworkExtensions project. The CustomViewObject in that project works around a couple of issues in the 11.1.1 release related to the quick query component (forcing the view criteria item operator to be "Starts With" instead of "Like", and working around bug# 7660871 which causes the quick query criteria to not be applied correctly in some situations). The CustomEntityImpl in the project implements a generic solution for declarative control over the posting order of associated (but not composed) entities by allowing an entity to specify a custom PostAfterAccessors property whose value is a comma-separated list of association accessors which should be checked for a new referenced row that should be posted before the current entity. The Emp entity in the example is configured with that property in order to cause a new, referenced Dept entity instance to post first.
- 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.
- 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 the EmployeeId , LastName , and FirstName of the employee, so only those three columns are selected from the database. In the details page, all EmployeesView columns are bound to UI components (and reflected in page definition attribute bindings) exceptfor the ManagerId and CommissionPct fields, so the SELECT list reflects this extended set of fields. The EmployeesView view object is marked to have SQLMode = "Declarative" so that ADFBC can calculate its runtime SELECT list based on the attributes bound in the current page definition. All of the EmployeesView attributes except for the primary key EmployeeId are marked with IsSelected='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 the SELECT 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 # . This SummaryEmployeeId 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 the employee-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 the Home.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 the SummaryEmployeesView 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 the DetailEmployeesView view object instance, we have set the Refresh property of the DetailEmployeesViewIterator iterator binding in the view2 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). The TracingViewObjectImpl class logs the queries being executed to more easily see the declarative-mode SQL SELECT list pruning optimization at work.
- 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 objects OnlyAddNewRowIfValidViewObjectImpl . The entity framework extension class overrides the validateEntity() 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 named onlyAddNewRowIfValid and the overridden rowQualifies() method ensures that a new row does not qualify for inclusion in the view object's rowsets unless it is valid. The AppModuleImpl class overrides the prepareSession() method to set the property on the DeptView1 view object instance. To run the demo, run the view1.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 a Dname value of upper-case X and a Loc value of upper-case Y . Notice that until the row validates, it's not added into the table.
- 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 # 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 # 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.
- This example illustrates one possible idea for a generic technique to automatically disable master/detail coordination for detail view objects that are not displayed on the current JSF page. It might be relevant to consider when you have a "deep" or "wide" hierarchy of master/detail view objects in your application module data model, where the end-user will be navigating/changing master rows often, triggering automatic master/detail coordination based on the view link instances in your data model. By design, the business service layer has no knowledge of what a "page" is or what view objects in the data model are used by a given "page". By extending the framework's business layer and controller layer, you can supply information about the view objects in use in the current page's binding container to the business service to enable it to leverage this additional information to avoid eagerly querying detail data that is not visible on the current page. The framework extension class CustomApplicationModuleImpl contains a method enableDetailsForViewInstances() that accepts an array of view instance names representing the views displayed on the current page. It proceeds to explore the view link instances in the data model related to the supplied view object names, and enable/disable master/detail coordination as appropriate so that only the view objects in the supplied list are queried. The ExampleModule application module extends this base class, and exposes the method on its client interface. In the ViewController project, the CustomJSFPageLifecycle class overrides the prepareModel() method to augment this phase of page processing to add a call to the abovementioned enableDetailsForViewInstances() method, passing in a list of view instances corresponding to the iterator bindings in the current page's binding container. Another framework extension class CustomViewObjectImpl overrides the executeQueryForCollection() method to short-circuit any attempt to query a detail view object when the framework-supplied named bind variable connecting it to the current master row has a null value. It accomplishes this by temporarily setting the maxFetchSize for the view object to zero, calling the super, then restoring the original maxFetchSize value. The view controller project is instrumented with a customized DCJboDataControl in order to add educational log output at the beginning and ending of each request, and the CustomViewObjectImpl class overrides the bindParametersForCollection method to log the execution of each query sent to the database. These two elements make it easier to observe which view object queries are getting executed on each request for educational purposes. The data model includes a main "CurrentEmployee" view over the EMP table, with a number of first-level, and one 2nd-level detail queries. The data in these detail queries is just dummy detail data queried again from cartesion products over the same EMP table to simulate various kinds of detail data. There are four JSF pages in demo: Home.jspx , Drill.jspx , AnotherPage.jspx , and ThirdPage.jspx . Each shows some subset of the overall data model. Again for educational purposes, you can experiment with enabling or disabling the generic optmizations using the value of the AM configuration parameter named enable.optimizations . The ExampleModule comes with two different configurations, one that has this parameter enabled, and the other where its disabled. By selecting the DataBindings.cpx file in the ViewController project, and selecting the ExampleModuleDataControl node under the dataControlUsages section in the Structure Window, you can use the Property Inspector to set the Configuration property to toggle between using the ExampleModuleLocal configuration where the optimizations are disabled and the ExampleModuleLocalOptimizationsEnabled configuration where the optimizations are enabled. The example is configured by default to use the configuration that has the 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. The ThirdPage also illustrates two techniques for forcing data in view objects to be requeried to have the user eagerly see the very latest data. The technique illustrated for EmpDetails5 involves setting the CacheResults property to false on its iterator binding. This causes the framework to perform a clearCache on the view object at the end of the request. Requerying the EmpDetails6 iterator is done using an invokeAction in the page definition, bound to an ExecuteQuery action binding. This invokeAction has a RefreshCondition set to conditionally perform the data-refreshing query when the page is rendered, but not during post-back. In both cases you can observe when the data is refreshed by looking at the value of the CurrentTime column in the tables. In your testing, make sure to visit all of the pages (even several times) and perform various levels of change master/detail current rows to get the full effect of the difference between the optimized and unoptimized cases.
- This example contains a TestPage.jspx and TestPageTwo.jspx. The first one illustrates using a combination of an invokeAction executable in the page definition, bound to an ExecuteWithParams built-in action, to declaratively pass the value of the URL parameter named dname to the named bind variable on the DeptViewWithBindVariable . The second page illustrates an alternative technique that may be applicable if the where clause that needs to be added is too complex or too dynamic to create at design time. It uses a combination of an invokeAction executeable in the page definition, bound to a method action, to conditionally invokes either the clearFilterOnDeptView() or the filterDeptViewByDname() on the application module's custom interface. Try tacking on an additional dname URL parameter to either of the pages like ?dname=acc or dname=s to see the effect of the filter. Intererstingly, the pages use the ADF Faces af:switcher component to conditionally present the results in a table or in a form depending on how many results are identified by the query.
- This example illustrates how to validate and render conditionally-required attributes. After running the included CreateTables.sql script to create the OPTIONAL_REQUIRED_TEST table, run the TestPage.jspx to see that when a row has its RowType attribute set to the value A then the ValueA inputText component renders, while if its RowType attribute is instead set to the value B then the ValueB inputText field renders. These fields set the showRequired property to true to show the required field indicator to the end-user even though the underlying ValueA and ValueB attribute are not marked as mandatory. The conditional mandatory validation is performed in the TestEntity entity object using entity-level method validators. The radio group UI component is marked to have its autoSubmit property true, and the ValueChangeListener method in the backing bean for the page sets a request-scope attribute as a flag to indicate that the row type is changing. This flag is then referenced by the ConditionalValidationPageController - identical in function to the one you might have seen in Example# 62 "Cascading Lists in JSF" - which is configured to be used by the TestPage by setting the ControllerClass property of its page definition. This customized page controller avoids validating the row if it detects that the row type is changing. The conditional rendering of the ValueA or ValueB inputText components is handled declaratively using an appropriate EL expression for the component's rendered property. When the autoSubmit radio group (with component id "RowTypeRadio") causes its partial-page request, the panelForm component in which the ValueA and ValueB inputText's reside is declaratively "repainted" by having its partialTriggers attribute set to that "RowTypeRadio" id value. By performing the partial-page triggering on the enclosing panelForm component, you avoid the gotchas related to having PPR events delivered to currently-unrendered components.
- 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.
- Demonstrates the different levels of polymorphic query support that we have in ADF Business Components. The TestClient example uses an instance of a "People" VO but illustrates that the client can cast "MenRow" rows to the MenRow interface supporting a getManAttr() , and "WomenRow" rows can be cast to a WomenRow interface to access a getWomanAttr() method that is specific to women. ADF Business Components supports two distinct kinds of polymorphism: ViewRow polymorphism (which you setup at the application module level) and EntityObject polymorphism (which you setup on an individual VO). This example shows both kinds of polymorphism at work, but they can be used independently.
- 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.
- 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 an invokeAction combined with an Execute operation binding (and appropriate settings for the Refresh and RefreshCondition properties of the invokeAction ) to conditionally refresh a view object's query results based on the presence of a request-scope flag attribute. You can read more about these settings in section 10.5.5 How to Use Refresh Correctly for InvokeAction and Iterator Bindings. The AnotherPage.jspx , to which you can navigate from Departments.jspx , contains two af:commandLink components that navigate back to the Departments.jspx page. One of those links uses a nested, af:setActionListener component to declaratively set the value of the request-scope attribute named refreshFlag to the value true . The presence of this flag attribute causes the invokeAction mentioned above to force a requery of the rows. The DeptView view object is instrumented to print a diagnostic message to let you see when its base query and its estimated row count query get executed. The range size of the iterator binding used on this page is set to 2 to you can see the table paging behavior even with only 4 rows of DEPT table data. When you use an af:table and have a range size of N set on your iterator binding to show only N rows per page, then the estimated row count query will be used since the table component needs that count to build its paging control. The DepartmentsProgrammatic.jspx page is nearly identical to the Departments.jspx page, except that it illustrates how to accomplish the conditional requery of the view object from code using the basic technique described in section 10.5.4.3 Using Custom ADF Page Lifecycle to Invoke an onPageLoad Backing Bean Method section of the ADF Developer's Guide for Forms/4GL Developers. It also uses a range size of 2. The DepartmentsAlwaysRequestOnPageEntry.jspx page illustrates how to create a page the refreshes its data each time you navigate to it from another page (but not when you post-back to it from the same page). And finally, the DepartmentsTimedAutoRefresh.jspx page illustrates how to use the combination of an af:poll component and an Execute action binding to refresh the page without user intervention every 5000 milliseconds (i.e. 5 seconds). Notice that the af:poll component has an id attribute set to the value " timer " and that an af:outputText on the page as well as the af:table UI components list this " timer " id in their partialTriggers property so that they will be partial-page refreshed to "repaint" any updated results. The af:outputText just shows the current date/time to make it easier to see when the timer is firing. In constrast to the other three pages, this page has no explicit (Refresh) button, so to create the Execute action binding in the page definition I selected the Go to Page Definition choice in right mouse context menu of the JSPX page visual editor window and then used the Structure Window view of the page definition for that page to select the bindings heading and Insert Inside bindings ->action> right-mouse menu choice to create an action binding for the DepartmentsIterator using the built-in operation named Execute .
- Programmatically Scrolling the JSF Table's Current Page of Rows [10.1.3.1, HR schema]
- The ProgrammaticScroll JSF backing bean in this example illustrates three different approaches to perform programmatic scrolling of the 25 rows in the HR schema's COUNTRIES table. Run the ProgrammaticScroll.jspx page and try using the (<<) and (>>) buttons, optionally changing the scrolling increment value in the text field located between these buttons. You can use the drop-down list to pick among the three different programmatic scrolling approaches.
- 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.
- This example illustrates a simple JSF page with a selectOneChoice and a selectOneRadio , each with its respective value bound to an Integer -valued backing bean property. The switcher controls use the respective property value to toggle the display of an appropriate PanelBox, and the partialTriggers property setup on the containing panelGroup component causes the panel to repaint when the value of the respective selectOneXXX component changes.
- 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).
- 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.
- 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.
- 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.
- When working with the ADF Business Components data control, the view objects and entity objects have event notification in place that the ADF Business Components implementation of the ADF row set iterator responds intelligently to. So, ADF iterators working with ADF Business Components-based back-ends are always up to date with changes made to the collections. If you are working instead with data binding against simple Java classes and do something in your code to update a Collection -valued property, you need to manually trigger the rebuild of the iterator. This sample illustrates the line of code required to do that in the ResultsAction.java custom data action class.
- 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.
- ADF Business Components has a built-in warnings facility that complements the validation and exceptions features. This example illustrates how to configure a custom FacesPageLifecycleClass (described in more details in 10.5.4.1 Globally Customizing the ADF Page Lifecycle of the ADF Developer's Guide for Forms/4GL Developers) which registers itself as the JboExceptionHandler . This allows it to receive the handleWarning() notification when any business components warning is signalled in custom code. As illustrated in the DeptImpl class in the example, you signal a warning by constructing an instance of the JboWarning class and passing it to the addWarning() method of the ApplicationModule . To distinguish between a warning and a purely information message, the example introduces a subclass InformationalMessage that extends JboWarning and the handleWarning() method in the CustomFacesPageLifecycle class reports the warning as a FacesMessage with the appropriate severity. To experiment with the demo, run the TestPage.jspx page and try entering the value " ERROR " for the Dname field. That will cause an attribute-level validation to fail for that attribute. If you instead enter a Dname value of " WARN ", then you'll see a warning reported. And if you simply make a change and save it successfully, you'll see a purely informational message reported.
- 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 the TestPage.jspx . Try submitting the search form without entering any of the selective-required criteria items ( Ename and Job 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 like sm (to find employee SMITH ) and click (Search), you'll get a different error telling you to please enter at least three characters.
- The TestPage.jspx page in this example contains an ADF Form dropped from the data control palette based on the Employees view object. It consciously chooses to avoid performing client-side required-field validation by notsetting the required property of the inputText controls (which defaults to false ). Instead, it sets the showRequired property of the components to the same EL expression that would normally be used by the client-side required property. This has the effect that required fields are rendered with the visual required indicator, but the mandatory field validation is performed by the ADF BC layer instead of on the client. The ViewController project includes a custom ADF Phase Listener, a custom Faces Page Lifecycle class, and a custom ADF Error Handler class just like the SRDemo sample application (explained in section 20.8.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 the getComponentClientId method on the FacesCtrlAttrsBinding object to retrieve the Faces component client id in order to construct a FacesMessage that is specifically related to a given UI component, (2) the use of the ADF Faces LabeledFacesMessage class to create a FacesMessage that remembers the label of the component to which it's associated, and (3) the special-case handling of AttrSetValException errors for mandatory fields in order to display a custom string from the CustomMessageBundle using the end-user-friendly UI label string of the attribute name that is required. In addition, since we've disabled the use of client-side mandatory field enforcement, combined with the fact that the ADF model layer does not by default validate the binding container if the end-user has not entered any values into any of the fields, we've overridden the validateModelUpdates() method in the CustomFacesPageLifecycle class in order to call a helper method forceValidationOfNewRowWithAllNullMandatoryAttributes() which does what it's name suggests. This ensures that if the user creates a new row and immediately clicks (Save) without entering any values for any fields, they see the expected errors about any mandatory fields. In addition, by running the TestHomePage.jspx you can running two different standalone create forms by clicking on an appropriate command button. The CreateNewEmployeePage.jspx page is a more traditional, declarative create form based directly on a view object as described in section 13.6 Creating an Input Form of the Dev Guide. The CreateNewEmployeePageUsingAMMethodViaEntity.jspx page shows an alternative approach that requires coding an application module custom method, exposed on its client interface, dropped onto the page as an ADF Parameter Form. Note that using the method-based approach, the method parameters are named the same as the underlying entity object attributes so that the created page definition variables and bindings have names that match the entity object attributes. Also note that the application module method uses an entity-based view object to create the new employee rather than directly creating the entity object so that the automatic bundled-exception handling is preserved. Try setting the "Ename" to the value XXXXX in order to observe what happens when an attribute-level validation rule fails. Finally, also note that the UI Hints for the parameter form page definition variables are defined in a message bundle specific to the page definition. With the view object based approach, those are automatically inherited from the underlying entity object. The example also illustrates the use of selectOneChoice "dropdown list" controls for mandatory fields. Their corresponding list binding is configured to allow a null value to correctly handle the fact that in a newly-created row the value of that attribute will be null if your entity object does not provide an alternative default value. The example contains workaround code in the form of the viewcontroller.util.ListBindingHelper to workaround bug# 5930745 where an additional blank entry can inadvertently be added to the list when the list binding related to a selectOneChoice control has a validation exception due to its being mandatory. Finally, the backing beans for the CreateNewEmployeePage and the CreateNewEmployeePageUsingAMMethodViaEntity pages were created in order to workaround bug# 5930784 where ADF/JSF incorrectly performs page navigation even when exceptions have been registered on the current page. By double-clicking on the declaratively-bound button and allowing JDeveloper to generate the ADF binding code in the backing bean, this reliably avoids page navigation when the action binding has caused exceptions to be raised. If you notice that sometimes the attribute-level exceptions are reported with errors that appear next to the fields and other times with errors reported only at the top, this is related to bugs# 5918276 and 5929646 where the getComponentClientId() function of the FacesCtrlAttrsBinding returns null if the binding has not previously "seen" a non-null value during the session as well as the fact that the FacesCtrlListBinding does not support a getComponentClientId() method. It is the ability to retrieve the client id of the component related to a binding that allows this example's custom error reporting to construct an ADF Faces Message that will be rendered next to the component to which it relates. You can run the demo with your browser set to prefer "Italian [it]" to see the page translated in Italian.
- This example illustrates the correct way to operate on the possibly multiple view link accessor rowsets of a tree binding. A very common mistake developers make is that they write application module custom methods that operate on a view object instance in the datamodel, only to be surprised when the changes they've made are not reflected in the tree on the page. Their approach fails because the ADFM tree binding uses view link accessor rowsets rather than data model view link instances to work with detail rows. To understand the difference, read section 35.1.3 Understanding View Link Accessors Versus Data Model View Link Instances in the 11g Dev Guide. To make this point extremely clear, the example's AppModule contains only a single view instance in the data model called Departments . The data model does not contain any view link instance or any "Employees" view instance. While those are useful for some master/detail UI scenarios, they are not needed/used-by a tree binding. Instead, the tree binding materializes the employee rows in each department by directly interacting with each DeptView row's view link accessor attribute, producing separate EmpView row sets for each of the distinct department rows that the user expands to see the details for. The example depends on a slightly modified version of the usual EMP and DEPT tables called DEPT_RANK and EMP_WITH_RANK . The latter table contains one additional column named EMP_RANK which is used to order the employees in a given department. You should run the included CreateTables.sql script in your SCOTT account before trying the demo. A few interesting points that the demo shows off is the use of the generic TableSupportBean which exposes some useful properties to the EL expression language like selectedNodeRowIterator and selectedNodeRowKey . The method action bindings in the page definition for the TreePage.jspx page reference these properties in order to declaratively pass the correct RowIterator and the key of the selected row in the table to the application module custom methods which resequence the selected employee's rank either up or down. Also note that in the Tuning section of the General panel for the DeptView view object, the Retain View Link Accessor Rowset checkbox is checked on. This setting is required for the tree binding to correctly reflect programmatic manipulations in the pending transaction made by developer-written code in the AM.
- 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 named dcParam and rsiParam (where 'rsi' is short for RowSetIterator). The example includes four other ADF Swing panels that then reuse the EmployeePanel , each passing in appropriate values for the dcParam and rsiParam parameters. To drop an instance of a reusable ADF Swing panel, simply select the Component Palette page named ADF Swing Regions and you'll see that the EmployeePanel automatically appears there as a reusable component. When you drag/drop the EmployeePanel onto a panel where you want to use it, JDeveloper pops up a dialog asking you to fill in EL expressions to give appropriate values for the panel's dcParam and rsiParam parameters. In this way, you can reuse the same panel with different view objects. You'll see a special "page" binding appear in the Executablessection of the including panel's page definition, along with metadata capturing the EL expressions you've entered. The example features a Panel1 panel that reuses EmployeePanel to display the results of the data collection named EmpView1 in TestModule1DataControl . A Panel2 panel reuses the EmployeePanel panel bound to the data collection named AllEmployees in the TestModule2DataControl , based on a different application module. The Panel3 panel illustrates that you can reuse the EmployeePanel for a data collection that is a view-linked detail view object instance, in particular the EmployeesInDepartment data collection in the TestModule2DataControl . And finally, the Panel4 panel shows that you can reuse the EmployeesPanel bound to a view object that's completely different than the original one that was designed to create it, provided that it has the expected attribute names with the expected data types. In this case, it is bound to the data collection named EmployeesReadOnly in the TestModule2DataControl , an instance of the non-entity-based (and hence read-only) view object of the same name.
- Router Data Action
- Shows a generic, and simple, customization of the basic ADF DataForwardAction to automatically use the String -based result of a declaratively-invoked business service method as the name of the Struts forward to use for "next page" navigation.
- This example illustrates how to use a custom page controller class to override the handleError() method to conditionally handle the JBO-35007 exception ('Row currency has changed since the user interface was rendered.') in a way that might be more useful to the end-user. This error can arise if the user accidentally gets the current row in and editor form out of sync with the current row in its underlying iterator. One classic way this can occur is if the user is running Internet Explorer and presses the [Ctrl]-[N] key to "fork" a new window with the current edit form (typically in an innocent attempt to view/edit two different rows side by side using two separate browser windows. Another way this error can occur is through use of the browser back button. To observe the custom behavior, try running the listEmployee.jspx page using Internet Explorer. Select an employee in the table and click the (Edit) button. When the edit form appears, press [Ctrl]-[N] to open a new browser window with the same form. Then, in that new window, press (Back to List), select a different employee row and click (Edit) again. At this point, return to the original window and click the (Submit) button on the edit form. Since this form is editing a row that is no longer the current row in the underlying iterator, a JBO-35007 error will be signalled, however the ControllerClass property of the editEmployeePageDef XML file is configured declaratively to use the custom page controller RedirectJBO35007ExceptionToAnotherPagePageController (in the bug.controller package) to handle the JBO-35007 and redirect to a problem.jspx page that tells the user something about what just happened, and gives them a way to get back to the list page. If you edit the value of the ControllerClass property of the editEmployeePageDef to be instead the name of the SetRequestScopeAttributeFlagForJBO35007PageController class instead, then when you repeat the above scenario to cause the JBO-35007 error to occur you'll see that instead the page becomes disabled and only allows the user to return to the list page.
- It's common to want a JSF page with a summary table that allows the user to select a current row and a detail area showing more information about the currently selected row. If you have enabled the autoSubmit property of the af:tableSelectOne component your af:table 's selection facet, then it can be a little puzzling why the other information on the page does not update when you change the current row. This example illustrates how to declaratively configure your af:table and an af:panelForm that displays additional information about the selected row in the table. The secret lies in configuring the partialTriggers property of the component that you want to be updated when the table selection changes. In the example, you see that I'd assigned an id of myTable to the af:table component, and on the af:panelForm component I've listed myTable as one of the component id's that should trigger a partial-page request "repaint" (of the af:panelForm ). To allow you to experiment with toggling the autoSubmit property of the tableSelectOne on or off at runtime, I've configured a simple SessionSettings session-scoped managed bean that has a single property named useAutoSubmit . By setting the value property of the af:selectBooleanCheckbox at the top of the page to the EL expression # 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 # for the value of the af:tableSelectOne component's autoSubmit property, we allow the changing value of the managed bean property to influence the runtime behvaior of the table selection to be auto-submitting or not. Finally, since a change in state of the checkbox needs to cause the table to repaint, I have assigned an id value of tableAutoSubmitControl to the checkbox, and listed that tableAutoSubmitControl component id in the partialTriggers property of the af:table . At runtime, you'll see that if auto-submit it off, then the current row changes when you click on the (testCurrentRow) button. If auto-submit is on, then the current row changes as soon as you click into the radio group button on the new current row. In both cases, the panelForm to the right is updated to reflect the values of the new current row. The (testCurrentRow) button is a bound declaratively to the testCurrentRow() method on the application module's client interface. It was created by dropping that method from the Data Control Palette onto the page. When you click on the button, you can see that the getDeptView1().getCurrentRow() method call inside that method already "sees" the new current row (and prints out its Deptno value to the console).
- 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 using the af:iterator's status variable's index value as the key into this map. The SelectBooleanRadioHelper class encapsulates a Map 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 and currentSelectedValue2 as temporary storage for the chosen attribute value from the selected row. The corresponding attribute bindings currentSelectedValue1Binding and currentSelectedValue2Binding 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.
- Simple AJAX-Style Partial Page Rendering (PPR) Example with AutoSubmit SelectOneChoice Control [10.1.3.2] 14-JUL-07
- This examples contains a single JSF page with an EmpView editing form. The EmpView view object includes the Emp entity object as its primary entity usage, as well as the Dept entity object as a secondary, reference entity usage, in order to display the related Loc value for the department to which the current employee is assigned. The Deptno is bound to a af:selectOneChoice component whose autoSubmit property has been set to true . This causes a PPR postback whenever the end-user changes the value of the list. The Loc field is displayed as a read-only af:inputText , and has its partialTriggers property set to the value of the id of the af:selectOneChoice component (" DeptnoPoplist ") that should trigger the partial page re-paint of the that Loc``af:inputText component. When you run the page notice that if you navigate between rows in the EmpView the PPR counter at the top of the page increments to illustrate that the entire JSF page is being re-rendered. In contrast, if you just change the value of the autoSubmit-enabled Deptno poplist, then the value of the corresponding Loc field repaints on the page, but the PPR counter at the top stays the same (since only the bit of the page that needed to be repainted was redrawn). Notice that other than the PPRDemo managed bean that facilities showing a counter on the page to better visualize when PPR is occurring and not, the example requires no Java code to implement.
- 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.
- 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. The TestTaskFlow.jspx page has two buttons that are configured to invoke the bounded task flow named show-employees-for-dept , passing in the value of the department number whose employees should be visualized. The task flow defines a parameter named p_deptno whose value is stored into the pageFlowScope attribute named p_deptno using the EL expression # . The ExecuteWithParams operation for the EmployeesByDepartment view object instance (of type EmpView ) was dropped onto a method call activity that has been set as the task flow's default activity. The EmployeesByDepartment view object instance has been configured in the application module data model panel to declaratively apply the view criteria named ByDepartment , so when you drop the ExecuteWithParams operation for this view object instance, the list of appropriate bind variables appears in the dialog. The varDeptno bind variable's EL expression is configured on the ExecuteWithParams binding in the page definition to the expression # 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 the EmployeesByDepartmentIterator iterator binding's Refresh property is configured to the value never 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 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.
- 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 # 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 # expression for each column showing attribute XXXX as the value of the "rendered" property.
- 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 the DEPT_WITH_OBJ_VERSION table. This is the standard DEPT table to which has been added a single, additional NUMBER column named OBJECT_VERSION . The ObjectVersion attribute in the Dept 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. The view1.jspx page uses the tr:inputHidden component to include the ObjectVersion 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 the ObjectVersion attribute value of the row being edited. Since these values differ, the RowInconsistentException 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 the CreateTables.sql script to create the DEPT_WITH_OBJ_VERSION table. Then run the view1.jspx page. Once the page appears in your default browser, copy the URL http://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 of Dname and click (Commit). Now the second browser is looking at a "stale" value for the Dname . In this second browser, update the value of Loc and click (Commit). The user gets the expected error "Another user has changed the row with primary key oracle.jbo.Key[10]". The AppModule 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 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 and 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 illustrates a simple JSF application that allows you to list, edit, add, and remove contacts. The MyServiceBean in the Model project is the stateless EJB 3.0 Session Bean that acts as the business service. To keep the example simple, the session bean works with an in-memory set of Contact POJOs (Plain Old Java Objects). The Session Bean's service methods each prints a diagnostic message to the console so you can better understand and appreciate when the ADF Model layer is working with the cached results of the finder methods as well as when it invokes business service facade methods to add, edit, and remove a Contact. The example is designed so that when the name of a Contact is changed, the Contact 's updated property is updated inside the business service to reflect the update time. When a new contact is added, edited, or deleted, the application causes the executeQuery() method on the method iterator to be executed to rebuild the RowSet of data being managed by the RowSetIterator of the iterator binding. When an iterator is refreshed during the ADF page lifecycle it gets a chance to decide whether its data needs to be recalculated by asking the business service, or whether it can use its cached data. For a method iterator, this decision is based on checking whether the associated method action has stored the result of its execution yet for a given set of its parameter values. If either its result has not yet been calculated, or if any of its parameter values has changed, then the method iterator is implicitly requeried. When a method iterator is requeried, it invokes its related method action binding and caches the result (unless the CacheResults property is explicitly set to false , which is not the case in this example!) and then rebuilds the RowSet of Row objects that wrap the actual data beans - Contact beans in this example. These Row objects adapt all bean data to have the same generic API and delegate to the wrapped "dataProvider" bean in each row to get/set the attribute values. It illustrates both programmatic and declarative techniques for accomplishing this: the former by invoking the executeQuery() in backing bean code, while the latter using a combination of an Execute action binding related to the method iterator and an invokeAction executable whose Refresh and RefreshCondition properties have been set to control the ADF lifecycle phase during which the Execute action should fire as well as a boolean EL expression to qualify under what conditions it should fire. You can read more about these settings in section 10.5.5 How to Use Refresh Correctly for InvokeAction and Iterator Bindings. It's important to note that since the findContactsByName(String) method takes a parameter, we take maximum benefit of the ADF Model layer's results caching when we insure that the EL expression used to pass the method action parameter continues to evaluate to the same value used when the data was originally retrieved. In this example, the value of the nameSearch that the end-user might apply to filter the results is kept in the session-scoped UserInfo managed bean so it can be referenced by the method action on both the ListPage.jspx and the EditPage.jspx pages. If you are not careful to insure this, then having the parameter values be different on different pages, given the conditions described above for the implicit execution of the method iterator, will cause potentially unwanted re-execution of the business service methods. The FwkExtensions project in the example includes generic helper objects and framework extension classes to customize the error handling very similar to those described in the ADF Developer's Guides. The FindOrMergePage.jspx illustrates an example of performing data binding to a method result that returns a single Contact bean instead of a collection of beans (List), using the helper method executeQueryForMethodIterator to re-execute the method iterator's query (since JDeveloper design time prevents the creation of a declarative Execute binding against such a method iterator at the moment). If you enter an email address on this page, it will find an existing contact by email if it exists and update its name if you supply a non-null value for the name parameter. If you enter an email that does not exist, it will add it to the list. This page also shows off some programmatic techniques for conditionally clearing the page definition variables used by the ADF parameter form dropped onto the page. Since the FindOrMergePage can make updates as well as add new rows, the af:commandLink on the page sets the requestScope flag to signal to the ListPage to refresh its data on navigating there.
- 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.
- This example includes a SocialSecurityNumberFormatter class that extends the default ADF Business Components number formatter class ( DefaultNumberFormatter ). It overrides the parse() and format() methods to implement the parsing and formatting of a United States social security number whose format is 000-00-0000 . The default number formatter does not work with this format mask as is because the JDK DecimalFormat class on which it's based doesn't correctly support that format mask as you might expect. You'll need to run the provided CreateEmpWithSocialSecurityNumber.sql script to create a version of the EMP table with an addition SSN column to store the social security number as a numerical value. The Emp entity object sets the custom property named Ssn_FMT_FORMATTER to the fully-qualified class name of the custom formatter class. This property and its value are stored in the entity object's companion EmpImplMsgBundle.java message bundle class. The CustomDCErrorHandler class in the FwkExtensions project contains logic that sets the attribute information on the DataCreationException that is thrown if that information is not already provided in the exception. This allows the error message to be correctly reported as an exception specific to a given attribute. Run the TestPage.jspx page to try entering valid and invalid social security numbers. Notice that the default component has been commented out for the component for Ssn on the page.
- This example illustrates a technique to override the applySortCriteria() method in a custom ADF BC data control to call setSortBy() on the iterator binding's underlying view object instance instead of the default of calling setOrderByClause() . The effect is that this leverages the view object's built-in support for performing in-memory sorting described in more detail in section 27.5.2 Sorting View Object Rows In Memory in the ADF Developer's Guide for Forms/4GL Developers. The ViewController project contains a custom subclass of the ADF BC data control, a custom subclass of the ADF BC Data Control Factory, and a reference to this factory in the DataBindings.cpx file. The CountryList view object retrieves its data from the companion CountryList.properties file. When you run the CountryList.jspx page, try clicking the table headings to sort ascending or descending by the CountryCode or the Description . While not required for the in-memory sorting example, the workspace also includes a few classes required if you don't want your application module to make any database connection at all. The NoDatabaseConnectionApplicationPoolImpl class that subclasses the default application module pool implementation to return null in a few strategic places to avoid the application module's connection to the database. The custom database transaction factory class NoDatabaseConnectionDatabaseTransactionFactory is configured to be used by setting the TransactionFactory property of the configuration, and it creates an instance of the custom NoDatabaseConnectionDBTransactionImpl2 class which overrides the doRollback() method to do nothing.
- 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.
- This example illustrates some generic framework extension classes in action for programmatic view objects whose data is related master/detail. The generic infrastructure code lives in the StaticDataViewObjectSupport project. All of the view objects in the Model project specify the oracle.adfbc.staticdata.CSVFileViewObjectImpl class as their framework base class to inherit the generic functionality of reading their data from a CSV (comma-separated values) file. The ListOfMapsDataProviderViewObjectImpl framework extension class implements a programmatic view object whose data is populated from a java.util.List of java.util.Map objects. The CSVFileViewObjectImpl extends ListOfMapsDataProviderViewObjectImpl to supply a "data provider" that reads data from CSV files. By convention, it reads data from the *.csv file in the same directory in the classpath as the view object's component definition file. So, for example, the model.States view object reads its data from the model/States.csv file. The compiler options of the project have been modified to add the *.csv extension to the list of files that should be copied to the outpath during compilation time. Four different JSPX pages in the ViewController project allow you to try out master/detail display of the programmatically retrieved data.
- This example illustrates a simple search page over an EmpView view object with three named bind variables EmpName , LowSal , and HighSal . The SearchPage.jspx was created by dropping the "ExecuteWithParams" action as a parameter form. It presents the results on a second ResultsPage.jspx. If the results were on the same page, then the ADF data binding layer would preserve the user's search criteria entry across postbacks to the same page. However, since showing the results causes page navigation, when the user returns to the search page, the search criteria are back to their default values. In this case, the named bind variables define their respective default values to be null, so this means the reset criteria is null when you come back to the page. If you want to have the user's search criteria for the named bind variable stay "sticky" across pages, then you can save it in an attribute in the process scope, and then assign the search field binding to the value of that processScope-saved value just before the page is rendered. The example uses a variation on the OnPageLoadBackingBeanBase class described in Using Custom ADF Page Lifecycle to Invoke an onPageLoad Backing Bean Method section of the ADF Developer's Guide for Forms/4GL Developers. The SearchPage.java backing bean overrides the onPagePreRender() method to set the values of the search field bindings to the value of the saved processScope attributes of the same names. The ControllerClass property of the search page's page definition references the backing bean as its page phase listener using the EL expression # . The setActionListener components on the buttons in the search page declaratively set the values of the processScope variables.
- 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.
- 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.
- 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.
- This example illustrates an approach to count the number of rows changed in the transaction (presumably for notifying the end user). In the example, the total number of changed rows (also broken down by inserts, deletes, and updates) is printed to the console. The implementation involves a customized DBTransactionImpl class which manages the counters in the UserData hashmap in the Session and a custom EntityImpl class (used by the Emp EO in the project) which increments the appropriate insert, update, or delete counter in its afterCommit() method.
- 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.
- 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 a UserInfo bean with a single favoriteColor property. This bean is registered in the adfc-config.xml file as a session-scoped managed bean, and using the JSF managed property feature, the default value of emgreen is injected into the bean at creation time. The Model project contains two view objects that each contain a bind variable named VarFavoriteColor whose default value we'd like to come from the current value of the aforementioned UserInfo managed bean's favoriteColor 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). The ExampleVO2 VO instance in the AM data model is of type ExampleVOUsingADFContextSessionInfoInBindVariable . This view object's VarFavoriteColor bind variable references the groovy expression adf.context.sessionScope.UserInfo.favoriteColor and represents the "simplest thing that works" approach. This takes advantage of the fact that ADFContext object abstracts access to the four interesting scopes that might be relevant during runtime of an ADF application: applicationScope , sessionScope , viewScope , and requestScope . 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. The Test class in the Testing project illustrates making use of the ADFContext.getSessionScope() to setup the session-level information the view object is expecting to find at runtime. The ExampleVO in the AM's data model is of type ExampleVOUsingControllerSuppliedUserDataHashtableInfoInBindVariable . This view object's bind variable of the same name references the groovy expression adf.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 ), the beginRequest method is overridden to invoke a setSessionFavoriteColor() method on the ExampleModule client interface to pass in the value of the UserInfo.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 the passivateState() and activateState() methods. The custom data control is configured by setting the fully-qualified name of the CustomDCJboDataControlFactory class in the ExampleModuleDataControl entry's FactoryClass property in the DataBindings.cpx file (in the dataControlUsages section). On each request, the view/controller layer passes this information into the business layer, and the ExampleVOUsingControllerSuppliedUserDataHashtableInfoInBindVariable view object references its value from the userData map. Notice the setDefaultValuesForSessionLevelFavoriteColor() method in the ExampleModuleImpl class. This is invoked in an overridden prepareSession() 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 the Testing project, the Test 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 a favoriteColor 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 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. The Second.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. The Third.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.
- 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.
- Since declarative PPR based on UI components id's in an editable table does not work in 10.1.3, this example illustrates the small bit of backing bean code (in the onDeptnoDnameOrLocValueChange() method of the Departments backing bean) that is necessary to make the AutoSubmit=true inputText fields in the editable table automatically enable the Commit and Rollback buttons as soon as the first value is changed in the table. The page includes normal declarative PPR (via the partialTriggers attribute) that causes a click on the (Create) button or the (Delete) button to enable the same two buttons. The expression used in the disabled attribute is not the default one dropped by the design time because it wasn't working for me to enable the button when only a delete had been performed. This EL expression referencing the transactionDirty attribute seemed to work more reliably.
- 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.
- Using ADF BC's support for the Oracle Intermedia ORDImage, ORDDoc, ORDAudio, and ORDVideo, you can simplify uploading, downloading, and displaying media and documents. However, since numerous users have asked for it, this example illustrates a simple JSF page with an inputFile component and the backing bean logic to handle inserting the contents of the uploaded file into a BLOB column in the database. Run the CreateTables.sql script to drop and create the simple UPLOADED_FILES table. Then, run the UploadFileToBlob.jspx page. Note that the page uses the af:form container with its usesUpload attribute set to true . Also notice that the inputFile control is bound to the backing bean property named fileInputComponent , allowing the backing bean to reference the UI component programmatically. The valueChangeListener on the inputFile is mapped via EL to the onFileUploaded() method in the backing bean. That method accesses the ExampleModule client interface of the ExampleModule application module, and invokes the saveUploadedFile() method on it. It passes in the file name, and a BlobDomain class representing the contents of the uploaded file. The (Upload File) button's action property is mapped via EL to the onUploadFileButtonClicked() method in the backing bean. This method either displays an error message if the filename to be uploaded is bad, or else causes the "Last File Files Uploaded" iterator to be re-executed to retrieve the latest list of the last file files uploaded (by any user). See Configuring ADF Faces File Uploading Servlet Parameters for information on some settings you might need to configure.
- Uploading Contents of af:inputFile to a CLOB Column [10.1.3.3] 03-OCT-2007
- This sample is a CLOB-based version of example #85. Using ADF BC's support for the Oracle Intermedia ORDImage, ORDDoc, ORDAudio, and ORDVideo, you can simplify uploading, downloading, and displaying media and documents. However, since numerous users have asked for it, this example illustrates a simple JSF page with an inputFile component and the backing bean logic to handle inserting the contents of the uploaded file into a CLOB column in the database. Run the CreateTables.sql script to drop and create the simple UPLOADED_FILES table. Then, run the UploadFileToClob.jspx page. Note that the page uses the af:form container with its usesUpload attribute set to true . Also notice that the inputFile control is bound to the backing bean property named fileInputComponent , allowing the backing bean to reference the UI component programmatically. The valueChangeListener on the inputFile is mapped via EL to the onFileUploaded() method in the backing bean. That method accesses the ExampleModule client interface of the ExampleModule application module, and invokes the saveUploadedFile() method on it. It passes in the file name, and a ClobDomain class representing the contents of the uploaded file. The (Upload File) button's action property is mapped via EL to the onUploadFileButtonClicked() method in the backing bean. This method either displays an error message if the filename to be uploaded is bad, or else causes the "Last File Files Uploaded" iterator to be re-executed to retrieve the latest list of the last file files uploaded (by any user). See Configuring ADF Faces File Uploading Servlet Parameters for information on some settings you might need to configure.
- Upload Text File and Image Example
- Illustrates a simple, no-code-required example of how to support file upload in a JSP page and save both text documents and images into the database. Relies on using the Oracle Intermedia database datatype ORDSYS.ORDDOC and ORDSYS.ORDIMAGE and their corresponding ADF Business Components domains that do the right thing to handle working with them.
- 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 its AutoRefresh property set to true and the Model project defines a shared application module instance named AppModule on the Business Components > Application Module Instances panel of the project properties. The AppModuleDataControl entry in the dataControlUsages section of the DataBindings.cpx file in the ViewController project has been configured to use the AppModuleShared configuration so that the UI works with a shared application module instance. As an optimization, the DeptView view object overrides the processDatabaseChangeNotification() method to keep track of the System.currentTimeMillis() in a local member field. The view object's getLastRequery() is exposed on the client interface and is accessed by the DepartmentPage backing bean's via a method action binding. That bean's onPollTimerExpired() 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 the Departments.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 the DEPT table and committing the changes. Sometime in the next 15 seconds, the different browser user's should update to reflect the changes automatically.
- 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 the EMAIL_MESSAGE and EMAIL_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 parent Email entity object. This validator uses Groovy code to work with a view accessor named ValidateOnePrimary which is of type EmailRecipientsView and has the design-time-applied view criteria named PrimaryRecipient (criteria mode "Both") applied to it. This view criteria filters based on the MessageId and the RecipientType='P' . The view accessor is configured to pass the value of the current Email entity's Id attribute as the value of the view criteria's VarMessageId 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 using adf.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 the EmailRecipient.RecipientType attribute uses an alternative approach to the view accessor in order to conditionally assign the default recipient type for a newly created EmailRecipient entity. The default expression is Email.Recipients.count("RecipientType == 'P' ? 1 : null") == 0 ? 'P' : 'C' which accesses the parent email message using the reverse association accessor named Email then accesses its rowset of recipients by references that email entity's Recipients association accessor attribute. Since the value of that expression is a RowSet we can use one of the built-in rowset, in-memory aggregation functions to calculate the count of the child EmailRecipient entity instances which have a RecipientType equal to P . The count() 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 of EmailRecipient instances having RecipientType equals to P is zero, then it returns the default value of P , otherwise it returns the default value of C to represent a recipient being copied on the mail. The Email entity object includes the MessageText attribute of type ClobDomain , and both the Email.SenderEmail and EmailRecipient.RecipientEmailAddress attributes use a custom domain type EmailAddress which validates the format of an email address. The NewMailMessage.jsff page fragment uses the special component to enable JSF to work properly with these three domain-valued attributes. The MailServer application module defines the custom method createNewMailAndPrimaryRecipient() 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 the create-new-email bounded task flow can invoke it declaratively to prepare the service layer for the creation of a new email. The CustomViewObjectImpl 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". The EmailRecipientsView in the example uses this framework extension class as its base class and has this custom property set. To run the example, run the TestPage.jspx . You'll need to login as either user userone or usertwo , both of whose password is welcome1 . Click on the button to create an "email" and then click (Send) to test the validation.
- This example illustrates an framework extension approach for adding a dynamic attribute named Valid to any view object whose value returns true if the primary entity usage in the row is valid, or false if it is invalid. The CustomViewObjectImpl class adds the dynamic attribute in its overridden create() method. The CustomViewRowImpl class overrides the getAttributeInternal() method to return the desired value for the dynamic attribute. The Emp entity object in the example has four different validation methods that enforce business rules like: (1) If Deptno=40, then Job must be SALESMAN or CLERK, (2) Salesmen in department 40 must have salary of 1500, (3) Clerks in department 40 must have salary 1000, and (4) Comm is not greater than Sal. The untitled1.jspx page in the ViewController project has a ADF Faces table and references the dynamic Valid attribute to highlight invalid rows in yellow using some appropriate EL expressions in the inlineStyle attribute of the fields in the table. The untitled1PageDef.xml file had to be hand-modified to include the dynamic Valid attribute in the AttrList of the EmpView table binding so that the EL expression used above of # would be resolvable. And finally, the Untitled1PageController class is registered as a custom page controller for the untitled1.jspx page (by setting the ControllerClass attribute at the root of the page def XML document. This custom controller overrides the default way that the validateModelUpdates() phase of the ADF page lifecycle is implemented to force invalid rows to be revalidated. This works around Bug# 5396224, where clicking a second time on the ADF faces table's "Next" or "Previous" navigation link causes a validation error to not be reported again.
- This example illustrates the methods to override in order to implement an entity object one or more of whose string attributes must be stored to the database in an encoded format. The example includes a simple CreateTablesAndPopulateData.sql script that creates a USER_INFO table with USERNAME and PASSWORD columns. As a trivial example of a entity object String-valued attribute stored in encoded format, the corresponding UserInfo entity object assumes that its Password should be stored in this way. The encoding technique employeed in the example is simple. A string like "abcd" is encoded when stored in the database as "[dcba]", that is, with its letters reversed and surrounded by brackets. Upon retrieving the entity object data from the database, the example decodes a queried value for the password by turning a string like "[dcba]" back into "abcd". The code is implemented as a CustomEntityImpl framework extension class, which the UserInfo entity uses as its base class. The generic encode/decode logic in this class is enabled on an entity object's String-valued attribute by setting the custom attribute property named EncodeValue , which the UserInfo entity's Password attribute has set. I was hoping the code involved would have been more elegant, and if I discover a more elegant approach I'll update this sample to reflect what I learn. Of course, we make the assumption that encoded attributes are not going to be user-queriable, however the example code does nothing to stop the user from trying to query on it.
- This example illustrates a simpler way to achive a variable IN list in a view object's query. For example, imagine that you want a DeptView view object to feature a WHERE like DEPTNO IN (:TheDeptNo) but you need the IN clause list to allow specifying one or more department numbers at runtime. One approach illustrated by example number 1 below involves writing some code that assigns an array of one or more deptno values for the bind variable. The approach presented here avoids the need for any code in the ADF layer by using a database function instead. Run the CreateTypeAndFunction.sql script to create the NUM_TABLE type and the IN_NUMBER_LIST() function. The function accepts a comma-separate string argument and returns a NUM_TABLE as its result. This allows the CommaSeparatedListOfDeptno bind variable in the example's DeptView view object to be of type String. The view object's WHERE clause looks like DEPTNO IN (SELECT * FROM TABLE( CAST ( in_number_list(:CommaSeparatedListOfDeptno) as num_table) ) ) . Run the AppModule in the tester can try entering values like "10" and "10,40" for the bind variable to see it in action.
- This example contains two read-only view objects in its Model project, one named MasterView and the other named ListBasedOnTableFunction . The former is a simple SELECT from DUAL that unions two rows of dummy data. The first row has the value "D" for its LIST_TYPE column, and the second row has the value "E". The ListForMasterRow view link defines a link between the master views ListType attribute and an attribute in the detail view object (which one doesn't actually matter), and it contains a custom view link SQL WHERE clause of simply "1 = 1". The ListBasedOnTableFunction view object defines a named bind variable Bind_ListType that has exactly the same name as the bind variable that the framework will automatically add for the view link. The expert-mode SQL statement for this view object references this bind variable as the argument to the GET_NAME_VALUE_LIST() PL/SQL function whose invocation it wraps in a TABLE() operator to treat the table-valued function result as if it were a table of data. The CreateTypesAndFunctions.sql script in the Model project creates the NAME_VALUE_TYPE object type, the NAME_VALUE_LIST type, and the GET_NAME_VALUE_LIST() function. The function is written to return a list of (Dname,Deptno) pairs from the DEPT table if the value passed in is 'D' and a list of (Ename,Empno) pairs if the value passed in is 'E'. Of course, the implementation of the function could be arbitrarily more interesting and dynamic without affecting the view object. The ViewController project contains a simple JSF page with a tree control displaying the two rows in the master view and their parameterized detail rows (which are a function of the value of the ListType attribute in each master row). The SwingView project contains a simple Panel1 panel with a similar Swing tree control showing the same thing.
- 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.
- This example contains a DepartmentDataFromXML view object that uses the SQL XML support in Oracle 9i Release 2 (or later) to query the data from an XML document into a view object. The view object accepts the XML text in a named bind variable, and uses the xmltype() constructor to treat that XML text as an XML document. Then it uses the xmlsequence() operator to treat the results of extract() -ing the / elements from the XML document as individual rows of source data. Finally, it uses the table() operator in combination with the extractValue() operator to retrieve the data values from each row of fragments, breaking out a DEPTNO , DNAME , and LOC value from the row. The TestPage.jspx in the ViewController project allows you to experiment with passing in different XML as the value of the bind variable.
- 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).
- 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.
- 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.
- 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.