Sei sulla pagina 1di 85

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


Name and date are cleared in HelloBean8.
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 reallyD..

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 value8..
8 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 8

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

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: name field now validated
in Apply request Values, before reset command 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 wait8. it works too well8
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 wait8. 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 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, 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 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. 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

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, can be defined separately from the list
of components that needs to be re-rendered
(refreshed).
Lets revisit our previous examples8.

JSF Lifecycle Postback Immediate


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

We clicked the Reset button8.


Name and date are cleared in HelloBean8.
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

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 persons
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

The af:target tag is your friend!


Lesson 16: When using JDeveloper 12c, use the
af:target tag to easily define which components
should be validated and submitted, and which
components should be re-rendered.

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)
8

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, 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 17: 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 18: 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

More Info
Understanding the JSF and ADF Optimized Lifeycle
Slides and sample apps downloadable
http://www.ateam-oracle.com/?p=3719

Avoiding JSF and ADF Lifecycle Frustrations


Shortened recording of this presentation by Frank Nimphius
http://download.oracle.com/otn_hosted_doc/jdeveloper/11gde
mos/JsfADFLifecycle/adfInsiderJsfAdfLifecycle.html

A Hidden Gem of ADF Faces: The af:target tag:


http://www.ateam-oracle.com/?p=20570

Final Recommendation
Write the 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!

Potrebbero piacerti anche