<Insert Picture Here>18 Invaluable Lessons About ADF Faces Page Lifecycle Steven Davelaar twitter:@stevendavelaar blogs: www.ateam-oracle.com and blogs.oracle.com/jheadstart Oracle Fusion Middleware Architects Team (the “A-team”) Agenda • Worls’s most comprehensive Hello World Demo Just Say Hello – JSF Lifecycle Initial 1. Restore View UI Component Tree RichPanelHeader RichPanelGroupLayout RichPanelFormLayout RichInputText RichInputDate 6. Render Response JSF Lifecycle - Postback 1. Restore View 2. Apply Request Values richInputText.setSubmittedValue(“Steven”) richInputDate.setSubmittedValue(“04-12-2012”) Postback 1.setValue() with converted value if valid • Clear submittedValue • Queue valueChange event (if applicable) .JSF Lifecycle . Process Validations • Validate and convert (if needed) name and date • Call richInputText. Apply Request Values 3. Restore View 2. setName with component value • Call HelloBean.name} value=“#{viewScope.date} 2.JSF Lifecycle Postback 1.HelloBean.setDate with component value • Clear submitted and (local) component value . Restore View value=“#{viewScope. Apply Request Values 3. Process Validations 4.HelloBean. Update Model • Call HelloBean. helloBean. Update Model 5. Apply Request Values actionListener=“#{viewScope. Invoke Application • Call HelloBean.sayHello} 3. Restore View 2.JSF Lifecycle Postback 1.sayHello . Process Validations 4. Update Model 5. Process Validations 4. Apply Request Values 3. Restore View 2.Postback 1.JSF Lifecycle . Render Response . Invoke Application 6. Current Lifecycle Phase in JDeveloper while Debugging . Just Say Hello – Reset Values • Clicking the Reset button should not fire validation. and should clear the Name and Date fields • We need a lifecycle shortcut that bypasses validation (both client-side and server-side) and model update . skipping validation and model update phases. . Render Response.JSF Lifecycle – Postback Immediate • Lesson 1: An immediate command executes the action and actionListener in phase 2. Apply Request Values and then jumps to phase 6. Restore View 2.reset . Apply Request Values • richInputText.JSF Lifecycle – Postback Immediate 1.setSubmittedValue(“Steven”) • richInputDate.setSubmittedValue(“04-12-2012”) • Call HelloBean. Restore View 2. But we still see the old values in the page! How come?? . Apply Request Values 6. Render Response • • • • We clicked the Reset button8.JSF Lifecycle – Postback Immediate 1. Name and date are cleared in HelloBean8. util. the UI components do NOT re-evaluate their underlying value binding.ResetUtils. the reset action • Clears the submittedValue • Clears local component value so value binding is re-evaluated • Marks the component as valid .JSF Lifecycle – Postback Immediate • Lesson 2: When executing an immediate command.rich.resetValue() • On an individual UI component. possibly showing stale data • How to force the UI components to do this? • Three options • Use af:resetActionListener • Use oracle.adf.reset() • UIComponent.view. reset() instead. no Java method needed • Automatically added when dragging and dropping a Rollback operation from Data Control Palette • Lesson 3: af:resetActionListener does NOT reset child regions.Using af:resetActionListener • Easiest option. . use ResetUtils. reset(UIComponent startComponent) • Reset method takes one parameter: the start UI Component to reset • However. subform.Using ResetUtils. carrousel or panelCollection is found • that component is used as the real starting point . this is not the REAL start component • Is used to traverse up the component tree • until a region. popup. form. Agenda • Worls’s most comprehensive Hello World Demo . Say Hello Suggestions • Suggest the type of greeting based on a person’s name . .Say Hello Suggestions – Will this work? Not reallyD.. getName() will return null (or old model value): remember lesson 1! • AND (wrong) greeting will NOT be displayed anyway: remember lesson 2! .Say Hello Suggestions – Will immediate=true work? • No. model is no longer updated. • 8 we need to call resetValue on the greeting inputText ..Say Hello Suggestions – Challenges • We need immediate=true to prevent premature validation of greeting field and date field • We need to refresh the greeting field properly • We need somehow to get hold of value entered in name field • We do want required validation on name field ----------------------------------------------------------------------• We already learned how to refresh the greeting field with underlying model value8. Say Hello Suggestions – Use Binding Property to Refresh Greeting Field . Say Hello Suggestions – Greeting Field Refreshed • At least the suggested greeting is displayed now. although it is still the wrong default greeting because getName() returns null in the suggest method . • UI Tree not released properly. causing errors in clustered env. even ComponentReference won’t be safe then. more memory usage • UI component might be reused in UI Tree of another page (fragment) • This can happen EVEN with request-scoped and backingBean-scoped beans • Lesson 4: Always use ComponentReference in component binding getter/setter methods • Lesson 5: Never use component binding in sessionscoped bean. .Side Step – More About Component Binding • The getter/setter methods generated by JDeveloper when using binding property are wrong • Code is not serializable. Side Step – Correct Code for Component Binding Methods . com/groundside/entry/the_uimanager_pattern • You can also find a component by id programmatically using invokeOnComponent API • See (google for) “ADF Code Corner sample 58” • Starting UI component should be as low as possible in UI Tree.oracle. multi-tab pages . starting at UIViewRoot can kill performance with large.Side Step – More About Component Binding • Component binding is often overly used • Use UIManager pattern from Duncan Mills to avoid unnecessary component binding • https://blogs. Say Hello Suggestions – Challenges • We need immediate=true to prevent premature validation of greeting field and date field • We need to refresh the greeting field properly • We need somehow to get hold of value entered in name field • We do want required validation on name field • ----------------------------------------------------------------------• May be we can use a valueChangeListener on name field? • May be we can use immediate=true on the name field? . Say Hello Suggestions – Using a ValueChangeListener • ValueChangeListener fires in phase 3. let’s set immediate=true on name field 8 . Process Validations • That phase is skipped with immediate command • Now. .Say Hello Suggestions – Using a ValueChangeListener • Lesson 6: When immediate=“true” on an Editable UI Component • Component validation is processed in phase 2. now it works! • But wait 8. Apply Request Values • The validated and converted value is stored on the component • valueChangeListener is also called in this phase • YES. before reset command is executed.Say Hello Suggestions – Using immediate on editable component • If we enter all fields except name. Arrrrggghhh! . then Reset button no longer works! • Why? Because of Lesson 6: name field now validated in Apply request Values. because then the general rule “Validations are skipped when setting a command component to immediate=“true” is no longer true! • Lesson 7: Never set immediate=“true” on an editable UI component.Say Hello Suggestions – Using Immediate on Editable Component • This makes setting immediate=“true on an editable UI component pretty useless. . it prevents you from cancelling/abandoning a page. Say Hello Suggestions – Back to the Challenges • We need immediate=true to prevent premature validation of greeting field and date field • We need to refresh the greeting field properly • We need somehow to get hold of value entered in name field • We do want required validation on name field ----------------------------------------------------------------------• Not a solution: valueChangeListener and immediate=true on name field • New solution: we need to get the value entered for name directly from the UI component . Say Hello Suggestions – Use Component Binding to Get Name Value • YES. it works too well8 • Method should not execute when name empty. or less than 4 chars . this works. and the reset button still works too! • But wait8. Process Validations in phase 3 • Validate and convert (if needed) name and date • Call richInputText. possibly invalid value by calling getSubmittedValue() on the name field • We need to do programmatically what normally happens automatically 3.setValue() with converted value if valid • Clear submittedValue • Queue valueChange event (if applicable) .Say Hello Suggestions – Use Component Binding to Get Name Value • We are using the raw. getCurrentInstance()) • comp.getCurrentInstance()) .processValidations(FacesContext.Say Hello Suggestions – Use Component Binding to Get Name Value • Lesson 8: You can programmatically execute JSF lifecycle phases 3 and 4 on a component: • comp.processUpdates(FacesContext. only the greeting field needs to be refreshed in browser. • Easily implemented using ADF Faces PPR .Say Hello Suggestions – Optimizing Using Partial Page Rendering (PPR) • When clicking the suggest button. Agenda • Worls’s most comprehensive Hello World Demo Sub Forms of Hello Saying • It was quite a challenge to get this greeting suggestion implemented • Is there really no easier way to do this? • The af:subform tag represents an independently submittable region of a page. The contents of a subform will only be validated (or otherwise processed) if a component inside of the subform is responsible for submitting the page. • Sounds promising, let’s try! Sub Forms of Hello Saying – Try 1 Sub Forms of Hello Saying – Try 1 align accross panelFormLayouts using labelWidth property • Submitting the main form. • Fix: put all items in sub-forms • Lesson 10: Layout messed up when using sub form • Fix: Each subform must contain its own panelFormLayout.Sub Forms of Hello Saying –Try 1 Findings • Lesson 9: Items not in any sub-form are still processed in lifecycle when submitting a sub-form. does not submit items in sub-form • Solution: set property default=“true” on the subform . Sub Forms of Hello Saying – Try 2 . what is functionally different from previous samples? • Greeting field is not required. what if we fix that? .Sub Forms of Hello Saying – Try 2 Findings • • • • Suggest button now works with empty date! Layout cleaned up! Pressing enter key on name shows suggested greeting! But wait8. Sub Forms of Hello Saying – Try 2 Findings • Let’s try to move greeting field to other subform . Sub Forms of Hello Saying – Try 3 . Sub Forms of Hello Saying – Try 3 Findings • No validation error on greeting field! • But greeting no longer shown • Lesson 11: Partial page refresh does not work across sub-forms • Sub forms do not work for this use case . Conclusion • Sub forms can be used in corner cases to avoid premature validation • Sub forms most useful for “default command” behavior .Sub Forms of Say Hello . Agenda • Worls’s most comprehensive Hello World Demo . Auto-Suggested Hello Saying • Auto-suggest the type of greeting when tabbing out the name field . Auto-Suggested Hello Saying – Will this work? • Will field validations fire prematurely? • Will greeting field be refreshed correctly? . with code in previous slide no premature validations fire but greeting field is not refreshed • So.Auto-Suggested Hello Saying – ADFoptimized lifecycle • Using autoSubmit = true on an editable UI Component kicks of the ADF-Optimized JSF Lifecycle • This optimized lifecycle always: • fires a partial submit • By default will only process and refresh the autoSubmitted component itself • Additional UI components will be processed in this lifecycle when partialTriggers property points to autoSubmitted item • So. what will happen when we add partialTrigger property to greeting field? . make greeting optional 2. add greeting programmatically as partial target .Auto-Suggested Hello Saying – Refreshing Greeting Field • Greeting field now processed as well -> validation error when null • Solutions: 1. nothing happens! • Why?? .Auto-Suggested Hello Saying – Making Greeting Optional • Making greeting optional seems to work • But it doesn’t work always 8 • It does not work when user clears greeting first • User clears existing greeting • User navigates back to name field and changes the name • User tabs out name field. Apply Request Values 3. Restore View 2.nameChanged which in turn calls.setGreeting(“Hi”) .What happens when greeting is cleared 1. Process Validations • Calls valueChangeListener method HelloBean. What happens when greeting is cleared 1. Restore View 2. Apply Request Values 3. . Process Validations 4. Update Model • Calls HelloBean.setGreeting(null) • Overrides the value set by valueChangeListener method D. How to prevent suggested greeting is overridden again • The JSF Model Update phase only updates underlying model value when the local component value differs from the model value • We need to reset the local UI Component value in namedChanged method . Auto-Suggested Hello Saying – Refreshing Greeting Field In Code . Auto-Suggested Hello Saying – Lessons Learned 12. Use programmatic PPR instead of partialTriggers property to prevent components to be processed by ADF optimized lifecycle. Auto-submitted fields use ADF optimized lifecycle preventing premature validation on other fields 13. This is known as Cross Component Refresh 14. avoiding premature validation . The components that are processed by ADF optimized lifecycle can be configured using partialTrigger property. Values set in value change listeners might be overridden in model update phase if not coded correctly 15. can be defined separately from the list of components that needs to be re-rendered (refreshed). .New in JDeveloper 12c: the af:target tag! • Provides a declarative way to allow a component to specify the list of targets it wants executed and rendered when an event is fired by the component. • The list of components on which the JSF lifecycle will be executed. • Let’s revisit our previous examples8. JSF Lifecycle – Postback Immediate 1. Restore View 2. Render Response • • • • We clicked the Reset button8. But we still see the old values in the page! How come?? . Name and date are cleared in HelloBean8. Apply Request Values 6. rich.resetValue() • On an individual UI component.adf.ResetUtils. possibly showing stale data • How to force the UI components to do this? • Three options • Use af:resetActionListener • Use oracle.JSF Lifecycle – Postback Immediate • Lesson 2: When executing an immediate command.view. the reset action • Clears the submittedValue • Clears local component value so value binding is re-evaluated • Marks the component as valid .reset() • UIComponent. the UI components do NOT re-evaluate their underlying value binding.util. Implementing Reset/Cancel Functionality using af:target tag! • No need to set immediate=true on the button • No issues with fields not being refreshed • No issues with subregions not being refreshed when using af:resetActionListener . Say Hello Suggestions • Suggest the type of greeting based on a person’s name . Say Hello Suggestions – Challenges • We need(ed) immediate=true to prevent premature validation of greeting field and date field • We need to refresh the greeting field properly • We need somehow to get hold of value entered in name field • We do want required validation on name field ----------------------------------------------------------------------• With af:target tag this becomes easy! . Suggest Greeting Using af:target tag . Auto-Suggested Hello Saying • Auto-suggest the type of greeting when tabbing out the name field . Auto-Suggest Greeting Using af:target tag . use the af:target tag to easily define which components should be validated and submitted.The af:target tag is your friend! • Lesson 16: When using JDeveloper 12c. . and which components should be re-rendered. Agenda • A bit more on the ADF optimized lifecycle . the boundary is the component itself • Boundaries can be changed by using partialTriggers property . when autosubmitting an editable field.ADF Optimized Lifecycle • ADF Faces sets boundaries on the page that allow the JSF lifecycle to run just on components within the boundary • As we learned before. rangeChangeEvent. context menu. selectionEvent • Events on showDetailIHeader: disclosureEvent • Events on panelAccordion (showDetailIItem) : disclosureEvent • Events on components inside panelCollection (toolbar. columnSelectionEvent. treeTable: disclosureEvent. etc • Events on tree: disclosureEvent.ADF Optimized Lifecycle • A number of component events always trigger the optimized lifecycle • Events on table. etc) • 8 . selectionEvent. Optimized Lifecycle of Employees – Overflow Right • When clicking on another row • Overflow area should be refreshed • Changes in overflow area should be preserved . Optimized Lifecycle of Employees – Configuring optimized lifecycle • When clicking on another row. changes in overflow area are now preserved . Optimized Lifecycle of Employees – Adding New Employee • Clicking the New Employee button should also preserve changes made in table overflow area • Easy8 works out-of-the-box • Now. let’s move that button to panelCollection toolbar . Optimized Lifecycle of Employees – Adding New Employee • Now. it will NOT work out-of-the-box • Button inside panelCollection will trigger optimized lifecycle • Changes in table overflow area will not be submitted • What is the “obvious” fix? . the partialTrigger property must point to the boundary component • In this use case. the boundary component of the optimized lifecycle is the panelCollection • So.Optimized Lifecycle of Employees – Adding New Employee • “Obvious” fix is to add button id to partialTriggers property of panelFormLayout • Lesson 17: To add components that should be processed in optimized lifecycle. this will work: • Note that you can use cascading partialTriggers • If panelCollection partialTriggers property refers to table. panelFormLayout only needs to refer to panelCollection . “obvious” fix does not work. Agenda • Worls’s most comprehensive Hello World Demo . Say Hello with a Song . Say Hello with a Song • Choose Song checkbox will need autoSubmit = true • Question 1: Can we use a partialTrigger property or do we need programmatic PPR to show/hide the Song drop-down list? • Song selectOneChoice will need autoSubmit = true • Question 2: Can we use a partialTrigger property or do we need programmatic PPR to show/hide the YouTube video frame? . Say Hello with a Song • Choose Song checkbox will need autoSubmit = true • Question 1: Can we use a partialTrigger property or do we need programmatic PPR to show/hide the Song drop-down list? • Song selectOneChoice will need autoSubmit = true • Question 2: Can we use a partialTrigger property or do we need programmatic PPR to show/hide the YouTube video frame? . Say Hello with a Song – Try 1 • Will this work? . so we use programmatic PPR • Answer 2: No validation issues. we can safely use partialTriggers property . the parent component should be refreshed • Answer 1: we need to refresh the enclosing panelFormLayout to see the song selectOneChoice • Using partialTrigger would cause premature validation errors (lesson 15).Say Hello with a Song • Lesson 18: To show/hide a component. Say Hello with a Song – Correct Code . oracle.ateam-oracle.com/?p=3719 • Avoiding JSF and ADF Lifecycle Frustrations • Shortened recording of this presentation by Frank Nimphius • http://download.More Info • Understanding the JSF and ADF Optimized Lifeycle • Slides and sample apps downloadable • http://www.com/?p=20570 .com/otn_hosted_doc/jdeveloper/11gde mos/JsfADFLifecycle/adfInsiderJsfAdfLifecycle.html • A Hidden Gem of ADF Faces: The af:target tag: • http://www.ateam-oracle. print them. learn them by heart.Final Recommendation • Write the lessons down. it will save you tons of frustration! . put them on the wall. and rehearse them every week.
Comments
Report "18 Invaluable Lessons About ADF-JSF Interaction"