83
1

Errores Mas Comunes Oracle Adf

Embed Size (px)

Citation preview

Page 1: Errores Mas Comunes Oracle Adf

1

Page 2: Errores Mas Comunes Oracle Adf

2

The following is intended to outline our general

product direction. It is intended for information

purposes only, and may not be incorporated into any

contract. It is not a commitment to deliver any

material, code, or functionality, and should not be

relied upon in making purchasing decisions.

The development, release, and timing of any

features or functionality described for Oracle’s

products remains at the sole discretion of Oracle.

Page 3: Errores Mas Comunes Oracle Adf

<Insert Picture Here>

Classic Mistakes with Oracle Application Development Framework

Internal APIs

Duncan Mills, Frank Nimphius

Oracle Application Development Tools

Product Management

Page 4: Errores Mas Comunes Oracle Adf

4

Oracle Fusion Middleware

Page 5: Errores Mas Comunes Oracle Adf

5

To err is human and every developer has the

right to make mistakes.

Don't abuse this privilege !

Page 6: Errores Mas Comunes Oracle Adf

6

ADF Framework

Mistakes

Page 7: Errores Mas Comunes Oracle Adf

7

Using Internal Packages

• ADF Faces, Trinidad and ADF Controller have an API

package and an IMPL package

– Define logical framework abstractions

– Simplifies implementation of future product changes

• APIs in public packages

– guaranteed to remain stable from release to release

• APIs in IMPL package are internal-only

– Not to be used outside of framework

– Can be modified at any time without notice

• Internal packages have "internal" in the naming

Page 8: Errores Mas Comunes Oracle Adf

8

Binding Classes – The Java in ADF

FacesCtrl* Bindings

Page 9: Errores Mas Comunes Oracle Adf

9

FacesCtrlHierBinding

FacesCtrlHierBinding binding expose the convenient methods I need. My expert tip: Always use these classes

<af:table value="#{bindings.allLocations.collectionModel}"

selectionListener="#{myBean.onTableSelect}"/>

public void onTableSelect(SelectionEvent selectionEvent) {

// --- perform optional pre-processing here --- //

RichTable _table = (RichTable ) selectionEvent.getSource();

CollectionModel model = (CollectionModel ) _table.getValue();

FacesCtrlHierBinding _binding =

(FacesCtrlHierBinding) model.getWrappedData();

FacesCtrlHierBinding.FacesModel treeModel =

(FacesCtrlHierBinding.FacesModel) _binding.getTreeModel();

treeModel.makeCurrent(selectionEvent);

// --- perform optional post-processing here --- //

}

Example(s)

Page 10: Errores Mas Comunes Oracle Adf

10

FacesCtrlHierBinding

• Don't use FacesCtrlHierBinding and FacesCtrlHierNodeBinding

directly

– Internal ADF Faces component model for tree, table and treeTable

• Use EL in Java: #{bindings.allDepartments.treeModel.makeCurrent}

– Pro:

• Easy to use

• Does it right for all Data Control types

– Con:

• Requires knowledge about the PageDef definition

• Use JUCtrlHierBinding, JUCtrlHierNodeBinding

– Pro:

• No knowledge about binding layer required

– Con:

• More code to write

• Requires advanced ADF skills

Page 11: Errores Mas Comunes Oracle Adf

11

Replacing FacesCtrlHierBinding

How-to use JUCtrlHierBinding to make the selected table row the current row in the ADF Binding

public void onTableSelect(SelectionEvent selectionEvent) {

// --- perform optional pre-processing here --- //

RichTable _table = (RichTable ) selectionEvent.getSource();

CollectionModel model = (CollectionModel ) _table.getValue();

JUCtrlHierBinding _binding = (JUCtrlHierBinding) model.getWrappedData();

DCIteratorBinding iteratorBinding = _binding.getDCIteratorBinding();

Object _selectedRowData = _table´.getSelectedRowData();

JUCtrlHierNodeBinding node = (JUCtrlHierNodeBinding) _selectedRowData ;

Key rwKey = node.getRowKey();

iteratorBinding.setCurrentRowWithKey(rwKey.toStringFormat(true));

// --- perform optional post-processing here --- //

}

