Anda di halaman 1dari 74

<Insert Picture Here>

18 Invaluable Lessons About ADF-JSF Interaction


FKA: What You Need To Know About JSF To Be Succesful With ADF Steven Davelaar twitter:@stevendavelaar blogs: blogs.oracle.com/jheadstart and blogs.oracle.com/ateam_webcenter Oracle Fusion Middleware Architects Team (the A-team)

Agenda
Worlss 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)

JSF Lifecycle - Postback


1. Restore View 2. Apply Request Values 3. Process Validations

Validate and convert (if needed) name and date Call richInputText.setValue() with converted value if valid Clear submittedValue Queue valueChange event (if applicable)

JSF Lifecycle Postback


1. Restore View
value=#{viewScope.HelloBean.name} value=#{viewScope.HelloBean.date} 2. Apply

Request Values

3. Process Validations 4. Update Model

Call HelloBean.setName with component value Call HelloBean.setDate with component value Clear submitted and (local) component value

JSF Lifecycle Postback


1. Restore View 2. Apply Request Values
actionListener=#{viewScope.helloBean.sayHello}

3. Process Validations 4. Update Model 5. Invoke Application

Call HelloBean.sayHello

JSF Lifecycle - Postback


1. Restore View 2. Apply Request Values 3. Process Validations 4. Update Model 5. Invoke Application 6. Render Response

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

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. Render Response, skipping validation and model update phases.

JSF Lifecycle Postback Immediate


1. Restore View 2. Apply Request Values

richInputText.setSubmittedValue(Steven) richInputDate.setSubmittedValue(04-12-2012) Call HelloBean.reset

JSF Lifecycle Postback Immediate


1. Restore View 2. Apply Request Values 6. Render Response

We clicked the Reset button . Name and date are cleared in HelloBean . But we still see the old values in the page! How come??

JSF Lifecycle Postback Immediate


Lesson 2: When executing an immediate command, the UI components do NOT re-evaluate their underlying value binding, possibly showing stale data How to force the UI components to do this? Three options
Use af:resetActionListener Use oracle.adf.view.rich.util.ResetUtils.reset() UIComponent.resetValue()

On an individual UI component, the reset action


Clears the submittedValue Clears local component value so value binding is re-evaluated Marks the component as valid

Using af:resetActionListener
Easiest option, 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, use ResetUtils.reset() instead.

Using ResetUtils.reset(UIComponent startComponent)


Reset method takes one parameter: the start UI Component to reset

However, this is not the REAL start component


Is used to traverse up the component tree until a region, form, subform, popup, carrousel or panelCollection is found that component is used as the real starting point

Agenda
Worlss most comprehensive Hello World Demo

Say Hello Suggestions


Suggest the type of greeting based on a persons name

Say Hello Suggestions Will this work?

Not really ..

Say Hello Suggestions Will immediate=true work?

No, model is no longer updated, 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 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 value .. we need to call resetValue on the greeting inputText

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

Side Step More About Component Binding


The getter/setter methods generated by JDeveloper when using binding property are wrong
Code is not serializable, causing errors in clustered env. UI Tree not released properly, 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, even ComponentReference wont be safe then.

Side Step Correct Code for Component Binding Methods

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.oracle.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, starting at UIViewRoot can kill performance with large, multi-tab pages

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. Process Validations That phase is skipped with immediate command Now, lets set immediate=true on name field

Say Hello Suggestions Using a ValueChangeListener

Lesson 6: When immediate=true on an Editable UI Component


Component validation is processed in phase 2. Apply Request Values The validated and converted value is stored on the component valueChangeListener is also called in this phase

YES, now it works! But wait .

Say Hello Suggestions Using immediate on editable component


If we enter all fields except name, then Reset button no longer works! Why? Because of Lesson 6: component validation takes place before the command action/actionListener is executed. Arrrrggghhh!

Say Hello Suggestions Using Immediate on Editable Component


