Sei sulla pagina 1di 83

1

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.

2
<Insert Picture Here>

Classic Mistakes with Oracle Application Development Framework


Internal APIs
Duncan Mills, Frank Nimphius
Oracle Application Development Tools
Product Management
Oracle Fusion Middleware

4
To err is human and every developer has the
right to make mistakes.
Don't abuse this privilege !

5
ADF Framework
Mistakes

6
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

7
Binding Classes – The Java in ADF

FacesCtrl* Bindings

8
FacesCtrlHierBinding

FacesCtrlHierBinding binding expose the convenient


methods I need. My expert tip: Always use these
classes

Example(s)
<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 --- //
}

9
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

10
Replacing FacesCtrlHierBinding

How-to use JUCtrlHierBinding to make the selected


table row the current row in the ADF Binding

Example(s)

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


}

11
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

12
ADF Bindings Mistakes

13
#{data.} Expression Root

I can use the #{data…} root in my EL to pull


information from another Binding Container!

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

public static ApplicationModule


getApplicationModuleForDataControl(String name){

return(ApplicationModule)JSFUtils.resolveExpression(
"#{data." + name + ".dataProvider}");
}

14
#{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()

15
Accessing the "bindings" object using EL

I access the ADF binding layer from EL in Java, using


#{bindings} . Objections ?

Example(s)

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

16
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();

17
Using page fragments

Adding a page fragment to my ADF page does not


render the ADF bound data content

Example(s)
<af:document id="d1">
...
<f:subview id="sv1">
<jsp:include page="/allDepartments.jsff"/>
</f:subview>
...
</af:document>

18
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

19
Adding new Rows

ADF bound table does not show new rows created in


View Object

Example(s)

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

20
Don't fight the framework !

21
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));

22
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));
}

23
ADF Controller Mistakes

24
Task Flow Parameters

I used the expression editor to reference my Task


Flow parameter… But it’s always NULL?

Example
<input-parameter-definition>
<name>arg</name>
<value>
#{pageFlowScope.myArg}
</value>
<class>
java.lang.String
</class>
<required/>
</input-parameter-definition>

25
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

26
PageFlow scope has Stale Data

PageFlow scope returns old data. Is there a way to


refresh the page flow scope ?

Example

private Map<String, Object> scopeVar =


AdfFacesContext.getCurrentInstance().getPageFlowScope();
public void buttonAction() {
//the data read below is "old" !!!
Object param1Value = scopeVar.get("param1");
...
}

27
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
Better

public void buttonAction(ActionEvent ae) {


AdfFacesContext facesCtx = null;
facesCtx = AdfFacesContext.getCurrentInstance()
Map<String, Object> scopeVar = facesCtx.getPageFlowScope();
Object param1Value = scopeVar.get("param1");

... }

28
PageFlow scope has Stale Data

• This also applies for other scopes

How-to access memory scope data in ADF

ADFContext.getCurrent().getApplicationScope();
ADFContext.getCurrent().getSessionScope();
AdfFacesContext.getCurrentInstance().getPageFlowScope();
ADFContext.getCurrent().getRequestScope();
ADFContext.getCurrent().getViewScope();

29
"We should forget about small efficiencies, say about
97% of the time: premature optimization is the root of
all evil"
- Donald Knuth

30
Extending AdfcExceptionHandler

I extended the ADFc exception handler, creating


oracle.adf. view.rich.context.ExceptionHandler
configuration file in .adf/META-DATA/services

Example(s)
public class MyExceptionHandler extends AdfcExceptionHandler{
public void handleException(FacesContext facesContext,
Throwable throwable,
PhaseId pahseId){
String error = throwable.getMessage();
...
super.handleException(...);
}
}

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

32
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;
     }
   }
}

33
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

34
queueActionEventInRegion

If it bends, bend it! I found a cool way to execute ADF


bindings contained in an ADF Region – Feeling lucky
today.

Example(s)
richRegion.queueActionEventInRegion(
"#{bindings.Delete.execute}",
null,
null,
false,
0,
0,
PhaseId.INVOKE_APPLICATION);
}

35
queueActionEventInRegion

See here ...

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
)

36
“I don't care about what anything was
DESIGNED to do, I care about what it CAN do.”
Gene Kranz, Apollo 13 (Movie, 1995)

37
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

38
Product Demonstration
queueActionEventInRegion

39
Redirect to Current Page

My page needs to redirect to current page. Using JSF


