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++) {
            boolean viewPushed = false;
            while (iterator.hasNext() && !viewPushed) {
                Row rowFields =;
                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;

No comments:

Post a Comment