This makes setting immediate=true on an editable UI component pretty useless, 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, 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, this works, and the reset button still works too! But wait . it works too well
Method should not execute when name empty, or less than 4 chars

Say Hello Suggestions Use Component Binding to Get Name Value


We are using the raw, possibly invalid value by calling getSubmittedValue() on the name field We need to do programmatically what normally happens automatically 3. Process Validations in phase 3
Validate and convert (if needed) name and date Call richInputText.setValue() with converted value if valid Clear submittedValue Queue valueChange event (if applicable)

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.processValidations(FacesContext.getCurrentInstance()) comp.processUpdates(FacesContext.getCurrentInstance())

Say Hello Suggestions Optimizing Using Partial Page Rendering (PPR)


When clicking the suggest button, only the greeting field needs to be refreshed in browser. Easily implemented using ADF Faces PPR

Agenda
Worlss 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, lets try!

Sub Forms of Hello Saying Try 1

Sub Forms of Hello Saying Try 1

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.
Fix: put all items in sub-forms

Lesson 10: Layout messed up when using sub form


Fix: Each subform must contain its own panelFormLayout, align accross panelFormLayouts using labelWidth property

Submitting the main form, does not submit items in sub-form


Solution: set property default=true on the subform

Sub Forms of Hello Saying Try 2

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 wait . 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

Lets 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

Sub Forms of Say Hello - Conclusion

Sub forms can be used in corner cases to avoid premature validation Sub forms most useful for default command behavior

Agenda
Worlss 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?

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, with code in previous slide no premature validations fire but greeting field is not refreshed So, what will happen when we add partialTrigger property to greeting field?

Auto-Suggested Hello Saying Refreshing Greeting Field

Greeting field now processed as well -> validation error when null Solutions:
1. make greeting optional 2. add greeting programmatically as partial target

Auto-Suggested Hello Saying Making Greeting Optional


Making greeting optional seems to work But it doesnt work always 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, nothing happens!

Why??

What happens when greeting is cleared


1. Restore View 2. Apply Request Values 3. Process Validations

Calls valueChangeListener method HelloBean.nameChanged which in turn calls.setGreeting(Hi)

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 .

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. Auto-submitted fields use ADF optimized lifecycle preventing premature validation on other fields 13. The components that are processed by ADF optimized lifecycle can be configured using partialTrigger property. This is known as Cross Component Refresh 14. Values set in value change listeners might be overridden in model update phase if not coded correctly 15. Use programmatic PPR instead of partialTriggers property to prevent components to be processed by ADF optimized lifecycle, avoiding premature validation

Agenda
A bit more on the ADF optimized lifecycle

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, when autosubmitting an editable field, the boundary is the component itself Boundaries can be changed by using partialTriggers property

ADF Optimized Lifecycle


A number of component events always trigger the optimized lifecycle
Events on table, treeTable: disclosureEvent, selectionEvent, rangeChangeEvent, columnSelectionEvent, etc Events on tree: disclosureEvent, selectionEvent Events on showDetailIHeader: disclosureEvent Events on panelAccordion (showDetailIItem) : disclosureEvent Events on components inside panelCollection (toolbar, context menu, etc)

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 Easy works out-of-the-box Now, lets 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?

Optimized Lifecycle of Employees Adding New Employee


Obvious fix is to add button id to partialTriggers property of panelFormLayout Lesson 16: To add components that should be processed in optimized lifecycle, the partialTrigger property must point to the boundary component In this use case, the boundary component of the optimized lifecycle is the panelCollection So, obvious fix does not work, this will work: Note that you can use cascading partialTriggers
If panelCollection partialTriggers property refers to table, panelFormLayout only needs to refer to panelCollection

Agenda
Worlss 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?

Say Hello with a Song


Lesson 17: To show/hide a component, 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), so we use programmatic PPR

Answer 2: No validation issues, we can safely use partialTriggers property

Say Hello with a Song Correct Code

Final Recommendation
Lesson 18: write previous 17 lessons down, print them, put them on the wall, learn them by heart, and rehearse them every week, it will save you tons of frustration!