Example(s)

Page 12: Errores Mas Comunes Oracle Adf

12

Other Mistakes

• Unnecessary casting to Faces binding classes

– the reference to Faces Binding object is obtained while

invoking non-faces specific binding methods.

– In this case, replaced FacesCtrl* binding with JUCtrl* binding

• Caching as member variables

– Faces binding reference as member variable, exposing public

getter and setter methods

– In general, don't cache the binding reference

Page 13: Errores Mas Comunes Oracle Adf

13

ADF Bindings Mistakes

Page 14: Errores Mas Comunes Oracle Adf

14

#{data.} Expression Root

I can use the #{data…} root in my EL to pullinformation from another Binding Container!

<af:outputText value="#{data.demo_v1PageDef.LastName}"/>

public static ApplicationModule

getApplicationModuleForDataControl(String name){

return(ApplicationModule)JSFUtils.resolveExpression(

"#{data." + name + ".dataProvider}");

}

Example(s)

Page 15: Errores Mas Comunes Oracle Adf

15

#{data.} Expression Root

• Sorry – not reliable, may not always work

– #{data.} accesses the binding cache and may not work if

• You’ve never instantiated that binding container

• You’ve just had a fail-over on a cluster

• Plus it’s sloppy design – if the UI needs the data, then say

so!

• Safer approach

– Create an explicit binding in the relevant pageDef and use #{bindings.*}

– In the finding the AM case, use an Action Binding

• findCtrlBinding() getDataControl()

getDataProvider()

Page 16: Errores Mas Comunes Oracle Adf

16

Accessing the "bindings" object using EL

I access the ADF binding layer from EL in Java, using #{bindings} . Objections ?

FacesContext fctx = FacesContext.getCurrentInstance();

ELContext elctx = fctx.getELContext();

Application app = fctx.getApplication();

ExpressionFactory efactory = app.getExpressionFactory();

ValueExpression vex = efactory.createValueExpression(

elctx,"#{bindings}", Object.class);

DCBindingContainer bindings = (DCBindingContainer) vex.getValue(elctx);

Example(s)

Page 17: Errores Mas Comunes Oracle Adf

17

Accessing the "bindings" object using EL

• Yes your honor – objection !

• You can use Java instead of EL (things have moved

on)

BindingContext bindingContext = BindingContext.getCurrent();

BindingContainer bindings = bindingContext.getCurrentBindingsEntry();

Page 18: Errores Mas Comunes Oracle Adf

18

Using page fragments

Adding a page fragment to my ADF page does not render the ADF bound data content

<af:document id="d1">

...

<f:subview id="sv1">

<jsp:include page="/allDepartments.jsff"/>

</f:subview>

...

</af:document>

Example(s)

Page 19: Errores Mas Comunes Oracle Adf

19

Using page fragments

• JSP include only include the page content, not the

ADF binding dependency

• Suggestions

– Copy the page fragment PageDef content into the PageDef

file of the parent page

– Use ADF Faces page templates if the content you include is

used on many pages

• Templates can have bindings

– Use ADF Regions

• Bounded task flows

• Can have their own bindings

Page 20: Errores Mas Comunes Oracle Adf

20

Adding new Rows

ADF bound table does not show new rows created in View Object

BindingContext bctx = BindingContext.getCurrent();

DCDataControl dc = bctx.findDataControl("AppModuleLocal");

ApplicationModule am = (ApplicationModule)dc.getDataProvider();

ViewObject vo = am.findViewObject("EmployeesVO1");

Row rw = vo.createRow();

rw.setAttribute("EmployeeId", 1234);

Example(s)

