Thursday, February 13, 2014

Showing first tab always when enabling MDS

I came across this scenario earlier, MDS customization is enabled for project, the project runs under webcenter portal.

User runs a page having three tabs, PanelTab along with showDetailItems used, when user select second tab and navigate away, then returns back to the previous page the last selected tab is displayed.

Using Persist property for the ShowDetailItem doesn't solve the problem, since panelTab component in Webcenter will always remember the last selected tab.

One of the WRONG scenario I tried is using Javascript to force the panelTab to set the tab property disclosed to false when page loads, this worked but it have a jumping effect between the tabs and still its a workaround.

The RIGHT way to do it is by using ChangeManager as shown below:

      public void tabDisclosureListener(DisclosureEvent disclosureEvent) {    
        RichShowDetailItem tab = (RichShowDetailItem)disclosureEvent.getComponent();
        FacesContext fc = FacesContext.getCurrentInstance();
        ChangeManager cm = RequestContext.getCurrentInstance().getChangeManager();
        ComponentChange cc = new AttributeComponentChange("disclosed", Boolean.FALSE);
        cm.addComponentChange(fc, tab, cc);
        ........
    }

This will reset the disclosed property when ever any of the tabs where clicked.

Wednesday, February 12, 2014

Tracking Entity Changes (instead of using Triggers on Database side)

In this example I am tracking all changes on specific set of columns or tables to trigger any events before transaction commit changes.

first you need to get a list of all view objects and compare its entity reference with list of tables you have, either stored in database or as fixed list of tables, note that ADF isAttributeChange method uses Java column naming convention not the column name you have on database, so you must build a list of java attribute names based on database column names.

so you need to retrieve all entity usages from viewDef, then get actual table name from the entity definition, also I am building a list of column (database_name) attribute (ADF_name) map, which will be used to check AttributeChangeStatus.

 public Map getViewObjectsNeedsToBeTracked(ViewObject[] allViews, ViewObjectImpl) {
        Map viewObjectsMap = new HashMap();
        //RowSetIterator iterator = Source Data Iterator or Array of tables
        for (int i = 0; i < allViews.length; i++) {
            iterator.reset();
            boolean viewPushed = false;
            while (iterator.hasNext() && !viewPushed) {
                Row rowFields = iterator.next();
                String tableName = (String)rowFields.getAttribute(tableFieldName);
                ViewObjectImpl view = (ViewObjectImpl)allViews[i];
                Map sourceMap = getSourceTableFromView(view);
                if (sourceMap != null) {
                    Object keys[] = sourceMap.keySet().toArray();
                    String sourceTable = (String)keys[0];
                    if (StringUtils.equalsIgnoreCase(tableName, sourceTable)) {
                        AttributeDef defs[] = sourceMap.get(keys[0]);
                        viewObjectsMap.put(tableName, createPairList(allViews[i], defs));
                        viewPushed = true;
                    }
                }
            }
        }
        return viewObjectsMap;
    }

private Map getSourceTableFromView(ViewObjectImpl view) {
        String sourceTable = null;
        Map map = null;
        ViewDefImpl viewDef = (ViewDefImpl)view.getDef();
        EntityReference references[] = viewDef.getEntityUsages();
        if (references != null && references.length > 0) {
            try {
                map = new HashMap();
                EntityDefImpl entityDef = references[0].getEntityDef();
                sourceTable = entityDef.getSource();
                sourceTable = StringUtils.substring(sourceTable, sourceTable.indexOf(".") + 1, sourceTable.length());
                map.put(sourceTable, entityDef.getAttributeDefs());
            } catch (Exception exp) {
                sourceTable = StringUtils.substring(sourceTable, 0, sourceTable.length());
            }
        }
        return map;
    }

Then get list of Attribute definition for source EntityDef, make sure to get persistent attributes only, these are the columns will be posted to database when transaction is committed, other attributes such as transient or constraints should be skipped.

                AttributeDef def = entityAttributeDefs[i];
                if (def.getAttributeKind() == AttributeDef.ATTR_PERSISTENT) {
                    String defColumnName = def.getColumnName();
                    String defName = def.getName();
                   

Check attribute changes methods, passing all captured View Rows along with list of parameters need to tracked:

 private static boolean rowAttributeStatusCheck(ViewRowImpl row, Object[] parameters) {
        boolean result = false;
        if (row != null && parameters != null) {
            for (Object param : parameters) {
                result = result || row.isAttributeChanged(param.toString());
            }
        }
        return result;
    }

Great resource for layouts

Great resource for ADF layouts, informative and direct:
http://www.slideshare.net/AMIS_Services/lbors-goodbyenightmarekscope