Hi ,
Use Case :Need to show latest records into af:table with use of oracle coherence.
Class Description :
The following class which i used to achieve my requirement .
1-TableActiveCollectionModelDecorator
This class used for providing the model data for af:table
Extends ActiveCollectionModelDecorator
2-TableActiveModelClass
This class extends BaseActiveDataModel
3-CoherenceClass
This class use to put the data into oracle coherence
4-Interface TableInterface for listen Map listener
The class and interface relationship is depicted in following picture
UI description :
Here i used af:table as UI component to show the latest data.
I have been working on a project where i need to show the latest data on UI .For this we are using following technology.
1-Active data service
2-And oracle coherence
Since this bit tricky and tough to understand so for this i have divided my post under following parts
Step 1-In first part will explain active data service configuration into the application.
Step 2-In second part will explain oracle coherence for maintaining data in memory cache.
Step 3-In third part will explain communication between between oracle coherence and Active data Service.
Step 4-Registration of the bean into adfc-config.xml
Step5-Doing following operation into oracle coherence cache.
1-Adding new record into cache
2-update records into cache
3-delete records into cahce
So let me explain each individual point in details
Step 1-In first part will explain active data service configuration into the application.
1-You require to configure Active Data Service in the adf-config.xml.In adf-config.xml file need to register communication transport details and need to create new property file name as adf-config.properties file .
i)ADD following code in adf-config.xml
ii)First create services folder under .adf/META-INF directory and then create property file name adf-config.properties add following code in adf-config.properties file
*Be careful all the above line should be in one single line.
2-Since here i am using af:table component for Active data service so first class which we do require to extends is ActiveCollectionModelDecorator.
Here i am using ActiveCollectionModelDecorator class however you can also use ActiveDataModel class .
Code is following
Here following method are override
1-public ActiveDataModel getActiveDataModel() {}
2- public CollectionModel getCollectionModel(){}
3-Second class which is require to extends BaseActiveDataModel class moreover this class is also very important class.Code is following
Although here i am not doing any thing in the startActiveData and stopActiveData but it is used to seed and remove the resource.
Above are steps to implements Active data service and following are for oracle coherence
Step 2-In second part will explain oracle coherence for maintaining data in memory cache.
1-First need to add the coherence.jar jar file into application path. coherence.jar is already available in jdeveloper installation folder
Location is following
oracle installation folder name\oracle_common\modules\oracle.coherence
2-Created class name as CoherenceClass where i have done initialization for Name Cache as following in static block
static {
nameCache = CacheFactory.getCache(CACHE_NAME);
}
3-In constructor of CoherenceClass load the data form method and add in the oracle coherence as following
public CoherenceClass() {
CacheFactory.ensureCluster();
NamedCache nc = CacheFactory.getCache(CoherenceClass.CACHE_NAME);
nc.addMapListener(this);
if (nc.size() == 0) {
nc.putAll(loadDataFromCoherence());
}
}
private static Map loadDataFromCoherence() {
//This are my friends name
Map loadDataMap = new HashMap();
loadDataMap.put("C0", new TableData(0L, "Prateek"));
loadDataMap.put("C1", new TableData(1L, "Abhishek"));
loadDataMap.put("C2", new TableData(2L, "Satyendra"));
loadDataMap.put("C3", new TableData(3L, "Ramesh"));
loadDataMap.put("C4", new TableData(4L, "Anoop"));
loadDataMap.put("C5", new TableData(5L, "Jamal"));
loadDataMap.put("C6", new TableData(6L, "Laljeet"));
loadDataMap.put("C7", new TableData(7L, "Hariom"));
loadDataMap.put("C8", new TableData(8L, "Rajesh"));
return loadDataMap;
}
4-In next step i required to implements interface name MapListener which has following method to catch the event.
public void entryInserted(MapEvent mapEvent) { }
public void entryUpdated(MapEvent mapEvent) }
public void entryDeleted(MapEvent mapEvent) {}
If we add/remove/delete any things from same cache it will automatically trigger this method accordingly
5-So in the same class i have implemented MapListener and override above three method .
Step 3-In third part will explain communication between between oracle coherence and Active data Service.
Here i done with Active data service and oracle coherence.Although we do require communication between coherence and ads .
For providing communication between these two i have created one interface and step are following
1-Created an interface name as TableInterface which has following method
2-implemetated this interface with same class which extends ActiveCollectionModelDecorator class and override all the method code are following
Step 4-Registration of the bean into adfc-config.xml
<managed-bean id="__2">
<managed-bean-name id="__1">tableActive</managed-bean-name>
<managed-bean-class id="__4">com.backing.bean.ads.TableActiveCollectionModelDecorator</managed-bean-class>
<managed-bean-scope id="__3">session</managed-bean-scope>
</managed-bean>
<managed-bean id="__26">
<managed-bean-name id="__25">coherenceClass</managed-bean-name>
<managed-bean-class id="__23">com.backing.bean.coherence.CoherenceClass</managed-bean-class>
<managed-bean-scope id="__24">session</managed-bean-scope>
<managed-property id="__28">
<property-name id="__27">listener</property-name>
<value id="__29">#{tableActive}</value>
</managed-property>
</managed-bean>
Step5-Doing following operation into oracle coherence cache.
I have created TestingClass class for doing add/delete/update into cache i have created one main class which has following code.
So in above code if you run after running the page since only add line is not commented so it will add the new record into cache .
1-Aftering adding records in cache
2-After updating records
3-After deleting records
Code is present at following location
https://docs.google.com/open?id=0B8cP4jZuxLlXbWcyU0RVejc5b28
I have to explain more in details which i know but due to less time i have to stop here but later sure i will update this post if possible.
However this is just POC to understand communication between oracle coherenernce and ADS.
Reference :
1-http://biemond.blogspot.in/2009/12/adf-data-push-with-active-data-service.html
2-http://matthiaswessendorf.wordpress.com/2010/01/07/adf%E2%80%99s-active-data-service-and-scalar-data-like-activeoutputtext/
3-Oracle Fusion Developer Guide
Thanks
Prateek
Use Case :Need to show latest records into af:table with use of oracle coherence.
Class Description :
The following class which i used to achieve my requirement .
1-TableActiveCollectionModelDecorator
This class used for providing the model data for af:table
Extends ActiveCollectionModelDecorator
2-TableActiveModelClass
This class extends BaseActiveDataModel
3-CoherenceClass
This class use to put the data into oracle coherence
4-Interface TableInterface for listen Map listener
The class and interface relationship is depicted in following picture
UI description :
Here i used af:table as UI component to show the latest data.
I have been working on a project where i need to show the latest data on UI .For this we are using following technology.
1-Active data service
2-And oracle coherence
Since this bit tricky and tough to understand so for this i have divided my post under following parts
Step 1-In first part will explain active data service configuration into the application.
Step 2-In second part will explain oracle coherence for maintaining data in memory cache.
Step 3-In third part will explain communication between between oracle coherence and Active data Service.
Step 4-Registration of the bean into adfc-config.xml
Step5-Doing following operation into oracle coherence cache.
1-Adding new record into cache
2-update records into cache
3-delete records into cahce
So let me explain each individual point in details
Step 1-In first part will explain active data service configuration into the application.
1-You require to configure Active Data Service in the adf-config.xml.In adf-config.xml file need to register communication transport details and need to create new property file name as adf-config.properties file .
i)ADD following code in adf-config.xml
<?xml version="1.0" encoding="utf-8" ?>
<adf-config xmlns="http://xmlns.oracle.com/adf/config"
xmlns:ads="http://xmlns.oracle.com/adf/activedata/config">
<ads:adf-activedata-config xmlns=
"http://xmlns.oracle.com/adf/activedata/config">
<transport>long-polling</transport>
<latency-threshold>10000</latency-threshold>
<keep-alive-interval>10000</keep-alive-interval>
<polling-interval>3000</polling-interval>
<max-reconnect-attempt-time>1500000</max-reconnect-attempt-time>
<reconnect-wait-time>10000</reconnect-wait-time>
</ads:adf-activedata-config>
</adf-config>
<adf-config xmlns="http://xmlns.oracle.com/adf/config"
xmlns:ads="http://xmlns.oracle.com/adf/activedata/config">
<ads:adf-activedata-config xmlns=
"http://xmlns.oracle.com/adf/activedata/config">
<transport>long-polling</transport>
<latency-threshold>10000</latency-threshold>
<keep-alive-interval>10000</keep-alive-interval>
<polling-interval>3000</polling-interval>
<max-reconnect-attempt-time>1500000</max-reconnect-attempt-time>
<reconnect-wait-time>10000</reconnect-wait-time>
</ads:adf-activedata-config>
</adf-config>
ii)First create services folder under .adf/META-INF directory and then create property file name adf-config.properties add following code in adf-config.properties file
http\://xmlns.oracle.com/adf/activedata/config=oracle.adfinternal.view.faces.activedata.ActiveDataConfiguration$ActiveDataConfigCallback
*Be careful all the above line should be in one single line.
2-Since here i am using af:table component for Active data service so first class which we do require to extends is ActiveCollectionModelDecorator.
Here i am using ActiveCollectionModelDecorator class however you can also use ActiveDataModel class .
Code is following
package com.backing.bean.ads;
import com.backing.bean.coherence.CoherenceClass;
import com.backing.bean.coherence.Example;
import com.backing.bean.data.TableData;
import com.backing.bean.interfacee.TableInterface;
import com.backing.bean.model.TableActiveModelClass;
import java.util.List;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import oracle.adf.view.rich.event.ActiveDataEntry;
import oracle.adf.view.rich.event.ActiveDataUpdateEvent;
import oracle.adf.view.rich.model.ActiveCollectionModelDecorator;
import oracle.adf.view.rich.model.ActiveDataModel;
import oracle.adfinternal.view.faces.activedata.ActiveDataEventUtil;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.SortableModel;
public class TableActiveCollectionModelDecorator extends ActiveCollectionModelDecorator {
private TableActiveModelClass _activeDataModel =
new TableActiveModelClass();
List<TableData> getTableDataList = null;
private CollectionModel _model = null;
public TableActiveCollectionModelDecorator() {
super();
}
public ActiveDataModel getActiveDataModel() {
return _activeDataModel;
}
protected CollectionModel getCollectionModel() {
if (_model == null) {
FacesContext ctx = FacesContext.getCurrentInstance();
ExpressionFactory ef = ctx.getApplication().getExpressionFactory();
ValueExpression ve =
ef.createValueExpression(ctx.getELContext(), "#{coherenceClass}",
CoherenceClass.class);
CoherenceClass context =
(CoherenceClass)ve.getValue(ctx.getELContext());
getTableDataList = context.getTableDataList();
_model = new SortableModel(getTableDataList);
}
return _model;
}
}
*Here coherence class is responsible to fetch data from coherence and return into this class.When the page if load first time getCollectionModel() method will called and return data back to UI.import com.backing.bean.coherence.CoherenceClass;
import com.backing.bean.coherence.Example;
import com.backing.bean.data.TableData;
import com.backing.bean.interfacee.TableInterface;
import com.backing.bean.model.TableActiveModelClass;
import java.util.List;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import oracle.adf.view.rich.event.ActiveDataEntry;
import oracle.adf.view.rich.event.ActiveDataUpdateEvent;
import oracle.adf.view.rich.model.ActiveCollectionModelDecorator;
import oracle.adf.view.rich.model.ActiveDataModel;
import oracle.adfinternal.view.faces.activedata.ActiveDataEventUtil;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.SortableModel;
public class TableActiveCollectionModelDecorator extends ActiveCollectionModelDecorator {
private TableActiveModelClass _activeDataModel =
new TableActiveModelClass();
List<TableData> getTableDataList = null;
private CollectionModel _model = null;
public TableActiveCollectionModelDecorator() {
super();
}
public ActiveDataModel getActiveDataModel() {
return _activeDataModel;
}
protected CollectionModel getCollectionModel() {
if (_model == null) {
FacesContext ctx = FacesContext.getCurrentInstance();
ExpressionFactory ef = ctx.getApplication().getExpressionFactory();
ValueExpression ve =
ef.createValueExpression(ctx.getELContext(), "#{coherenceClass}",
CoherenceClass.class);
CoherenceClass context =
(CoherenceClass)ve.getValue(ctx.getELContext());
getTableDataList = context.getTableDataList();
_model = new SortableModel(getTableDataList);
}
return _model;
}
}
Here following method are override
1-public ActiveDataModel getActiveDataModel() {}
2- public CollectionModel getCollectionModel(){}
3-Second class which is require to extends BaseActiveDataModel class moreover this class is also very important class.Code is following
package com.backing.bean.model;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import oracle.adf.view.rich.activedata.BaseActiveDataModel;
import oracle.adf.view.rich.event.ActiveDataUpdateEvent;
import oracle.adf.view.rich.model.ActiveCollectionModelDecorator;
import oracle.adf.view.rich.model.ActiveDataModel;
import org.apache.myfaces.trinidad.model.BaseMenuModel;
import org.apache.myfaces.trinidad.model.CollectionModel;
public class TableActiveModelClass extends BaseActiveDataModel {
@Override
protected void startActiveData(Collection<Object> rowKeys,
int startChangeCount) {
}
@Override
protected void stopActiveData(Collection<Object> rowKeys) {
}
@Override
public int getCurrentChangeCount() {
return changeCounter.get();
}
public void prepareDataChange() {
changeCounter.incrementAndGet();
}
public void notifyDataChange(ActiveDataUpdateEvent event) {
fireActiveDataUpdate(event);
}
private final AtomicInteger changeCounter = new AtomicInteger();
}
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import oracle.adf.view.rich.activedata.BaseActiveDataModel;
import oracle.adf.view.rich.event.ActiveDataUpdateEvent;
import oracle.adf.view.rich.model.ActiveCollectionModelDecorator;
import oracle.adf.view.rich.model.ActiveDataModel;
import org.apache.myfaces.trinidad.model.BaseMenuModel;
import org.apache.myfaces.trinidad.model.CollectionModel;
public class TableActiveModelClass extends BaseActiveDataModel {
@Override
protected void startActiveData(Collection<Object> rowKeys,
int startChangeCount) {
}
@Override
protected void stopActiveData(Collection<Object> rowKeys) {
}
@Override
public int getCurrentChangeCount() {
return changeCounter.get();
}
public void prepareDataChange() {
changeCounter.incrementAndGet();
}
public void notifyDataChange(ActiveDataUpdateEvent event) {
fireActiveDataUpdate(event);
}
private final AtomicInteger changeCounter = new AtomicInteger();
}
Although here i am not doing any thing in the startActiveData and stopActiveData but it is used to seed and remove the resource.
Above are steps to implements Active data service and following are for oracle coherence
Step 2-In second part will explain oracle coherence for maintaining data in memory cache.
1-First need to add the coherence.jar jar file into application path. coherence.jar is already available in jdeveloper installation folder
Location is following
oracle installation folder name\oracle_common\modules\oracle.coherence
2-Created class name as CoherenceClass where i have done initialization for Name Cache as following in static block
static {
nameCache = CacheFactory.getCache(CACHE_NAME);
}
3-In constructor of CoherenceClass load the data form method and add in the oracle coherence as following
public CoherenceClass() {
CacheFactory.ensureCluster();
NamedCache nc = CacheFactory.getCache(CoherenceClass.CACHE_NAME);
nc.addMapListener(this);
if (nc.size() == 0) {
nc.putAll(loadDataFromCoherence());
}
}
private static Map loadDataFromCoherence() {
//This are my friends name
Map loadDataMap = new HashMap();
loadDataMap.put("C0", new TableData(0L, "Prateek"));
loadDataMap.put("C1", new TableData(1L, "Abhishek"));
loadDataMap.put("C2", new TableData(2L, "Satyendra"));
loadDataMap.put("C3", new TableData(3L, "Ramesh"));
loadDataMap.put("C4", new TableData(4L, "Anoop"));
loadDataMap.put("C5", new TableData(5L, "Jamal"));
loadDataMap.put("C6", new TableData(6L, "Laljeet"));
loadDataMap.put("C7", new TableData(7L, "Hariom"));
loadDataMap.put("C8", new TableData(8L, "Rajesh"));
return loadDataMap;
}
4-In next step i required to implements interface name MapListener which has following method to catch the event.
public void entryInserted(MapEvent mapEvent) { }
public void entryUpdated(MapEvent mapEvent) }
public void entryDeleted(MapEvent mapEvent) {}
If we add/remove/delete any things from same cache it will automatically trigger this method accordingly
5-So in the same class i have implemented MapListener and override above three method .
Step 3-In third part will explain communication between between oracle coherence and Active data Service.
Here i done with Active data service and oracle coherence.Although we do require communication between coherence and ads .
For providing communication between these two i have created one interface and step are following
1-Created an interface name as TableInterface which has following method
public void entryInCoherence(Integer rowKey, TableData tableData);
public void updateInCoherence(Integer rowKey, TableData tableData);
public void deleteInCoherence(Integer rowKey, TableData tableData);
public void updateInCoherence(Integer rowKey, TableData tableData);
public void deleteInCoherence(Integer rowKey, TableData tableData);
2-implemetated this interface with same class which extends ActiveCollectionModelDecorator class and override all the method code are following
public void entryInCoherence(Integer rowKey, TableData tableData) {
if (rowKey != null) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.INSERT,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
}
public void updateInCoherence(Integer rowKey, TableData tableData) {
if (rowKey != null) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.UPDATE,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
}
public void deleteInCoherence(Integer rowKey, TableData tableData) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.REMOVE,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
if (rowKey != null) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.INSERT,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
}
public void updateInCoherence(Integer rowKey, TableData tableData) {
if (rowKey != null) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.UPDATE,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
}
public void deleteInCoherence(Integer rowKey, TableData tableData) {
TableActiveModelClass asm = _activeDataModel;
asm.prepareDataChange();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.REMOVE,
asm.getCurrentChangeCount(),
new Object[] { rowKey },
new Object[] { null },
new String[] { "id",
"name" },
new Object[] { tableData.getId(),
tableData.getName() });
asm.notifyDataChange(event);
}
Step 4-Registration of the bean into adfc-config.xml
<managed-bean id="__2">
<managed-bean-name id="__1">tableActive</managed-bean-name>
<managed-bean-class id="__4">com.backing.bean.ads.TableActiveCollectionModelDecorator</managed-bean-class>
<managed-bean-scope id="__3">session</managed-bean-scope>
</managed-bean>
<managed-bean id="__26">
<managed-bean-name id="__25">coherenceClass</managed-bean-name>
<managed-bean-class id="__23">com.backing.bean.coherence.CoherenceClass</managed-bean-class>
<managed-bean-scope id="__24">session</managed-bean-scope>
<managed-property id="__28">
<property-name id="__27">listener</property-name>
<value id="__29">#{tableActive}</value>
</managed-property>
</managed-bean>
Step5-Doing following operation into oracle coherence cache.
I have created TestingClass class for doing add/delete/update into cache i have created one main class which has following code.
package com.backing.bean.coherence;
import com.backing.bean.data.TableData;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class TestingClass {
public TestingClass() {
super();
}
public static void main(String[] args) {
//here only add new record line is commented
//following checking the update and delete please remove the comment
NamedCache nc = CacheFactory.getCache(CoherenceClass.CACHE_NAME);
//adding new record
nc.put("PK1", new TableData(1001L, "PrateekShaw"));
//updatring record
// nc.put("PK1", new TableData(1001L, "PrateekKumarShaw"));
//deleting record
// nc.remove("PK1");//Pass the key
}
}
import com.backing.bean.data.TableData;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class TestingClass {
public TestingClass() {
super();
}
public static void main(String[] args) {
//here only add new record line is commented
//following checking the update and delete please remove the comment
NamedCache nc = CacheFactory.getCache(CoherenceClass.CACHE_NAME);
//adding new record
nc.put("PK1", new TableData(1001L, "PrateekShaw"));
//updatring record
// nc.put("PK1", new TableData(1001L, "PrateekKumarShaw"));
//deleting record
// nc.remove("PK1");//Pass the key
}
}
So in above code if you run after running the page since only add line is not commented so it will add the new record into cache .
1-Aftering adding records in cache
2-After updating records
3-After deleting records
Code is present at following location
https://docs.google.com/open?id=0B8cP4jZuxLlXbWcyU0RVejc5b28
I have to explain more in details which i know but due to less time i have to stop here but later sure i will update this post if possible.
However this is just POC to understand communication between oracle coherenernce and ADS.
Reference :
1-http://biemond.blogspot.in/2009/12/adf-data-push-with-active-data-service.html
2-http://matthiaswessendorf.wordpress.com/2010/01/07/adf%E2%80%99s-active-data-service-and-scalar-data-like-activeoutputtext/
3-Oracle Fusion Developer Guide
Thanks
Prateek
Prateek, this is very useful. But Why all the managed bean is registered in session scope?
ReplyDeleteIs there any limitation?
Hi,
DeleteNo it's depend on your requirement.
But scope should be more than request and backing bean
Thanks
Prateek
Many thanks for sharing Prateek
ReplyDeleteI hope it would work the same if I link Coherence and Programmatic BC and bind programmatic VO behind the UI table. Please share your views on that.
Hi Ponraj.
DeleteYes you can get the data from coherence and programmatic create VO.But i things it does not support ADS.
For supporting ADS you need to create new model which support ADS.
Hi Prateek, Thanks for your blog really helpful.
ReplyDeleteOne problem i am finding in using this is the data that is being loaded at the start ( the names of your friends in the tables), if i try to modify the data in those rows or delete them altogether, its not reflecting in real time in ADF-ADS. The Coherence cache is updated and i if i open a new browser instance, it reflects the change. The example you have where you create a new one, then update/delete that record works just fine.
Thanks
Anirban
Hi Anirban,
DeleteIt should work the only things which you should need to remember that is row key.While create the event for Update/Delete you should need to pass correct row key.Might be you are passing wrong row key therefore it is not working for existing rows.