ExternalContext redirect() works but seems to loose
ADF controller state

Example

FacesContext fctx = FacesContext.getCurrentInstance():


ExternalContext ectx = fctx.getExternalContext();
UIViewRoot root = fctx.getViewRoot();
String viewId = root.getViewId();
ectx.redirect("/faces/"+viewId);

40
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();
}
}

41
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 ?

Example

FacesContext fctx = FacesContext.getCurrentInstance();


NavigationHandler nh =
fctx.getApplication().getNavigationHandler();
nh.handleNavigation(fctx, null, "doEmployeesFiltered");

Navigation case

42
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

43
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

Example
ControllerContext ccontext = ControllerContext.getInstance();
//set the viewId to display
String viewId = "EmployeesView";
ccontext.getCurrentViewPort().setViewId(viewId);

44
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();
}

45
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);

46
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;
}

47
Product Demonstration
Navigation in bounded Task Flow

48
Expression Language
Mistakes

49
Accessing Managed Beans #{requestScope.<…>}

I prefix all my managed bean EL references with the


scope the bean is in, for example, #{requestScope.
BeanName.propertyName}

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

50
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

51
JavaServer Faces
Mistakes

52
JSF Lifecycle - immediate="true"

I have a command button that when pressed should


update a text field. Just its not working … Arrrgs

Example(s)
<af:inputtext value="#{mybacking.firstName}" .../>

<af:commandButton
action="#{mybacking.updateFirstNameVal}" immediate="true"
.../>

53
JSF Lifecycle - immediate="true"

• Understand the JSF Request Lifecycle


• JSF Phases
Restore View

Apply Request Values

Process Validation

Update Model Values

Invoke Application

Render Response

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


– Command button is special case
– Use "immediate" on button to bypass model update

54
ADF Lifecycle "extends" JSF Lifecycle
JSF Lifecycle Phases ADF Lifecycle Phases

Restore View JSF Restore View For Same View

Init Context New Init Context


Context
Prepare Model Prepare Model

Apply Request Values JSF Apply Request Values


Prepare Render

Process Validation JSF Process Validation

Update Model Values For Same View


JSF Update Model Values
Render Response
Validate Model Updates

Invoke Application JSF Invoke Applications


Prepare Render

Meta Data Commit

Changed yes
View?

no

Render Response

55
Product Demonstration
Immediate = true

56
One to Print on a T-Shirt

Immediate = true ≠ PartialSubmit = true

PartialSubmit = true ≠ Immediate = true

57
ADF Faces Component
Mistakes

58
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 ?

Example(s)
<af:form>
<table>
<tr valign="top">
<td><af:inputText ... label="search" /></td>
<td><af:commandButton ... text="go" /></td>
</tr>
</table>
...
</af:form>

59
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 !

60
Examples

61
Inline Style CSS

Some components seem to ignore CSS. Others apply


it wrong

Example(s)

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


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

????

62
Inline Style CSS

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

63
Nesting Tables – Failed Use Case I

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


work.

Example(s)

64
Nesting Tables – Failed Use Case I

No layout boundaries

• 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

65
Not everything that compiles can be shipped!

66
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

67
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

68
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 !

Example(s)
<af:table …
value="#{bindings.allDepartments.collectionModel}">
...
<af:column>
<af:table ...
Value="#{bindings.dependentEmployees.collectionModel">
...
</af:table>
</af:column>
</af:table>

69
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

70
af:iterator in table columns

My table rows have nested information I want to show


to users. How do I do this then ?

71
af:iterator in table columns

• Create a detail node binding


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

Var="row"

72
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

Example(s)
<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>

73
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

74
File Upload in ADF Region

File uploads don't work in ADF Regions. I am


scratching my head in disbelief

• Same code works in JSPX page


• I see no exception

75
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

76
JavaScript Mistakes

77
Using the Browser DOM

I am a JavaScript expert and "DOM" is my corporate


nickname.: DOM, James DOM

Example(s)

function cancelEventAndUpdateWithDom(evt){
evt.cancel();
var txtfield1 = document.getElementById("it1::content");
txtfield1.value = "Hello OOW 2010"
}

78
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");
}

79
Using the Browser DOM

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


DOM manipulation ?

Example(s)

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

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>

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

81
82
Related Oracle Press Books

• Quick Start Guide to Oracle Fusion Development


• Oracle JDeveloper 11g Handbook
• Oracle Fusion Developer Guide

83

Potrebbero piacerti anche