Professional Documents
Culture Documents
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 Oracles products remains at the sole discretion of Oracle.
To err is human and every developer has the right to make mistakes. Don't abuse this privilege !
ADF Faces, Trinidad and ADF Controller have an API package and an IMPL package
Define logical framework abstractions Simplifies implementation of future product changes
FacesCtrl* Bindings
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(); _binding.getTreeModel();
FacesCtrlHierBinding.FacesModel treeModel = (FacesCtrlHierBinding.FacesModel) treeModel.makeCurrent(selectionEvent); // --- perform optional post-processing here --- // }
FacesCtrlHierBinding
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
12
13
Example(s)
<af:outputText value="#{data.demo_v1PageDef.LastName}"/>
14
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
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
Yes your honor objection ! You can use Java instead of EL (things have moved on)
BindingContext bindingContext = BindingContext.getCurrent(); BindingContainer bindings = bindingContext.getCurrentBindingsEntry();
17
Example(s)
<af:document id="d1"> ... <f:subview id="sv1"> <jsp:include page="/allDepartments.jsff"/> </f:subview> ... </af:document>
18
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
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
21
22
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
24
Example
<input-parameter-definition> <name>arg</name> <value> #{pageFlowScope.myArg} </value> <class> java.lang.String </class> <required/> </input-parameter-definition>
25
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
Example
private Map<String, Object> scopeVar = AdfFacesContext.getCurrentInstance().getPageFlowScope(); public void buttonAction() { //the data read below is "old" !!! Object param1Value = scopeVar.get("param1"); ... }
27
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
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
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
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
38
Product Demonstration
queueActionEventInRegion
39
Example
FacesContext fctx = FacesContext.getCurrentInstance(): ExternalContext ectx = fctx.getExternalContext(); UIViewRoot root = fctx.getViewRoot(); String viewId = root.getViewId(); ectx.redirect("/faces/"+viewId);
40
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 case
42
43
44
45
46
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
49
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
51
52
Example(s)
<af:inputtext value="#{mybacking.firstName}" .../> <af:commandButton action="#{mybacking.updateFirstNameVal}" immediate="true" .../>
53
54
JSF Apply Request Values JSF Process Validation JSF Update Model Values Validate Model Updates
Invoke Application
Prepare Render
Changed View?
yes
no
Render Response
55
Product Demonstration
Immediate = true
56
57
58
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
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
Example(s)
<af:inputText label="PhoneNumber" id="it2" inlineStyle="background-color:Red; color:Green;"/>
????
62
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
64
No layout boundaries
65
66
af:forEach, af:iterator
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 reordered 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
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
70
71
72
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
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
75
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
Example(s)
function cancelEventAndUpdateWithDom(evt){ evt.cancel(); var txtfield1 = document.getElementById("it1::content"); txtfield1.value = "Hello OOW 2010" }
78
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
Example(s)
var txtfield1 = AdfPage.PAGE.findComponentByAbsoluteId('it1');
80
81
82
Quick Start Guide to Oracle Fusion Development Oracle JDeveloper 11g Handbook Oracle Fusion Developer Guide
83