Page 21: Errores Mas Comunes Oracle Adf

21

Don't fight the framework !

Page 22: Errores Mas Comunes Oracle Adf

22

Adding new Rows

• You almost created a mine field!

– Ignoring separation of layers

– Bypassing the ADF binding layer

– Making assumptions about the Data Control provider

– Ignoring our message of what ADF is designed for

• Try working through the ADF binding layer

BindingContext bctx = BindingContext.getCurrentInstance();

BindingContainer bindings = bctx.getCurrentBindingEntry()

DCIteratorBinding dcIterator =

(DCIteratorBinding) bindings.get("IteratorBindingName");

Row rw = dcIteratorBinding.getRowSetIterator().createRow();

rw.setNewRowState(Row.STATUS_INITIALIZED);

//insert row to iterator

dcIteratorBinding.getRowSetIterator().insertRow(rw);

//make new row the current

dcIteratorBinding.setCurrentRowWithKey(

rw.getKey().toStringFormat(true));

Page 23: Errores Mas Comunes Oracle Adf

23

Adding new Rows

• Better

– if you have access to a table, tree or treeTable component

– Does not require knowledge about the binding layer, thus generic

private void createRowInTable(RichTable table){

CollectionModel model = (CollectionModel ) table.getValue();

JUCtrlHierBinding _binding = (JUCtrlHierBinding) model.getWrappedData();

DCIteratorBinding dcIteratorBinding= _binding.getDCIteratorBinding();

Row rw = dcIteratorBinding.getRowSetIterator().createRow();

rw.setNewRowState(Row.STATUS_INITIALIZED);

//insert row to iterator

dcIteratorBinding.getRowSetIterator().insertRow(rw);

//make new row the current

Key k = rw.getKey();

dcIteratorBinding.setCurrentRowWithKey(k.toStringFormat(true));

}

Page 24: Errores Mas Comunes Oracle Adf

24

ADF Controller Mistakes

Page 25: Errores Mas Comunes Oracle Adf

25

Task Flow Parameters

I used the expression editor to reference my Task Flow parameter… But it’s always NULL?

<input-parameter-definition>

<name>arg</name>

<value>

#{pageFlowScope.myArg}

</value>

<class>

java.lang.String

</class>

<required/>

</input-parameter-definition>

Example

Page 26: Errores Mas Comunes Oracle Adf

26

Task Flow Parameters

• Don’t be fooled by the expression editor!

– In this circumstance it can’t quite be trusted.

• By setting the <value> attribute of

the param-def you have re-mapped

the data from the implied variable

• Probably a good idea to explicitly

define a target bean in the

task flow definition

Page 27: Errores Mas Comunes Oracle Adf

27

PageFlow scope has Stale Data

PageFlow scope returns old data. Is there a way to refresh the page flow scope ?

private Map<String, Object> scopeVar =

AdfFacesContext.getCurrentInstance().getPageFlowScope();

public void buttonAction() {

//the data read below is "old" !!!

Object param1Value = scopeVar.get("param1");

...

}

Example

Page 28: Errores Mas Comunes Oracle Adf

28

PageFlow scope has Stale Data

• Never store a scope map in a member variable of

your bean

• It does not improve performance and you might be looking at stale data

public void buttonAction(ActionEvent ae) {

AdfFacesContext facesCtx = null;

facesCtx = AdfFacesContext.getCurrentInstance()

Map<String, Object> scopeVar = facesCtx.getPageFlowScope();

Object param1Value = scopeVar.get("param1");

... }

Better

Page 29: Errores Mas Comunes Oracle Adf

29

PageFlow scope has Stale Data

• This also applies for other scopes

ADFContext.getCurrent().getApplicationScope();

ADFContext.getCurrent().getSessionScope();

AdfFacesContext.getCurrentInstance().getPageFlowScope();

ADFContext.getCurrent().getRequestScope();

ADFContext.getCurrent().getViewScope();

