Con5623 pdf 5623_001
- 2. About
me
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
2
- 3. The
Briefing
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
3
- 5. Use
Case
(Dive
Site)
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
5
- 6. Use
Case
(Dive
Site)
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
6
- 7. Dynamic
BC
Model
Structure
En0ty
Defini0on
ABributes
UI
Hints
Valida0on
rules
View
Object
Defini0on
ABributes
LOV’s
UI
Catego0es
View
Accessors
View
Criterias
Lookup
View
Defini0on
View
Object
Instance
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
7
- 11. Dynamic
View
Object
Ø 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;
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
11
- 12. Dynamic
View
DefiniOon
Ø 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();
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
12
- 13. Dynamic
EnOty
DefiniOon
Ø 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();
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
13
- 14. Agile
APribute
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()));
…
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
14
- 15. Length
Validator
Example
Ø 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;
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
15
- 16. Link
to
the
Resource
Bundle
Ø 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);
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
16
- 17. Check
Point
ü 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
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
17
- 18. Give
It
a
Try!
Ø 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"/>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
18
- 19. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
19
- 22. ProgrammaOcally
Populated
View
Object
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
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
22
- 24. ProgrammaOcally
Populated
View
Object
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;
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
24
- 25. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
25
- 26. Dynamic
List
of
Values
select
Id,
Name
from
Language
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
26
- 27. Dynamic
List
of
Values
Ø Create and register lookup View Definition
Ø Create and add View Accessor
Ø Create and add List Binding Definition
Ø Set the LOV for the attribute
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
27
- 28. Dynamic
List
of
Values
Ø 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();
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
28
- 29. Dynamic
List
of
Values
Ø 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);
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
29
- 30. Dynamic
List
of
Values
Ø 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);
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
30
- 31. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
31
- 32. Create,
Update
and
Delete
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;
}
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
32
- 33. Create,
Update
and
Delete
Ø 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());
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
33
- 34. PassivaOon
/
AcOvaOon
Issue
Ø Passivation/Activation of dynamic VOs is a bit different
Ø Need to set internal VO’s property manually
agileVo.setProperty(
ViewObjectImpl.INTERNAL_UI_PASSIVATE_DEF_FULL_NAME,
Boolean.TRUE
);
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
34
- 35. Read
Only
Dynamic
Table
<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>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
35
- 36. Read
Only
Dynamic
Table
<executables>
<iterator
Binds="#{pageFlowScope.vo.name}"
DataControl="AgileDataModelServiceDataControl“
RangeSize="25"
id="VAgileIterator"/>
</executables>
<bindings>
<tree
IterBinding="VAgileIterator"
id="VAgile">
<nodeDefini0on
Name="VAgile0"/>
</tree>
</bindings>
<af:table
rows="#{bindings.VAgile.rangeSize}"
fetchSize="#{bindings.VAgile.rangeSize}”
…
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
36
- 37. Dynamic
Form
<dynamic:form value="#{bindings.VAgileIterator}" id="f1"/>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
37
- 38. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
38
- 39. UI
Categories
<dynamic:form value="#{bindings.VAgileIterator}" id="f1“
category="General"/>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
39
- 40. UI
Categories
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);
}
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
40
- 41. UI
Categories
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());
…
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
41
- 42. UI
Categories
<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>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
42
- 43. UI
Categories
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;
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
43
- 44. UI
Categories
<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;
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
44
- 45. Dynamic
Train
<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>
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
45
- 46. Dynamic
Train
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;
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
46
- 47. Dynamic
Train
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;
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
47
- 48. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
48
- 49. Dynamic
View
Criteria
View
Object
1
*
View
Criteria
1
*
View
Criteria
Row
1
*
setValue()
View
Criteria
Item
ABribute
Opera0on
Operand
@Override
public
String
getCriteriaItemClause(ViewCriteriaItem
crieriaItem)
{
return
(String)
crieriaItem.getValue();
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
49
- 50. Dynamic
View
Criteria
Ø 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);
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
50
- 51. Memory
SorOng
<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*/)
;
}
}
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
51
- 52. Live
Demo
Eugene
Fedorenko
adfprac0ce-‐fedor.blogspot.com
52