Posts

Showing posts from May, 2011

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…

Setting the bind variable value for the destination View Object in the View Link

Image
I'm sharing an interesting use case that has come up recently from an internal team. The developer was looking for some hooks to set bind variable value used in the destination View Object participating in a View Link. Steve Muench has shared a useful tip to solve this case, let me share the same here for your reference, thanks Steve :)

The use case requirement is to set bind variable value conditionally for the child view object. Interestingly, the bind variable value is supposed to set programmatically only when the child view object is executed as part of master child coordination(through view link), in all other cases it's left to the caller.

The solution is very straight forward. The 11.1.1.5.0 release has new method added ViewObjectImpl::prepareRowSetForQuery(ViewRowSetImpl vrs) to intercept the VO query preparation phase. You may need to override this method, and add check for parent rows(to see whether VO instance is participating in master child coordination) and s…

Why do you see a duplicate af:commandToolbarButton after partial page refresh?

This is a very widely observed issue if you have partialTriggers set for child components of <af:toolbar>.
<af:toolbar> <af:commandToolbarButton ... partialTriggers="someComp"/> </af:toolbar>
What goes wrong here?

Well, please see the tag documentation for <af:toolbar&gt . I'm copying the relevant content for your reference.

Updating through PartialTriggers

Note that if a toolbar child component is going to be updated through partial page rendering, you need to update the toolbar as well. You do this by adding the child components id to the toolbar's partialTriggers attribute. This way the toolbar can appropriately manage its children in respect to sizing and placement in overflow. Also note that many input components also update themselves through partial page rendering. If you include an input component (or quickQuery) on a toolbar, you should include that child's id in the toolbar's partialTriggers attribute so that t…

Soft deletion of rows

Image
In this post I'm sharing a simple example illustrating the 'soft deletion' of rows and undoing the delete later if the user opts for. The business use case requirement is that, whenever end user delete rows, system should not delete these rows from the underlying data base table, rather should mark(update) them as deleted. Later user can undo the deletion to restore the deleted rows(this operation should not rollback the transaction)


Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS4 + HR Schema]

A glance at the implementation

The 'Soft Delete' action has two steps,
1.The action first refreshes the row with database by calling row.refresh(Row.REFRESH_WITH_DB_FORGET_CHANGES) to discard the modifications that user might have done on the row before opting for delete(if any)
2. Next step is to remove the row from the iterator(effectively from entity object). Deleted row keys are stored in an ArrayList for performing …

ADF BC run time now calls refreshCollection(...) on your shared ViewObject !

There is an interesting enhancement available on ViewObjectImpl::executeQuery() with 11.1.1.5.0 release. Now the executeQuery() will check for the View Object's parent Application Module configuration to see if its defined as 'shared AM' and may call refreshCollection(...) for shared View Objects. So you don't need to worry on calling the confusing refreshCollection(...) to access cached query collection without reexecuting the query. You are allowed to call ViewObjectImpl::executeQuery() always in a seamless way :)

If you really need to forcefully execute query on shared View Object, then please use ViewObjectImpl::forceExecuteQueryOfSharedVO() - API available since 11.1.1.5.0

Preparing ViewObject's query for execution

If you need to assign bind variable values or modify where clause conditionally just before the the query execution, then 11.1.1.5.0(PS4) release has a new method added ViewObjectImpl::prepareRowSetForQuery(ViewRowSetImpl vrs). This method engages well with ViewObjectImpl::getQueryHitCount()and ViewObjectImpl::getEstimatedRowCount() as well. I mean the prepareRowSetForQuery(...) will get invoked before calling the the above methods by the runtime. This is useful if you need to set bind variable values before the query execution for List Of Values or ViewAccssors used for displaying Tree components.

You can use this method safely(zero side effect) to add your logic for tweaking default query by setting bind variable values or additional where clause at run time.
Example:

public class DepartmentsViewObjectImpl extends ViewObjectImpl{
...
@Override
public void prepareRowSetForQuery(ViewRowSetImpl vrs) {
vrs.ensureVariableManager().setVariableValue("bindVarDeptId", deptIdRunti…

Oracle JDeveloper and Oracle ADF 11g Release 1 Patch Set 4 is now available on OTN

Oracle JDeveloper and Oracle ADF 11g Release 1 Patch Set 4 (11.1.1.5.0)(Build 6013) is available on OTN. Check it out

Turning off the stretchable behavior of <af:inputComboboxListOfValues>

Image
The <af:inputComboboxListOfValues> has been enhanced recently(11.1.1.4.0) to stretch the contents of the drop down list to reflect the display width of the attribute that you set on a view object.


This feature is controlled by a boolean ADF skin property, -tr-stretch-dropdown-table. Web UI Developers Guide says...
This property determines whether the table in the dropdown list stretches to show the content of the table columns or limits the width of the table to the width of the input field in the inputComboboxListOfValues component.

You can turn off the stretchable behavior using the following selector in your css file. Customizing the skinning is already discussed in one of my previous post- Style your application in your own way. More details on skinning can be found in the following link as well - Apache Trinidad Skinning

af|inputComboboxListOfValues{
-tr-stretch-dropdown-table: false;
}

Multiple root Application Modules sharing the same transaction context !

I'm not sure how many of you noticed the following section in Fusion Developers Guide - 10.2.6 What You May Need to Know About Shared Application Modules and Connection Pooling. This part talks about an AM configuration parameter 'jbo.shared.txn' which can be used for sharing entity cache and DB connection across multiple root application modules. You just need to key in same string value for 'jbo.shared.txn' using the properties page of the editor for the bc4j.xcfg file of the root application modules.

Please note that this property is applicable for shared as well as non shared Application Modules(though originally designed for non-shared AM). Interestingly, this is used internally by the declarative taskflow transaction to allow the ADF BC Data Controls to share a DBTransaction. I'm copying the relevant content from developers guide below for a quick reference...

When your application defines more than one shared application module, you can change the defa…

Disclaimer

The views expressed on this blog are my own and do not necessarily reflect the views of my employer.