How-to access memory scope data in ADF

Page 30: Errores Mas Comunes Oracle Adf

30

"We should forget about small efficiencies, say about

97% of the time: premature optimization is the root of

all evil"

- Donald Knuth

Page 31: Errores Mas Comunes Oracle Adf

31

Extending AdfcExceptionHandler

I extended the ADFc exception handler, creating oracle.adf. view.rich.context.ExceptionHandlerconfiguration file in .adf/META-DATA/services

public class MyExceptionHandler extends AdfcExceptionHandler{

public void handleException(FacesContext facesContext,

Throwable throwable,

PhaseId pahseId){

String error = throwable.getMessage();

...

super.handleException(...);

}

}

Example(s)

Page 32: Errores Mas Comunes Oracle Adf

32

Extending AdfcExceptionHandler

• Ouch ! Hold on ....

• ADFc exception handling usually is sufficient and you

don't need to customize the exception handler

– Not all exceptions are accessible for the ADFc controller

• If you need to extend the default exception handler

– Don't use AdfcExceptionHandler

– Internal class that you should not use

– Even Product Managers got this wrong

• Extend ExceptionHandler and re-throw exceptions

you don't know how to handle

• See next slide how to do it right ...

Page 33: Errores Mas Comunes Oracle Adf

33

Extending AdfcExceptionHandler…

import oracle.adf.view.rich.context.ExceptionHandler;

public class CustomExceptionHandler extends ExceptionHandler {

public CustomExceptionHandler() {

super();

}

public void handleException(FacesContext facesContext,

Throwable throwable, PhaseId phaseId)

throws Throwable

{

String error_message;

error_message = throwable.getMessage();

if (error_message != null &&

error_message.indexOf("ADF_FACES-30108") > -1)

{

ExternalContext ectx = facesContext.getExternalContext();

ectx.redirect("faces/SessionExpired.jspx");

}

else

{

throw throwable;

}

}

}

Page 34: Errores Mas Comunes Oracle Adf

34

Extending AdfcExceptionHandler

• Configuration

– Create oracle.adf.view.rich.context.Exceptionhandler

text file and store it in .adf\META-INF\services

– you need to create the “services” folder

– Add the absolute name of your custom exception handler

• Java class that extends ExceptionHandler

• Configuration is framework wide

– Not to be deployed with ADF Library

Page 35: Errores Mas Comunes Oracle Adf

35

queueActionEventInRegion

If it bends, bend it! I found a cool way to execute ADF bindings contained in an ADF Region – Feeling lucky today.

richRegion.queueActionEventInRegion(

"#{bindings.Delete.execute}",

null,

null,

false,

0,

0,

PhaseId.INVOKE_APPLICATION);

}

Example(s)

Page 36: Errores Mas Comunes Oracle Adf

36

queueActionEventInRegion

public void queueActionEventInRegion(

javax.el.MethodExpression actionExpression,

javax.el.MethodExpression launchListenerMethodExpression,

javax.el.MethodExpression returnListenerMethodExpression,

java.lang.Boolean useWindow,

java.lang.Integer windowWidth,

java.lang.Integer windowHeight,

javax.faces.event.PhaseId phaseId

)

See here ...

Page 37: Errores Mas Comunes Oracle Adf

37

“I don't care about what anything was

DESIGNED to do, I care about what it

CAN do.”

Gene Kranz, Apollo 13 (Movie, 1995)

Page 38: Errores Mas Comunes Oracle Adf

38

queueAction

• Queues an ActionEvent so that it behaves as if you

queued it on a command component inside of the

region

– Used to navigate region from outside

– Navigation cases are discoverable

• Though executes any method, it is not what this is

designed for

– Available actions are not discoverable

– Result of method invocation may not display

– Works against TaskFlow encapsulation

Page 39: Errores Mas Comunes Oracle Adf

39

Product Demonstration

queueActionEventInRegion

