Skip to main content

Checking for dirty data

Sometimes you may need to check for the modified state of the business data. If your data update is always triggered through ADF binding layer(where the UI component is bound with data using EL #{bindings.xxx.inputValue}), then its an easy job as all the data access is routed through a common entry point. You can safely use DCDataControl::isTransactionModified() - This returns true if you have modified any of the attribute values exposed by the DataControl. You can use this API even if you use EJB and JavaBean Data Control as well.

DCBindingContainer dcBindingContainer=(DCBindingContainer)
BindingContext.getCurrent().getCurrentBindingsEntry();
if(dcBindingContainer.getDataControl().isTransactionModified()){
//Code goes here...
}

Please note that for those Data Controls which does not have direct implementation for the 'transaction commit'(e.g: EJB or JavaBean Data Control ), its your duty to clear the modified flag once you persist the changes by calling the below given API.

dcBindingContainer.getDataControl().commitTransaction();

Comments

Nice post!
What is the difference from isTransactionDirty()?

Thanx in advance!
Til said…
I have a different scenario
I have 5 Iterators in my page and I make some calculation before save in one of them From Bean.
I want to know if this Iterator have modified data modified or no , I don't care about other iterators in the page.
Is there any method to know if this Iterator have modified data or no to make calculations a gain not to make them every time I Press save.
Jobinesh said…
Spyros,
SomeDC::isTransactionDirty() works well with those DataControls which have implemented oracle.adf.model.TransactionalDataControl. Apparently it works with ADF BC. However this may not work (as of now) with Bean DC as it lacks the specific transactional context implementation. DCDataControl::isTransactionModified() does not consult underlying model for checking the modified status, rather it keeps track of 'TxnModified' flag and marks it as dirty whenever UI pushes updated data to the binding layer.
Jobinesh said…
Til,
I don't think anything existing at Iterator level to check the status. However, if you ADF BC, probably you can try EntityImpl::getEntityState, for each row in the iterator.
Til said…
Thanks Jobinesh but How can I get EntityImpl From Bean.
SK said…
In the form how to if there 10 fields, and only 2 fields are modified, How to get to know which fields are modified using iterator?
Jobinesh said…
Well..you may need to try as shown below (for BC Model)

DCBindingContainer dcb = (DCBindingContainer)bc.getCurrentBindingsEntry();
DCIteratorBinding iterBinding = dcb.findIteratorBinding(iteratorName);
ViewRowImpl dataRow = (ViewRowImpl)iterBinding.getCurrentRow();
String[] attrbNames = dataRow.getAttributeNames();
for (String attrib : attrbNames) {
if (dataRow.isAttributeChanged("attrName")) {
// .....
}
}
Nice!
Forgive me for asking again but this raises another question.
According to API ViewRowImpl.isAttributeChanged
Advanced method: Applications should typically not use this method.
http://download.oracle.com/docs/cd/E16162_01/apirefs.1112/e17483/oracle/jbo/server/ViewRowImpl.html#isAttributeChanged(java.lang.String)
What does this mean?

Sincerely, thanx for your time and all light that you shed on framework's technicalities.
Jobinesh said…
ViewRowImpl.isAttributeChanged woks only with Rows built on EntityObject instances(state flag is with entity) and may fail in all other scenarios. This may be the one reason for marking it as internal usage(in my personal view), otherwise this API just delegates the call to EO instance and looks fine for me.
Thanx for clarifying this once more! I 've seen this a lot in the API and it seemed strange. So, as you said it means "You should know what you do when you are using this method." :)
Hemant said…
I've found a strange problem.
When a clob data field is read from tables and rendered on the page, later if the user doesn't change anything on the page, the data model layer is marked as dirty.

I found this in this way.
I am setting the page af:document uncommitted data warning to ON. Then on the page, there is an item representing a clob column in the table. I have a navigation link to other page and when clicking that, the ADF lifecycle should check whether the page is dirty. I think it will use some method like
ControllerContext.getInstance().getCurrentViewPort().isDataDirty() to do this? The problem is, if that clob field has more than 31744 characters, even you didn't change anything, it will tell you have uncommitted data.
With less than 31744 chars, it works correctly.

I've tried both the "jbo.genericDomain", "oracle.genericDomain" coverter and my customized code clobConverter.

I can see that the String is completed passed into the converter(with my customized code) even when the characters are more than 31744. But it looks the framework just determines that the original data is not the same as the new data.

Please help me out!!
Deepika said…
Hi Jobinesh
I am using the above to check for the transaction state while creating a row in the popup. However when I open the same row in a popup in edit mode, make no changes & try to check for the transaction state, I still get the state as modified. Can you please let me know what it checks for even though I have not changed anything?

Popular posts from this blog

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…