deep dive into oracle adf
TRANSCRIPT
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
About me
2
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
The Briefing
3
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 4
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Use Case (Dive Site)
5
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Use Case (Dive Site)
6
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Dynamic BC Model Structure
En0ty Defini0on
View Object Defini0on
View Object Instance
ABributes UI Hints
Valida0on rules
ABributes LOV’s
View Accessors
Lookup View Defini0on
UI Categories
View Criterias
7
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com 8
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Giant Stride Entry
9
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Giant Stride Entry
10
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Generate VO’s name Ø Try to find the VO Ø Create View Definition Ø Create VO instance for the View Definition public ViewObject createDynamicVO(String agileEn0tyName) { //Generate VO name for the given en0ty name just by adding VAGILE_ prefix //The name for "DIVERS" agile en0ty is generated as "VAGILE_DIVERS”. JboNameU0l class can be used String agileVOName = getAgileVOName(agileEn0tyName); ViewObject agileVO = findViewObject(agileVOName); if (agileVO == null) { ViewDefImpl agileViewDef = new VAgileDefImpl(agileVOName, getAgileEn0tyDefini0on(agileEn0tyName)); agileVO = createViewObjectForDef(agileVOName, agileViewDef); } return agileVO; }
Dynamic View Object
11
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Extend VAgile view definition Ø Set row implementation class Ø Create entity definition Ø Resolve and register definition object public class VAgileDefImpl extends ViewDefImpl { public VAgileDefImpl(String name, VAgileEn0tyDefini0onRowImpl agileEn0tyDefini0on) { super(DEF_SCOPE_SESSION, name, "com.cs.blog.deepdiveadf.agiledatamodel.views.VAgile"); setRowClass(VAgileRowImpl.class); String en0tyName = generateAgileEn0tyName(name); //VAGILE_DIVERS -‐> VAGILE_DIVERS_ENTITY En0tyDefImpl en0tyDefImpl = new En0tyAgileDefImpl(en0tyName, agileEn0tyDefini0on); addEn0tyUsage("En0ty", en0tyDefImpl.getName(), false, false); addAllEn0tyABributes("En0ty"); //Two magic calls resolveDefObject(); registerDefObject(); }
Dynamic View DefiniOon
12
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Set implementation class of entity instances Ø Add agile attributes Ø Resolve and register the definition object public class En0tyAgileDefImpl extends En0tyDefImpl { public En0tyAgileDefImpl(String en0tyName, VAgileEn0tyDefini0onRowImpl agileEn0tyDefini0on) { super(en0tyName); setRowClass(En0tyAgileImpl.class); RowIterator agileABributes = agileEn0tyDefini0on.getAgileABributes(); while (agileABributes.hasNext()) { addAgileABribute((VAgileABributesRowImpl) agileABributes.next()); } //Two magic calls resolveDefObject(); registerDefObject(); }
Dynamic EnOty DefiniOon
13
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
private void addAgileABribute(VAgileParamDefini0onRowImpl agileABr) { ABributeDefImpl at = addABribute(/*aBrName*/ agileABr.getName(), /*columnName*/ agileABr.getName(), /*javaType*/ agileABr.getJavaType(), /*isPrimaryKey*/ agileABr.isPK(), /*isDiscriminator*/ false, /*isPersistent*/ ! agileABr.isTransient()); at.setMandatory(agileABr.isMandatory()); at.setDefaultValue(agileABr.getDefaultvalueliteral()); at.setTransientExpression(agileABr.getDefaultvalueexpression()); if (agileABr.isReadonly()) at.setUpdateableFlag(ABributeDef.READONLY); if (agileABr.getDependencies()!=null) at.setBackwardDependencies(Arrays.asList(agileABr.getDependencies().split(" "))); at.setProperty(ABributeHints.ATTRIBUTE_LABEL, agileABr.getLabel()); at.setProperty(ABributeHints.ATTRIBUTE_TOOLTIP, agileABr.getDescrip0on()); at.setProperty(ABributeHints.ATTRIBUTE_AUTOSUBMIT, agileABr.isAutoSubmit()); if (agileABr.getMaxlength()!=null) at.addValidator(AgileValidatorFactory.getLengthValidator(agileABr.getMaxlength())); … }
Agile APribute
14
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø There is a set of pre-defined validators Ø JboLengthValidator, JboCompareValidator, JboExpressionValidator, …
Ø Extend JboAbstractValidator Ø Invoke a constructor and specify the error message
public sta0c JboLengthValidator getLengthValidator(int maxLength) { JboLengthValidator jlv = new JboLengthValidator(/*inverse*/ false, /*operType*/ JboLengthValidator.LESSTHANEQUALTO, /*dataType*/ JboLengthValidator.CHARACTER, /*value*/ maxLength); //maxlength_err=Value must not be longer than {0} characters jlv.setErrorMsgId(MAX_LENGTH_ERROR); HashMap errvaluesMap = new HashMap(); errvaluesMap.put("0", Integer.toString(maxLength)); jlv.setErrorMsgExpressions(errvaluesMap); return jlv; }
Length Validator Example
15
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create Resource Bundle Definition Ø Implement ResourceBundleDef interface Ø Link entity definition to the resource bundle <ResourceBundle> <Proper0esBundle Proper0esFile="com.cs.blog.En0tyAgileBundle"/> </ResourceBundle> public class En0tyAgileDefImpl extends En0tyDefImpl { private sta0c String RESOURCE_BUNDLE_FILE="com.cs.blog.En0tyAgileBundle"; private void linkToResourceBundle() { Proper0esBundleDef rb = new Proper0esBundleDef(this); rb.setProper0esFile(RESOURCE_BUNDLE_FILE); setResourceBundleDef(rb); }
Link to the Resource Bundle
16
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
ü Custom View Definition for an entity-based VO is created and registered ü Custom Entity Definition is created and registered
ü Contains all necessary attributes ü UI hints are set up ü Validators are created ü Resource Bundle is linked
ü View Object instance is created
ü Only standard ADF BC API is used
Check Point
17
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Dynamic table Ø Dynamic binding approach
Ø EL expression in Binds attribute Ø #{pageFlowScope.vo} != #{pageFlowScope.vo.name}
<executables> <iterator Binds="#{pageFlowScope.vo.name}" DataControl="AgileDataModelServiceDataControl“ RangeSize="25" id="VAgileIterator"/> </executables> <dynamic:table value="#{bindings.VAgileIterator}" id="t1"/>
Give It a Try!
18
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
19
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
ProgrammaOcally Populated View Object
ResultSet
20
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
ProgrammaOcally Populated View Object
21
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public VAgileImpl q Constructor
protected void executeQueryForCollection q Retrieve and store a pointer to data from alternative data source
protected boolean hasNextForCollection
q Whether there is any data to fetch out protected ViewRowImpl createRowFromResultSet
q Actually create and populate new VO’s row public long getQueryHitCount
q Return an estimated count of the rows
protected void releaseUserDataForCollection q Release and close resources
ProgrammaOcally Populated View Object
22
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
ProgrammaOcally Populated View Object
23
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) { resultSet = (ResultSet)getUserDataForCollec0on(qc); ViewRowImpl r = null; if (resultSet != null) { r = createNewRowForCollec0on(qc); boolean theSameEn0tyRow = true; try { Object keyValue = resultSet.getObject("PKVALUE"); while (theSameEn0tyRow) { int aBrIndex = getABributeIndexOf(resultSet.getString("ATTRNAME")); ABributeDef at = getABributeDef(aBrIndex); populateABributeForRow(r, aBrIndex, resultSet.getObject("ATTRVALUE")); theSameEn0tyRow = resultSet.next() && keyValue.equals(resultSet.getObject("PKVALUE")); } } catch (SQLExcep0on s) { throw new JboExcep0on(s); } } else setFetchCompleteForCollec0on(qc, true); return r; }
ProgrammaOcally Populated View Object
24
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
25
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Dynamic List of Values
select Id, Name from Language
26
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create and register lookup View Definition Ø Create and add View Accessor Ø Create and add List Binding Definition Ø Set the LOV for the attribute
Dynamic List of Values
27
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create and register lookup View Definition Ø Create and add View Accessor Ø Create and add List Binding Definition Ø Set the LOV for the attribute
ViewDefImpl vaViewDef = new ViewDefImpl(); vaViewDef.setQuery(lookupSql); vaViewDef.setFullSql(true) String lookupViewDefName = generateName(viewName, aBr.getName()); vaViewDef.setName(lookupViewDefName); vaViewDef.setFullName(lookupViewDefName); vaViewDef.addViewABribute(lookupValueABrName, lookupValueABrName, Object.class); vaViewDef.addViewABribute(lookupDisplayABrName, lookupDisplayABrName, Object.class); ((ABributeDefImpl) vaViewDef.getABributeDef(0)).setPrimaryKey(true); vaViewDef.resolveDefObject(); vaViewDef.registerDefObject();
Dynamic List of Values
28
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create and register lookup View Definition Ø Create and add View Accessor Ø Create and add List Binding Definition Ø Set the LOV for the attribute ViewAccessorDef vaccessdef = new ViewAccessorDef(); vaccessdef.setName(lookupViewDefName); vaccessdef.setViewDefFullName(lookupViewDefName); addViewAccessorDef(vaccessdef);
Dynamic List of Values
29
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create and register lookup View Definition Ø Create and add View Accessor Ø Create and add List Binding Definition Ø Set the LOV for the attribute ListBindingDef lov = new ListBindingDef(getDefManager(), Defini0onObject.DEF_SCOPE_SESSION); String LOVName = generateLOVName(aBr.getName()); lov.setName(LOVName); lov.setListVOName(viewAccessorDefName); lov.setABrNames(new String[] {aBr.getName()}); lov.setListABrNames(new String[] {lookupValueABrName}); lov.setListDisplayABrNames(new String[] {lookupValueABrName, lookupDisplayABrName}); addListBindingDef(lov); ((ABributeDefImpl) aBr).setLOVName(LOVName); ((ABributeDefImpl) aBr).setProperty(ABributeHints.ATTRIBUTE_CTL_TYPE, ABributeHints.CTLTYPE_COMBOLOV);
Dynamic List of Values
30
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
31
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public class En0tyAgileImpl extends En0tyImpl protected void doDML(int opera0on, Transac0onEvent e) { switch (opera0on) { case DML_INSERT: { executeDMLprocedure(getInsertProcedureName()); break; } case DML_UPDATE: { executeDMLprocedure(getUpdateProcedureName()); break; } case DML_DELETE: { executeDMLprocedure(getDeleteProcedureName()); break; } } }
Create, Update and Delete
32
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Get IStoredProc instance Ø Set input parameters values Ø Execute PL/SQL procedure Ø Populate attributes from output parameters
private void executeDMLprocedure(String procedureName) { IStoredProc storedProc = getStoredProc(procedureName); for (IStoredProcParam param : storedProc.getParams()) { if (param.isIn()) param.setParamValue(getABribute(param.getParamName())); } storedProc.execute(); for (IStoredProcParam param : storedProc.getParams()) { if (param.isOut()) populateABribute(getEn0tyDef().getABributeIndexOf(param.getParamName()), param.getParamValue()); } }
Create, Update and Delete
33
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø findByPrimaryKey is invoked on activation of modified entity public En0tyImpl findByPrimaryKey(DBTransac0on txn, Key key) { En0tyImpl en0ty = super.findByPrimaryKey(txn, key); if (en0ty == null) { en0ty = createBlankInstance(txn); ABributeDef[] keyABrs =getPrimaryKeys(); //Populate key aBributes for (int i = keyABrs.length -‐ 1; i >= 0; i-‐-‐) { ((En0tyAgileImpl) en0ty).populateABribute(keyABrs[i].getIndex(), key.getKeyValues()[i]); } ((En0tyAgileImpl) en0ty).doSelect(); ((En0tyAgileCollImpl) en0ty.getEn0tyCache()).add(en0ty); } return en0ty; }
PassivaOon / AcOvaOon Issue
34
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:table rows="#{bindings.VAgile.rangeSize}" fetchSize="#{bindings.VAgile.rangeSize}" emptyText="#{bindings.VAgile.viewable ? 'No data to display.' : 'Access Denied.'}" var="row" rowBandingInterval="0” value="#{bindings.VAgile.collec0onModel}" selectedRowKeys="#{bindings.VAgile.collec0onModel.selectedRow}" selec0onListener="#{bindings.VAgile.collec0onModel.makeCurrent}" rowSelec0on="single" id="t1"> <af:forEach items="#{bindings.VAgile.aBributeDefs}” var="def"> <af:column headerText="#{bindings.VAgile.labels[def.name]}“ sortable="true" sortProperty="#{def.name}“ id="c2"> <af:outputText value="#{row[def.name]}" id="ot2"/> </af:column> </af:forEach> </af:table>
Dynamic Table
35
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<executables> <iterator Binds="#{pageFlowScope.vo.name}" DataControl="AgileDataModelServiceDataControl“ id="VAgileIterator"/> </executables> <bindings> <tree IterBinding="VAgileIterator" id="VAgile"> <nodeDefini0on Name="VAgile0"/> </tree> </bindings>
Dynamic Table
<af:table rows="#{bindings.VAgile.rangeSize}" fetchSize="#{bindings.VAgile.rangeSize}” …
36
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<dynamic:form value="#{bindings.VAgileIterator}" id="f1"/>
Dynamic Form
37
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:iterator id="i1" value="#{bindings.VAgile.aBributesModel.aBributes}" var="aBr"> <af:dynamicComponent id="d2" aBributeModel="#{aBr}" value="#{bindings[aBr.containerName][aBr.name].inputValue}"/> </af:iterator> <tree IterBinding="VAgileIterator" id="VAgile"> <nodeDefini0on Name="VAgile0"/> </tree>
Dynamic Component (12c)
38
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø DynamicComponent has limitations Ø af:Iterator + af:switcher approach can be used <af:iterator value=”#{bindings.VAgile.aBributesModel.aBributes}" var="aBr" id="dc_i1"> <af:switcher id="dc_s1" defaultFacet="Default" facetName=”#{bindings[aBr.containerName][aBr.name].agileTypeID}”> <f:facet name="DATE"> <af:inputDate id="dc_id1" label=”#{bindings[aBr.containerName][aBr.name].label}” value=”#{bindings[aBr.containerName][aBr.name].inputValue}” shortDesc="#{bindings[aBr.containerName][aBr.name].tool0p}” /> </f:facet> <f:facet name=”INT”> …
Hand made Dynamic Form
<tree IterBinding="VAgileIterator" id="VAgile"> <nodeDefini0on Name="VAgile0"/> </tree>
39
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
40
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<dynamic:form value="#{bindings.VAgileIterator}" id="f1“ category="General"/>
UI Categories
41
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public class VAgileDefImpl extends ViewDefImpl private void createUICategories(RowIterator uiCategories) { if (uiCategories.hasNext()) { CategoryManager cm = ensureCategoryManager();
while (uiCategories.hasNext()) { VAgileEn0tyGroupRowImpl r = (VAgileEn0tyGroupRowImpl)uiCategories.next();
DefaultVOCategoryImpl defaultCategory = new DefaultVOCategoryImpl(r.getName()); defaultCategory.setProperty(GenericHints.PROPERTY_LABEL, r.getLabel());
defaultCategory.setCategoryManager(cm); cm.addCategory(defaultCategory); } } }
UI Categories
42
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
private void addAgileABribute(VAgileParamDefini0onRowImpl agileParam) { ABributeDefImpl at = addABribute(/*aBrName*/ agileParam.getName(), /*columnName*/ agileParam.getName(), /*javaType*/ agileParam.getJavaType(), /*isPrimaryKey*/ agileParam.isPK(), /*isDiscriminator*/ false, /*isPersistent*/ !agileParam.isTransient()); … if (agileParam.getAgilegroupname()!=null) at.setProperty(ABributeHints.ATTRIBUTE_CTL_CATEGORY, agileParam.getAgilegroupname()); … }
UI Categories
43
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:iterator id="i2" value="#{bindings.VAgile.aBributesModel.hierarchicalABributes}” var="aBr"> <af:switcher id="sw1" facetName="#{aBr.descriptorType}" defaultFacet="ATTRIBUTE"> <f:facet name="GROUP"> <af:group 0tle="#{aBr.label}" id="g1"> … </f:facet> <f:facet name="ATTRIBUTE"> <af:dynamicComponent id="ad1" aBributeModel="#{aBr}" value="#{bindings[aBr.containerName][aBr.name].inputValue}"/> </f:facet> </af:switcher> </af:iterator>
UI Categories (12c)
44
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:naviga0onPane id="catPane" rendered="#{not empty viewScope.EditViewBean.tabMenuModel}" value="#{viewScope.EditViewBean.tabMenuModel}" var="tab"> <f:facet name="nodeStamp"> <af:commandNaviga0onItem id="catPaneID" ac0onListener="#{viewScope.EditViewBean.tabAc0vatedEvent}" textAndAccessKey="#{tab.propertyMap['LABEL']}"> <f:aBribute name="tabId" value="#{tab.name}"/> </af:commandNaviga0onItem> </f:facet> </af:naviga0onPane>
UI Categories
45
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public MenuModel getTabMenuModel() { List pageList = getAgileVO().getCategoriesList(); if (pageList!=null && pageList.size()>1) return new ChildPropertyMenuModel(pageList, null, CollecOons.singletonList(pageList.indexOf(getSelectedPage()))); else return null; }
UI Categories
46
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<dynamic:form value="#{bindings.VAgileIterator}" id="f1" binding="#{viewScope.EditViewBean.dynform}" category="#{viewScope.EditViewBean.selectedCategoryName}"/> <dynamic:form value="#{bindings.VAgileIterator}" id="f1" binding="#{viewScope.EditViewBean.dynform}" forceRefresh="#{viewScope.EditViewBean.formNeedRefresh}"/> public Boolean getFormNeedRefresh() { if (ObjectU0ls.equal(dynform.getCategory(), getSelectedCategoryName())) return false; else { this.dynform.setCategory(getSelectedCategoryName()); return true; } }
UI Categories
47
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<af:train id="t2" value="#{viewScope.InsertViewBean.trainMenuModel}" var="node" rendered="#{not empty viewScope.InsertViewBean.trainMenuModel}"> <f:facet name="nodeStamp"> <af:commandNaviga0onItem textAndAccessKey="#{node.propertyMap['LABEL']}" immediate="#{viewScope.InsertViewBean.trainMenuModel.immediate}" disabled="#{viewScope.InsertViewBean.trainMenuModel.readOnly}" visited="#{viewScope.InsertViewBean.trainMenuModel.visited}" id="cni" ac0onListener="#{viewScope.InsertViewBean.trainAc0on}"> <f:aBribute name="stopName" value="#{node.name}"/> </af:commandNaviga0onItem> </f:facet> </af:train>
Dynamic Train
48
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public ProcessMenuModel getTrainMenuModel() { ProcessMenuModel processMenuModel == null; List pageList = getAgileVO().getCategoriesList(); if (pageList!=null && pageList.size()>1) { ChildPropertyTreeModel childPropertyTreeModel = new ChildPropertyTreeModel(pageList, null); processMenuModel = new CategoryTrainMenuModel(childPropertyTreeModel, NAME); processMenuModel.setCurrentStop(getCurrentStopName()); } return processMenuModel; }
Dynamic Train
49
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
public class CategoryTrainMenuModel extends ProcessMenuModel{ private String currentStop; @Override protected String getCurrentViewId() { return currentStop; } public CategoryTrainMenuModel(Object instance, String viewIdProperty) { super(instance, viewIdProperty); } public void setCurrentStop(String currentStop) { this.currentStop = currentStop; } public String getCurrentStop() { return currentStop; } }
Dynamic Train
50
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
51
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
@Override public String getCriteriaItemClause(ViewCriteriaItem crieriaItem) { return (String) crieriaItem.getValue(); }
Dynamic View Criteria
View Object
View Criteria
View Criteria Row
View Criteria Item
ABribute Opera0on Operand
1
1
1
*
*
* setValue()
52
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Create View Criteria and set name Ø Create View Criteria Row Ø Create View Criteria Item for the first aBribute Ø Set where clause as value Ø Set CRITERIA_MODE_CACHE to ensure memory filtering Ø Add View Criteria to View Defini0on ViewCriteriaImpl viewCriteria = (ViewCriteriaImpl) createViewCriteria(); viewCriteria.setName(userFilter.getName()); ViewCriteriaRow vcr = viewCriteria.createViewCriteriaRow(); String firstABributeName = getABributeDef(0).getName(); ViewCriteriaItem vci = new ViewCriteriaItem(firstABributeName, vcr); vci.setValue(userFilter.getWhereclause()); vcr.addCriteriaItem(firstABributeName, vci); viewCriteria.add(vcr); viewCriteria.setCriteriaMode(ViewCriteria.CRITERIA_MODE_CACHE); putViewCriteria(viewCriteria.getName(), viewCriteria);
Dynamic View Criteria
53
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
<BC4JDataControl id="AgileDataModelServiceDataControl" Package="com.cs.blog.deepdiveadf.agiledatamodel" FactoryClass="com.cs.blog.deepdiveadf.agiledatamodel.datacontrol.AgileDataControlFactory” … public class AgileDataControlFactory extends DataControlFactoryImpl { @Override protected String getDataControlClassName() { return AgileDataControl.class.getName(); } } public class AgileDataControl extends JUApplica0on { @Override protected void applySortCriteria(DCIteratorBinding iter, SortCriteria[] sortBy) { if (sortBy != null) { ViewObject vo = iter.getViewObject(); JboEnvUOl.applyVOSortCriteria(vo, sortBy, true /*Transient*/) ; } }
Memory SorOng
54
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Ø Set VO property PROP_ALWAYS_USE_SORT to true Ø Sor0ng is always performed in memory
public class VAgileImpl extends ViewObjectImpl … @Override protected void create() { super.create() setProperty(PROP_ALWAYS_USE_SORT, "true"); } …
Memory SorOng (11.1.1.7.0 & 12c)
55
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Live Demo
56
Eugene Fedorenko adfprac0ce-‐fedor.blogspot.com
Safety Stop. QuesOons & Answers
57