Page 40: Errores Mas Comunes Oracle Adf

40

Redirect to Current Page

My page needs to redirect to current page. Using JSF ExternalContext redirect() works but seems to loose ADF controller state

FacesContext fctx = FacesContext.getCurrentInstance():

ExternalContext ectx = fctx.getExternalContext();

UIViewRoot root = fctx.getViewRoot();

String viewId = root.getViewId();

ectx.redirect("/faces/"+viewId);

Example

Page 41: Errores Mas Comunes Oracle Adf

41

Redirect to Current Page

• JSF doesn't know about ADF Controller and ADF Region states

• Use ControllerContext to create redirect URL

private void redirectToSelf(){

FacesContext fctx = FacesContext.getCurrentInstance();

ExternalContext ectx = fctx.getExternalContext();

String viewId = fctx.getViewRoot().getViewId();

ControllerContext controllerCtx = null;

controllerCtx = ControllerContext.getInstance();

String activityURL = controllerCtx.getGlobalViewActivityURL(viewId);

try{

ectx.redirect(activityURL);

} catch (IOException e) {

//Can't redirect

e.printStackTrace();

}

}

Page 42: Errores Mas Comunes Oracle Adf

42

Navigation in Bounded Task Flow

JSF NavigationHandler.handleNavigation() is not recommended for use to navigate in bounded task flows though it appears to work. Why ? And what should I use instead ?

FacesContext fctx = FacesContext.getCurrentInstance();

NavigationHandler nh =

fctx.getApplication().getNavigationHandler();

nh.handleNavigation(fctx, null, "doEmployeesFiltered");

Example

Navigation case

Page 43: Errores Mas Comunes Oracle Adf

43

Navigation in Bounded Task Flow

• Let's do the "why" first

– Directly invocation of methods on the NavigationHandler

doesn't conform with JSF specification

• Bypasses JSF lifecycle

– invoke application phase is missed out

– Pending changes are not submitted

– E.g, using ADF, no MDS commit would happen

• It's a bad thing to do even if you don't notice incorrect

behavior

– The specification assumes that the framework will invoke the

NavigationHandler in response to an ActionEvent

Page 44: Errores Mas Comunes Oracle Adf

44

Navigation in Bounded Task Flow

• I have a several options for you

– 1. Use setViewId() on the controller context

• Navigates to viewId in bounded task flow

• Does not navigate to routers and method call activities

– 2. queue an action event on a command component

– 3. Use queueActionEventOnRegion

ControllerContext ccontext = ControllerContext.getInstance();

//set the viewId to display

String viewId = "EmployeesView";

ccontext.getCurrentViewPort().setViewId(viewId);

Example

Page 45: Errores Mas Comunes Oracle Adf

45

Navigation in Bounded Task Flow

• A several options for you

– 1. Use setViewId() on the controller context

– 2. queue an action event on a command component

• Component can be hidden

– 3. Use queueActionEventOnRegion

private void onQueueC3ButtontAction() {

FacesContext fctx = FacesContext.getCurrentInstance();

UIViewRoot root = fctx.getViewRoot();

RichCommandButton button =

(RichCommandButton) root.findComponent("r1:cb3");

ActionEvent actionEvent = new ActionEvent(button);

actionEvent.queue();

}

Page 46: Errores Mas Comunes Oracle Adf

46

Navigation in Bounded Task Flow

• A couple of options for you

– 1. Use setViewId() on the controller context

– 2. queue an action event on a command component

– 3. Use queueActionEventOnRegion

• Queues an action by its navigation case

Private void navUsingQueueAction(ActionEvent actionEvent) {

UIComponent comp = actionEvent.getComponent();

while(!(comp instanceof RichRegion)){

comp = comp.getParent();

}

((RichRegion) comp).queueActionEventInRegion(

createMethodExpressionFromString("doEmployees"),

null, null, false, 0, 0,PhaseId.INVOKE_APPLICATION);

}

