Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers 10g (10.1.3.1.0) Part Number B25947-01 |
|
|
View PDF |
With the page for the "Search Technicians by Name" use case implemented, you can turn your attention to the "Update Technician Profile" use case. Assuming you want the manager to be able to view all the attributes of the technician user when they go to update the profile, you'll need to create a view object that includes all the User
entity object's attributes to support the updateprofile.jspx
page. Once you add this new view object to the TechnicianService
's data model, you'll see it appear in the Data Control Palette, from where you can then drop it onto the updateprofile.jspx
page to create an edit form in one step.
To add a view object with all of the User
entity object's attribute, open the business component diagram again in the Model
project and drop a new view object from the Component Palette. Name the new view object Technicians
since it will be used to show all the data about technicians. Drop the User entity object onto the new view object in the diagram, and double-click the view object to open the View Object Editor. Using the editor you can:
Add the same WHERE clause you did for the SearchTechniciansByName
view object to query rows only where user_role = 'technician'
Set the UserId
attribute to be Updatable only While New to prevent the end user from updating the values of UserId
values in existing rows.
Back on the diagram drop the Technicians
view object onto the TechnicianService
to use it in the data model, and name the view object instance UpdateProfile
. Figure 2-32 shows the updated business service model. You'll notice that the corresponding UpdateProfile
data collection appears immediately in the Data Control Palette.
To open the visual editor for the updateprofile.jspx
page, open the JSF page flow diagram, double-click the /updateprofile.jspx
page and click Finish in the Create JSF JSP wizard.
You can build the edit form shown in Figure 2-33 with the following steps:
Drop a panelHeader
component from the ADF Faces Core page of the Component Palette onto the page and set its text
attribute in the Property Inspector to "Update Technician Profile".
Drop the UpdateProfile
data collection from the Data Control Palette and drop it onto the page as an ADF Form.
Expand the Operations folder of the TechnicianService data control in the Data Control Palette and drop its Commit
built-in operation in the "footer" facet folder of the panelForm
in the Structure window. Change its Text
property to "Save". Set its Disabled
property to "false". Set its Action
property to "BackToSearch" by picking it from the list to have the button follow the "BackToSearch" navigation rule you created in the JSF page flow diagram earlier.
Drop a Rollback
built-in operation to the "footer" facet of the panelForm
in the Structure window. Change its Text
property to "Cancel". Set its Disabled
property to "false". As with the Save button, set this button's Action
property to "BackToSearch".
When a manager finds the technician whose profile she wants to update, clicking the UpdateProfile button will take her to the updateprofile.jspx
page. In order for the updateprofile.jspx
page to know which technician to edit, you can use a declarative technique to set an attribute to the value of key that represents the current technician's row. Figure 2-34 shows the Structure window after a declarative setActionListener
component is added as a child of the Update Profile command button. This setActionListener
component evaluates one EL expression to determine the value to copy and another EL expression to determine the property to which to assign this value. The Property Inspector shows the EL expressions indicating that it should copy the value from the rowKeyStr
property of the Email
binding, and set it into the value of an attribute named rowKeyStr in the request scope.
In the page definition of the updateprofile.jspx
page, you can use another declarative technique to invoke an action binding for the built-in setCurrentRowWithKey
operation whenever the page is rendered. This action binding accepts a parameter whose value you can provide using the #{requestScope.rowKeyStr}
expression. In this way, without writing code you can use the key of the current row from the browse page to set the current row for editing in the UpdateProfile
data collection. These steps allow you to synchronize the two pages without writing code.
For a page like searchtechnicians.jspx
, sometimes you want the end user to immediately see results from the view object's query when they see the page for the first time. On other occasions, you might want the user to first have a chance to enter some search criteria before performing the query. Assuming you want the searchtechnicians.jspx
page to behave like this, you can conditionalize the initial display of data based on an EL expression. The expression that will come in handy for this tasks allows you to detect whether the page is being displayed for the first time, or whether the end-user has subsequently clicked a button or link on the page, causing the browser to post a request back to the server to handle the event. As shown in Figure 2-35, by setting the RefreshCondition
property on the TechniciansIterator
binding to the EL expression:
${adfFacesContext.postback == true}
you cause the iterator to present data only after the user has interacted with the page. When the page first renders, this postback property will be false, and the related data collection will be empty.
If you run the pages now you will see that they are working. A manager can search for technicians, browse their skills, update a technician's profile, and save changes. If the manager accidentally updates a piece of data that violates a business rule that you've encapsulated inside your domain business layer of entity objects, she will automatically see the error messages. Figure 2-36 shows the results of trying to update the email address to a value that contains the domain name. Similar errors would appear if you tried to violate the other business rules you added to the User
entity, or if you had additional view objects that referenced the same entity objects. When multiple managers use the application simultaneously, the ADF components comprising the business service automatically handle multi-user concurrency through row locking, lost-update protection, and application module pooling.