Referring to the post on Baig’s Technology Blog, Creating Shuttle Component in Oracle ADF , I was searching about a tutorial on how to use the SelectManyCheckBox and I found his post very interesting. Though, I thought it may be useful to give more details about the example in the post.
This tutorial is to present how to use the SelectManyCheckbox (Figure 1) & SelectManyShuttle (Figure 2) controls to present a many-to-many relationship.
From my development experience, there are lot of cases that we need to present a many-to-many relationship in our applications. The most used example is presenting access rights. As there are many users & groups, also there are many access rights/roles that can be assigned to users or groups. Our example here demonstrate on the famous example, many students , many courses & students may register in many Courses.
Both ADF controls, SelectManyCheckbox & SelectManyShuttle are almost the same. They both require the attribute named “value” and the child tag f:selectItems. Starting with the child tag f:selectItems, this tag represents the available items to be listed on both the SelectManyCheckbox & the SelectManyShuttle (the available courses in current example). The value attribute represents the selected items from the whole items. So, value attribute is the subset of the f:selectItems. These items should be selected in the SelectManyCheckBox or added to the right hand side in the case of SelectManyShuttle.
The question is, where is the power of ADF bindings & drag-and-drop capabilities? To implement this many-to-many relationship, we need to make some of our own handling, but still make use of the page bindings objects.
So, starting the page by dropping the students data control over the JSPX page, displaying it as SelectOneChoice, this control represents the combo box of all students. This control will play three roles in our example. First, the autosubmit attribute is set to true, to cause the page to invalidate the binding objects. Second, it will handle the valueChangeListener event in order to notify the SelectManyCheckBox or SelectManyShuttle that the current student is changed and the selectedItems should be changed also. Third, the control will be a partial trigger target to the SelectManyCheckBox or SelectManyShuttle. Both controls refers to it as the partial trigger target to be notified that the current student changed and the selected items should be refreshed.
Before going into the manual handling, we will define some page binding objects manually. Opening the binding of the JSPX page, switching to the bindings, we will define the following :
- CourseView1Iterator : this iterator is used manually in the helper class to iterate over all courses. This should refer to the courses view.
- StudentCourseView3Iterator : this iterator is used by the helper class to iterate over all the rows that represents the registration of a student in a course. It should refer to StudentCourseView3.
- Commit : this represents an action represents the Commit operation on the our data control to reflect any data update to the database.
- Id : this attribute represents a tracking of the selected student in the SelectOneChoice control.
The back bean here uses a helper class(instead of using writing the whole handling in the bean class itself) that consists of :
List selectedCourses;: this attribute represents a list to be bound on by the SelectManyCheckBox or SelectManyShuttle.
List allCourses;: this attribute represents a list of all available courses to be bound on by the child f:selectItems.
attributeListForIterator: this method is used to retrieve a list of the rows in a specific iterator. It only retrieve only one attribute in each row (the student ID in this example, it is used to retrieve the registered courses).
selectItemsForIterator: this method is the same as the previous one, but this method retrieves two specific attributes (it is used to retrieve all courses with each row contains the ID & name of the course).
getCurrentStudentId: this method retrieves the current selected student in the selectOneChoice using the manually defined binding attribute “Id”.
getSelectedCourses: this method is a modified version of the selectedCourses list accessor to check if the selectedList should be refreshed.
getAllCourses: this method uses the selectItemsForIterator method to retrieve all courses.
processShuttle: this method is responsible for the update/commit operation. it first removes the current registered courses of the selected student. Then, it creates new rows representing the selected courses. Finally, it commits these created rows to the database to update the registered courses.
refreshSelectedList: this is a flag to refer if the selected courses should be changed.
A mistake I made when I implemented this example, was that I forgot to expose the setter of the helper class in the back bean of the page. This led to the SelectManyCheckbox not be shown at all. It was a silly mistake, though it wasted me time to figure what is wrong as ADF Faces framework didn’t provide exception or error refering to inaccisiblility to a bound value property (the value of the SelectManyCheckbox here).
Here is a screen of the application after it launches.
ADF Business Components Transaction & Caching
Another topic that i read about is transactions management in ADF BC. As the application module is the part responsible for it, application modules. Application module instance corresponds to a single database transaction. Any nested, child application modules manipulates the data found in the parent application module (creating rows, querying ..).
Application modules maintains caches for cache of data inside it , update its caches when the transaction is committed & rollback the caches if the transaction is rolled back. So, in our example, all the change we make is cached in the application module. After clicking on the save button, the data is updated into the database and the application module cache is updated.
What if someone modified the database, using another session of the application, application module instance handles this using RDBMS locking feature. So that when the object entity instance try to update a row, it requests a lock first on that row till the transaction is committed or rolled back. Any other transaction trying to update this row will make the entity object instance to throw an exception specifying that the row is locked.
Finally, I hope you found the tutorial useful.
- Creating Shuttle Component in Oracle ADF by Baig Almaty.
- Oracle JDeveloper 11g Handbook , Oracle Press.