Page 47: Errores Mas Comunes Oracle Adf

47

Navigation in Bounded Task Flow

• Helper Method

private MethodExpression createMethodExpressionFromString(String s){

FacesContext fctx = FacesContext.getCurrentInstance();

ELContext elctx = fctx.getELContext();

ExpressionFactory exprFactory =

fctx.getApplication().getExpressionFactory();

MethodExpression methodExpr = exprFactory.createMethodExpression(

elctx,

s,

null,

new Class[]{});

return methodExpr;

}

Page 48: Errores Mas Comunes Oracle Adf

48

Product Demonstration

Navigation in bounded Task Flow

Page 49: Errores Mas Comunes Oracle Adf

49

Expression Language

Mistakes

Page 50: Errores Mas Comunes Oracle Adf

50

Accessing Managed Beans #{requestScope.<…>}

I prefix all my managed bean EL references with the scope the bean is in, for example, #{requestScope. BeanName.propertyName}

<af:outputText value="#{requestScope.BeanName.LastName}"/>

Example(s)

Page 51: Errores Mas Comunes Oracle Adf

51

Accessing Managed Beans #{requestScope.<…>}

• Doesn’t always work for beans in default Servlet

scopes

– requestScope, sessionScope, applicationScope

– Bypasses JavaServer Faces managed bean facility

• Only looks for in-memory objects

• Does not instantiate managed beans

– Only good idea if looking up memory attributes you know

exist or you want to create

• Works for ADF specific scopes

– viewScope, pageFlowScope, backingBeanScope

– ADFc controller takes care of managed bean instantiation if

configuration is available

Page 52: Errores Mas Comunes Oracle Adf

52

JavaServer Faces

Mistakes

Page 53: Errores Mas Comunes Oracle Adf

53

I have a command button that when pressed should update a text field. Just its not working … Arrrgs

<af:inputtext value="#{mybacking.firstName}" .../>

<af:commandButton

action="#{mybacking.updateFirstNameVal}" immediate="true"

.../>

Example(s)

JSF Lifecycle - immediate="true"

Page 54: Errores Mas Comunes Oracle Adf

54

JSF Lifecycle - immediate="true"

• Understand the JSF Request Lifecycle

• JSF Phases

• Immediate means "execute first" not "execute only"

– Command button is special case

– Use "immediate" on button to bypass model update

Render Response

Restore View

Apply Request Values

Process Validation

Update Model Values

Invoke Application

Page 55: Errores Mas Comunes Oracle Adf

55

ADF Lifecycle "extends" JSF Lifecycle

Render Response

Restore View

Apply Request Values

Process Validation

Update Model Values

Invoke Application

ChangedView?

JSF Restore View

Init Context

Prepare Model

JSF Apply Request Values

JSF Process Validation

JSF Update Model Values

Validate Model Updates

JSF Invoke Applications

Meta Data Commit

yes

no

New

Context

Init Context

Prepare Model

Prepare Render

Prepare Render

For Same View

Render Response

For Same View

ADF Lifecycle PhasesJSF Lifecycle Phases

Page 56: Errores Mas Comunes Oracle Adf

56

Product Demonstration

Immediate = true

Page 57: Errores Mas Comunes Oracle Adf

57

One to Print on a T-Shirt

Immediate = true ≠ PartialSubmit = true

PartialSubmit = true ≠ Immediate = true

Page 58: Errores Mas Comunes Oracle Adf

58

ADF Faces Component

Mistakes

Page 59: Errores Mas Comunes Oracle Adf

59

Mixing JSF and HTML

HTML helps me to create the layout I want. Sometimes however it seems to break ADF Faces. Is this a bug ?

<af:form>

<table>

<tr valign="top">

<td><af:inputText ... label="search" /></td>

<td><af:commandButton ... text="go" /></td>

</tr>

</table>

...

</af:form>

Example(s)

Page 60: Errores Mas Comunes Oracle Adf

