Upload
euegene-fedorenko
View
1.155
Download
0
Embed Size (px)
Citation preview
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 2
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 3
Sailing Route
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 4
public class VBoatImpl extends ViewObjectImpl implements VBoat { public void setupOfficeName(String officeName) { En0tyDefImpl boatEn0tyDef = getEn0tyDef(BOAT); AQributeDefImpl ad = (AQributeDefImpl) boatEn0tyDef.findAQributeDef("RegisterOffice"); ad.setDefaultValue(officeName); }
5
Default AQribute Value. Bad Idea
Ø Setup office name as default attribute value Ø Invoke the VO method on task flow entry
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:inputText value="#{bindings.Length.inputValue}" visible="#{bindings.Length.hints.viewableOnInsert}" label="#{bindings.Length.hints.label}" …
6
Custom AQribute Proper0es
Ø Define a custom entity attribute property Ø Use the property in the JSF visible attribute as UI hint
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public void setBoatclass(String value) { setAQributeInternal(BOATCLASS, value); setupViewableOnInsert(value); } private void setupViewableOnInsert(String boatClass) { for (int aQr : SIZE_ATTRIBUTES) { AQributeDefImpl aQrDef = (AQributeDefImpl) getDefini0onObject().getAQributeDef(aQr); aQrDef.setProperty(VIEWABLE_ON_INSERT, !SMALL.equals(boatClass)); } }
7
Custom AQribute Proper0es. Bad Idea
Ø Update custom property value in the Boat Class setter
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 8
En0ty Defini0on Reef
public void setupOfficeName(String officeName) { Applica0onModule am = getApplica0onModule(); am.getSession().getUserData().put("officeName", officeName); }
9
Default AQribute Value. Good Idea
Ø Keep office name in a user session data map Ø Use a Groovy expression in the Default Value
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
@Override protected Object getHistoryContextForAQribute(AQributeDefImpl aQr) { if (aQr.getHistoryKind() == AQributeDefImpl.HISTORY_CREATE_USER) { return getDBTransac0on().getSession().getUserData().get("officeName"); } else { return super.getHistoryContextForAQribute(aQr); } }
10
Tracking Change History
Ø Mark the attribute as ”Created By” history column Ø Override getHistoryContextForAttribute in the EntityImpl
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
protected En0tyAQrHintsImpl createEn0tyAQrHints(AQributeDefImpl aQrDef) { return new CustomEn0tyAQrHintsImpl(aQrDef, this); } public class CustomEn0tyAQrHintsImpl extends En0tyAQrHintsImpl { @Override public String getHint(LocaleContext locale, String sHintName) { if (VIEWABLE_ON_INSERT.equals(sHintName)) { String boatClass = ((BoatImpl) getEn0tyImpl()).getBoatclass(); return Boolean.toString(!SMALL.equals(boatClass)); } return super.getHint(locale, sHintName); }
11
Custom AQribute Proper0es. Good Idea
Ø Create a custom Entity Attribute Hints implementation class Ø Override createEntityAttrHints in the EntityImpl
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
@Override public void resolveDefObject() { super.resolveDefObject(); setupViewableOnInsert(); } private void setupViewableOnInsert() { for (String aQr : SIZE_ATTRIBUTES) { AQributeDefImpl aQrDef = (AQributeDefImpl) findAQributeDef(aQr); aQrDef.setPropertyExpression(VIEWABLE_ON_INSERT, "Boatclass != '1'"); } }
12
Custom AQribute Proper0es. Groovy Expressions
Ø Create a custom Entity Definition class Ø Override resolveDefObject method Ø Setup a Groovy expression with setPropertyExpression method
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 13
LOV Archipelago
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 14
VO based View Accessor vs En0ty based View Accessor
15
LOVs in a Search Form
Ø Define a separate LOV for a search form Ø Add a LOV-switcher attribute Ø Use adf.isCriteriaRow expression to switch the LOVs JBO-‐35111: LOV in a search form cannot use a view accessor defined on an En0ty. Change LOV_En0ty_BoaQype to use a view accessor defined in the view object
(adf.isCriteriaRow) ? "LOV_VO_BoaQype" : "LOV_En0ty_BoaQype”
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
16
LOVs in a Search Form
SELECT * FROM BOAT Boat WHERE Boat.BoatClass = :boatClass public String getBoatClass() { return someCalculatedBoatClass; }
if (adf.isCriteriaRow) return dataProvider.viewCriteria.viewObject.boatClass; else return viewObject.boatClass;
JBO-‐25077: Name boatClass not found in the given object: oracle.adf.model.bean.DCDataVO.
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 17
Shared VO Instance
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 18
Session Shared AM vs Applica0on Shared AM
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 19
Row Level Binds
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 20
Master/Detail Pirates
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 21
Master/Detail Pirates
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public class VBoatImpl extends ViewObjectImpl { protected void create() { super.create(); addListener(new DetailRowSetsListener()); } public class DetailRowSetsListener implements RowSetListener { @Override public void navigated(Naviga0onEvent event) { ViewObject vo = (ViewObject) event.getSource(); for (RowSet detail : vo.getDetailRowSets()) { detail.closeRowSet(); } }
22
Master/Detail Pirates
Ø Use separate VO instances for different use-cases Ø Add RowSetListener to the master VO instance Ø Reproduced only when AM pooling is enabled
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 23
Ac0va0on/Passiva0on Vortex
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 24
Ac0va0on/Passiva0on Vortex
25
Ac0va0on/Passiva0on Vortex
Ø Retain View Link Accessor Rowset Ø Passivated transient VO attributes Ø Dynamic VO attributes
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 26
Ac0va0on/Passiva0on Vortex
27
Ac0va0on/Passiva0on Vortex
Ø Retain View Link Accessor Rowset Ø Passivated transient VO attributes Ø Dynamic VO attributes
Ø Close VO row set when it is not needed anymore
public void flowFinalizer() { BindingContext bc = BindingContext.getCurrent(); Applica0onModule am = bc.findDataControl("SampleModelServiceDataControl").getApplica0onModule(); ViewObject vo = am.findViewObject("VBoat"); vo.closeRowSet(); }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
28
Enabling AM Pooling Programma0cally
Ø Create custom ApplicationPool implementation class Ø Specify PoolClassName in the AM Configuration Ø Override isAMPoolingEnabled method
public class CustomApplica0onPoolImpl extends Applica0onPoolImpl { @Override public boolean isAMPoolingEnabled() { return getYourOwnAMPoolingEnabled(); } …
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 29
Associa0on Consistency Piyall
30
Separate View Objects for Different Use-‐Cases
Ø Different sets of attributes Ø Different View Links, View Accessors, LOVs, View Crierias, etc. Ø Different attributes UI hints Ø Different SQL execution tuning options
VSailorBrowse VSailorInsert
Sailor
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
31
Associa0on (View Link) Consistency
Ø View Objects are based on the same entity Ø Only one primary entity usage Ø All secondary entity usages are references
VSailorBrowse VSailorInsert
Sailor
Entity Cache
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
32
Associa0on Consistency Piyall
Ø New row should fit with memory filter Ø rowQualifies() Ø RowMatch
Ø Disabled when Where Clause is applied at runtime Ø Use setAssociationConsistent(true) to enable
protected void executeQueryForCollec0on(Object qc, Object[] params, int noUserParams) { super.executeQueryForCollec0on(qc, params, noUserParams); setAssocia0onConsistent(true); }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 33
View Criteria Rocks
34
Controlling VC items UI hints
Ø Declarative approach for basic UI hints Ø Label, Tool0p, Display Width, Format, etc.
Ø Override getCriteriaItemAttributeHints in ViewObjectImpl class
@Override public AQributeHints getCriteriaItemAQributeHints(ViewCriteriaItem vci) { if (vci.getAQributeDef().getName().equals("Boat")) { if (getPredefinedBoat() != null) { vci.setProperty(ViewCriteriaItem.RENDERED_MODE, ViewCriteriaItem.CRITERIA_RENDERED_MODE_NEVER); } else { vci.setProperty(ViewCriteriaItem.RENDERED_MODE, ViewCriteriaItem.CRITERIA_RENDERED_MODE_BOTH); } } return super.getCriteriaItemAQributeHints(vci); }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 35
Managed Bean Scope Gorgon
36
UI Component Binding Challenge
Ø UI components are not serializable Ø High Availability mode Ø ADF Controller save points
Ø Transient variable is not an option Ø UI component tree should not be hard referenced <af:table value="#{bindings.VBoat.collec0onModel}" var="row" binding="#{BrowseBean.table}" private RichTable table; public RichTable getTable() { return table; } public void setTable(RichTable table) { this.table = table; }
Request or Backing Bean
Scope!
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
37
UI Component Binding Example
binding="#{BrowseBean.table}" headerText="#{BrowseBean.searchTitle}" public class BrowseBoats { private RichTable table; public String getSearchTitle() { return "Search boats"; }
binding="#{BrowseBean.table}” headerText="#{BrowseBean.searchTitle}" public class BrowseSailors { private RichTable table; public String getSearchTitle() { return "Search sailors"; }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
38
Request Scope Managed Beans
Ø One instance of the bean within request
public class BrowseSailors { private RichTable table; public String getSearchTitle() { return "Search sailors"; }
public class BrowseBoats { private RichTable table; public String getSearchTitle() { return "Search boats"; }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
39
Backing Bean Scope Managed Beans
Ø One instance of the bean per region within request
public class BrowseSailors { private RichTable table; public String getSearchTitle() { return "Search sailors"; }
public class BrowseBoats { private RichTable table; public String getSearchTitle() { return "Search boats"; }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
40
Backing Bean Scope Managed Beans
Ø One instance of the bean per region within request
public class BrowseBoats { private RichTable table; public String getSearchTitle() { return "Search boats"; }
public class BrowseSailors { private RichTable table; public String getSearchTitle() { return "Search sailors"; }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
41
View Scope Managed Beans
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
42
UI Component Reference
Ø Use ComponentReference to hold the UI component reference Ø Serializable Ø Avoids hard references to UI components
Ø Good enough for any memory scope
public class BrowseSailors { private ComponentReference tableReference; public void setTable(RichTable table) { tableReference = ComponentReference.newUIComponentReference(table); } public RichTable getTable() { return (tableReference == null ? null : (RichTable) tableReference.getComponent()); }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 43
Excep0on Handling Stone
44
Controller Excep0on Handler
Ø Mark a task flow activity as an Exception Handler Ø Handle exceptions related to the task flow navigation
Ø Method Call, Router, Task Flow Call, Ini0alizer, Finalizer, etc. Ø Not a View Ac0vity
public void excep0onHandler() { ControllerContext context = ControllerContext.getInstance(); ViewPortContext currentRootViewPort = context.getCurrentViewPort(); if (currentRootViewPort.isExcep0onPresent()) { Excep0on ex = currentRootViewPort.getExcep0onData(); FacesContext fc = FacesContext.getCurrentInstance(); FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), null); fc.addMessage(null, facesMessage); fc.renderResponse(); } }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
45
Nested Task Flow Call Sailors Task Flow
Create Sailor Task Flow
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
46
Must Have Excep0on Handler
Ø Pop the task flow from the stack if there is no Exception Handler Ø Repeat until Exception Handler is located
Task Flow 0
Task Flow 1
No Exception Handler Task Flow 2
No Exception Handler Task Flow 3
Task Flow S
tack
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 47
UI Mermaids
48
Immediate aQribute
Ø Validation and ValueChangeEvent at Apply Request Values phase Ø The Lifecycle does not stop Ø The rest of phases are not skipped
<af:inputText value="#{bindings.Lengthh.inputValue}" visible="#{bindings.Lengthh.hints.viewableOnInsert}" par0alTriggers="socBoatClass" <af:selectOneChoice value="#{bindings.Boatclass.inputValue}" autoSubmit="true" immediate="true" id="socBoatClass” public void valueChangeListenerBoatClass(ValueChangeEvent valueChangeEvent) { UIComponent c = valueChangeEvent.getComponent(); c.processUpdates(FacesContext.getCurrentInstance()); FacesContext.getCurrentInstance().renderResponse(); }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
49
Programma0cally Refreshing Components
Ø Dependent components don’t participate in the request Ø Add components as partial targets to the AdfFacesContext
<af:inputText value="#{bindings.Lengthh.inputValue}" id="itLength" visible="#{bindings.Lengthh.hints.viewableOnInsert}" <af:outputText value="(meters)" id="otLength" visible="#{bindings.Lengthh.hints.viewableOnInsert}” public void valueChangeListenerBoatClass(ValueChangeEvent valueChangeEvent) { UIComponent c = JsfU0ls.findComponentInRoot("itLength"); AdfFacesContext.getCurrentInstance().addPar0alTarget(c); c = JsfU0ls.findComponentInRoot("otLength"); AdfFacesContext.getCurrentInstance().addPar0alTarget(c); … }
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
50
ClientComponent aQribute
<af:outputText value="(meters)" id="otLength” HTML: <span id="pt1:dyntdc:reg:1:pt1:otLength”> clientComponent=”true" (meters) </span> document.getElementById("otLength") = HTMLSpanElement AdfPage.PAGE.findComponent("otLength") = AdfRichOutputText <af:outputText value="(meters)" id="otLength” HTML: <span id="pt1:dyntdc:reg:1:pt1:otLength”> par0alTriggers="socBoatClass" (meters) </span> document.getElementById("otLength") = HTMLSpanElement AdfPage.PAGE.findComponent("otLength") = undefined <af:outputText value="(meters)" id="otLength” HTML: (meters) document.getElementById("otLength") = undefined AdfPage.PAGE.findComponent("otLength") = undefined <no PPR-‐capable ID found for elements of: RichOutputText[UIXFacesBeanImpl, id=otLength]> Eugene Fedorenko
adfprac0ce-‐fedor.blogspot.com
51
SelectBooleanCheckBox example
<af:switcher facetName="#{SessionInfo.regaQaUpdatable ? 'regaQaUpdatable' : 'regaQaReadOnly'}"> <f:facet name="regaQaUpdatable"> <af:selectBooleanCheckbox value="#{bindings.InregaQa.inputValue}" disabled="#{empty bindings.Manufdate.inputValue}" par0alTriggers="idManufDate" …/> … </f:facet> <f:facet name="regaQaReadOnly"> <af:outputText value="#{bindings.InRegaQaName.inputValue}" …/> … </f:facet> </af:switcher>
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
52
SelectBooleanCheckBox piyall
Ø Invisible partially triggered components participate in the request Ø getSubmittedValue() never returns null for selection components
if (component.isRendered() && component.getSubmiQedValue() != null) { processComponent(component); } else { skipComponent(component); } <af:switcher facetName="#{SessionInfo.regaQaUpdatable ? 'regaQaUpdatable' : 'regaQaReadOnly'}"> <f:facet name="regaQaUpdatable"> <af:selectBooleanCheckbox value="#{bindings.InregaQa.inputValue}" disabled="#{empty bindings.Manufdate.inputValue}" par0alTriggers="idManufDate" …/> …
rendered="#{SessionInfo.regaQaUpdatable}"
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
53
Automa0c par0al page rendering (Auto-‐ppr)
<iterator Binds="VBoat" RangeSize="25" DataControl="SampleModelServiceDataControl" id="VBoatIterator" ChangeEventPolicy="ppr" />
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
54
Target Tag (JDeveloper 12c)
Ø Useful to skip validation while PPR execution Ø Available in ADF 12c
<af:selectOneChoice value="#{bindings.Boatclass.inputValue}" …> <af:target execute="@this" render="it1 it2 it3"/> </af:selectOneChoice> <af:inputText value="#{bindings.Lengthh.inputValue}” visible="#{bindings.Lengthh.hints.viewableOnInsert}" id=”it1” required=”true” <af:inputText value="#{bindings.Width.inputValue}” visible="#{bindings.Width.hints.viewableOnInsert}” id=”it2” required=”true” <af:inputText value="#{bindings.Capacity.inputValue}” visible="#{bindings.Capacity.hints.viewableOnInsert}” id=”it3” required=”true”
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
55
ValidateDateTimeRange validator
<af:inputDate value="#{bindings.RegaQastartdate.inputValue}" …/> <af:inputDate value="#{bindings.RegaQafinishdate.inputValue}" …/> <af:inputDate value="#{bindings.Firstracedate.inputValue}" …> <af:validateDateTimeRange minimum="#{bindings.RegaQastartdate.inputValue.value}" maximum="#{bindings.RegaQafinishdate.inputValue.value}"/> </af:inputDate>
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
56
ValidateDateTimeRange piyall
Ø Maximum = 5/30/2014 23:59:59.999
<af:validateDateTimeRange minimum="#{bindings.RegaQastartdate.inputValue.value}" maximum="#{bindings.LimitRegaQaFinishDate.inputValue.value}"/>
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 57
Ques0ons & Answers