60

Mixing JSF and HTML

• HTML only theoretically works in JSF– JSF 1.2 synchronizes lifecycle so that HTML "waits" for JSF

– Not all components accept HTML as a child component

– HTML binds to data using JSTL, which can only supports deferred expressions ${ ... }

• ADF Faces RC layout component handle geometry management, which may conflict with HTML

• ADF Faces components canbe accessed and manipulated from managed beans

• HTML elements don't participate in PPR

• Recommendation: Don't mix and match !

Page 61: Errores Mas Comunes Oracle Adf

61

Examples

Page 62: Errores Mas Comunes Oracle Adf

62

Inline Style CSS

Some components seem to ignore CSS. Others apply it wrong

<af:inputText label="PhoneNumber" id="it2"

inlineStyle="background-color:Red; color:Green;"/>

Example(s)

????

Page 63: Errores Mas Comunes Oracle Adf

63

Inline Style CSS

<tbody>

<tr id="j_id_id16"

<td>

<label for="j_id_id16::content">

PhoneNumber

</label>

</td>

<td>

<input id="j_id_id16::content"

type="text" value="650.507.9833"/>

</td></tr>

</tbody>

=

• ADF Faces Components are far more complex than simple HTML

elements

• Styles are applied to the root DOM element, not the component itself

• ContentStyle styles the inner area of a component

• Solution: Skinning

Page 64: Errores Mas Comunes Oracle Adf

64

Nesting Tables – Failed Use Case I

I want nested ADF Faces tables. This does not seem to work.

Example(s)

Page 65: Errores Mas Comunes Oracle Adf

65

Nesting Tables – Failed Use Case I

• Sample already optimized as much as possible

– Its as good as it gets

– Used tree binding for m/d to work (!)

– Auto row sizing to trim table layout

– Still, not a good idea

– Messes with ADF Faces geometry management

No layout boundaries

Page 66: Errores Mas Comunes Oracle Adf

66

Not everything that compiles can be shipped!

Page 67: Errores Mas Comunes Oracle Adf

67

af:forEach, af:iterator

• af:forEach and af:Iterator tags are often confused

• af:Iterator

– Behaves like a table without chrome

– Stamps children

– Can be used with JSF DataModel and Trinidad

CollectionModel

– Child items can access EL variables defined on a parent

• e.g. "row" in a table

Page 68: Errores Mas Comunes Oracle Adf

68

af:forEach, af:iterator

• af:forEach

– Replaces JSTL c:forEach, which does not support varStatus

– Only iterates java.util.Lists

• Does not support java.util.Collection

– Use to generate components

• For example: <f:selectItem …>

• Components are remembered by their index

– items created by <af:forEach> should not be added, removed or re-

ordered once the component tree has been created

– Use cases

• Components should be created conditionally based item in the loop.

• Different JSP includes, page templates, and dynamic declarative

components should be included per loop iteration

Page 69: Errores Mas Comunes Oracle Adf

69

Nesting Tables – Failed Use Case II

Need help! I am trying to build a nested table. Doesn't work in ADF Faces. Must be a bug. Screw you Oracle !

<af:table …

value="#{bindings.allDepartments.collectionModel}">

...

<af:column>

<af:table ...

Value="#{bindings.dependentEmployees.collectionModel">

...

</af:table>

</af:column>

</af:table>

Example(s)

Page 70: Errores Mas Comunes Oracle Adf

70

Nesting Tables

• Tables are rendered on the server

– Valid children is af:column

• Valid children are any output component and layout

element

– Tables are stamped, which means that a row is not a new

instance of a component

• No single table row refresh

• No query issued to fetch m/d dependent data per row

– If nested layouts are needed, use af:forEach or afIterator

Page 71: Errores Mas Comunes Oracle Adf

71

af:iterator in table columns

My table rows have nested information I want to show to users. How do I do this then ?

Page 72: Errores Mas Comunes Oracle Adf

72

af:iterator in table columns

• Create a detail node binding

• Use #{row.children} in af:iterator

Var="row"

Page 73: Errores Mas Comunes Oracle Adf

73

Opening popup dialogs

I want to open a popup from a command link in a table using af:showPopupBehavior. The popup does not show and instead the page is refreshed

<af:commandButton text="commandButton 1" id="cb1">

<af:showPopupBehavior popupId="popup1"

triggerType="action"

align="afterEnd"

alignId="it1"/>

</af:commandButton>

<af:popup id="popup1" ...>

...

</af:popup>

Example(s)

Page 74: Errores Mas Comunes Oracle Adf

74

Opening popup dialogs

• Popups must be opened using a partial submit

• Its a lighweight dialog that is part of the page HTML

output

– Repainting the page closes the popup

Page 75: Errores Mas Comunes Oracle Adf

75

File Upload in ADF Region

• Same code works in JSPX page

• I see no exception

File uploads don't work in ADF Regions. I am scratching my head in disbelief

Page 76: Errores Mas Comunes Oracle Adf

76

File Upload in ADF Region

• ADF Region uses page fragments

• Page fragments don't have an af:form tag on their

own

• af:form tag is in parent page, or if parent page is

fragment too, in the parent's parent page

• Make sure af:form tag has usesUpload="true" set

Page 77: Errores Mas Comunes Oracle Adf

77

JavaScript Mistakes

Page 78: Errores Mas Comunes Oracle Adf

78

Using the Browser DOM

I am a JavaScript expert and "DOM" is my corporate nickname.: DOM, James DOM

function cancelEventAndUpdateWithDom(evt){

evt.cancel();

var txtfield1 = document.getElementById("it1::content");

txtfield1.value = "Hello OOW 2010"

}

Example(s)

Page 79: Errores Mas Comunes Oracle Adf

79

Using the Browser DOM

• Accessing the browser DOM operates on HTML markup

– Markup is generated by component renderers

– HTML output may change without notice as it is an implementation

detail of the JSF component renderer

– HTML markup does not

• provide same set of component properties

• Allow PPR

• Better

– If you need to use JavaScript, use the ADF Faces client framework

function cancelEventAndUpdateWithAdfFaces(evt){

evt.cancel();

var txtfield1 = AdfPage.PAGE.findComponentByAbsoluteId('it1');

txtfield1.setValue("Hello OOW 2010");

}

Page 80: Errores Mas Comunes Oracle Adf

80

Using the Browser DOM

Tried what you said – just doesn't work. Back to direct DOM manipulation ?

var txtfield1 = AdfPage.PAGE.findComponentByAbsoluteId('it1');

Example(s)

Always returns null

<af:inputText id="it1" value="#{SampleBean.txt1}"/>

<af:commandButton text="Update" id="cb1" partialSubmit="true">

<af:clientListener method="cancelEventAndUpdateWithAdfFaces"

type="action"/>

</af:commandButton>

Page 81: Errores Mas Comunes Oracle Adf

81

Using the Browser DOM

• ADF Faces is performance optimized

– Most of the components rendered byserver side generated HTML

markup

– JavaScript objects are created for components with rich functionality

– Developers can enforce JavaScript object to be rendered

• Setting component property clientComponent = "true" or ...

• ... apply clientListener

<af:inputText id="it1" value="#{SampleBean.txt1}"

clientComponent="true"/>

<af:commandButton text="Update" id="cb1" partialSubmit="true">

<af:clientListener method="cancelEventAndUpdateWithAdfFaces"

type="action"/>

</af:commandButton>

Page 82: Errores Mas Comunes Oracle Adf

82

Page 83: Errores Mas Comunes Oracle Adf

83

Related Oracle Press Books

• Quick Start Guide to Oracle Fusion Development

• Oracle JDeveloper 11g Handbook

• Oracle Fusion Developer Guide