Monday, June 25, 2012

Get JPA Entity Attributes programmatically in managed bean

Sometimes it is necessary to get database table field column names for further functional process in applications. In one my previous article I have explained one of the use case - Configure Comparison of Row Objects at Run Time, here application module(BC4J) is used to access the ViewObject attributes.

In EJB data control doesn't create any application module or neither have access to application module Api's directly. When the ViewObject is accessed based on the Iterator a dummy object is created using DCDataVo Api. DCDataVo provides little leverage to access certain model layer functionality, so that all Adapter Data Control can use the DCDataVo api to extend to build custom features.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

Here in the below code JPA entity attributes are accessed in managed bean using DCDataVo api.

/**
 * This method will get the View Object based on Iterator
 * Reads the entity attributes(column names)
 * @param actionEvent
 */
public void compareAttributes(ActionEvent actionEvent) {
 DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
 DCIteratorBinding deptIter = dcBindings.findIteratorBinding("employeesFindAllIterator");
 ViewObject vo = deptIter.getViewObject();
 int count = 0;
 AttributeDef[] attrDefs = vo.getAttributeDefs();
 for (AttributeDef attrDef : attrDefs) {
  byte attrKind = attrDefs[count].getAttributeKind();
  //Condition to exclude the fk attributes
  if (attrKind == 1) {
   System.out.println(attrDef.getName());
   count++;
  }
 }
}

Displaying the Employee entity attributes.

Simulate JPA Dynamic Query Using View Criteria

Recently I'm working in an application where JPA entity has a named query with parameters passed to that query and exposed as EJB data control, here parameter is passed dynamically at run time. Now same data control is dropped as ADF table, where user can add new rows to the table and perform merge/persist operations.

JPA API provides an alternative way for defining JPA queries, which is mainly useful for building dynamic queries whose exact structure is only known at run time. Building a dynamic query based on fields that a user fills at run time in a form that contains many optional fields. 


In this article, I'm trying to Simulate JPA Dynamic Query Using View Criteria to filter ADF Table and perform merge/persist operations on ADF Table. Below solution is the workaround to achieve the above scenario using EJB data control.

In EJB data control doesn't create any application module or neither have access to application module Api's directly. When the ViewObject is accessed based on the Iterator a dummy object is created using DCDataVo Api.  DCDataVo provides little leverage to access certain model layer functionality, so that all Adapter Data Control can use the DCDataVo api to extend to build custom features.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

Implementation Steps

Create Fusion Web Application with entities based on Emplo, then create a session bean and data control for the session bean.

In the ViewController create index.jspx page and create a IndexBean.java as backing bean, follow the below steps:
  • From data control palette drag and drop EmployeesFindAll()->Table as ADF Table.
  • Drop  EmployeesFindAll()->Operations->Create as ADF Button, name as "Commit".
  • Drop the persistEmployees as ADF button and bind the value to "#{bindings.employeesFindAllIterator.currentRow.dataProvider}"
  • From component palette drop Input Text and label as "Department Id"
  • Drop Button, name as "Search" and ActionListener method as "executeSearch"
Open the IndexBean.java and copy the below method code.

/**
 * This method will get the View Object based on Iterator
 * Creates the view crietria at the runtime,
 * Set the Operator type and pass the paramater 
 * Execute the View Object, print results to the web screen.
 * @param actionEvent
 */
public void executeSearch(ActionEvent actionEvent) {
 DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
 DCIteratorBinding deptIter = dcBindings.findIteratorBinding("employeesFindAllIterator");
 // Getting the dummy ViewObject based on Iterator
 ViewObject vo = deptIter.getViewObject();
 // Create the viewCriteria at runtime
 ViewCriteria vc = vo.createViewCriteria();
 ViewCriteriaRow vcRow = vc.createViewCriteriaRow();
 // ViewCriteriaRow attribute value requires operator and value.
 // Note also single-quotes around string value.
 ViewCriteriaItem vcRowItem = vcRow.ensureCriteriaItem("departmentId");
 vcRowItem.setOperator("=");
 vcRowItem.getValues().get(0).setValue(this.getDeptId().getValue());
 vc.addElement(vcRow);
 vo.applyViewCriteria(vc);
 // Execute the query
 vo.executeQuery();
}

Run the index.jspx page and result page looks like below.


Now enter department Id in input text field and click on search button, Employees table will be filtered by department id. Now click on create button to add new rows to the particular searched department, notice a new row is created in the table. Enter the field values and save the record, here if you want to generate employee id as auto generated one then configure @Table Generator for employee id. 

Thursday, June 7, 2012

Display ADF Dynamic Table based on Declarative SQL Mode In View Object

While working in my previous article "Configure Comparison of Row Objects at Run Time", I struck in constructing the dynamic SQL statement, where I needed to pass the selected column attributes at run time and displays the results using ADF Dynamic Table.

ADF Business Components support constructing design time and run time SQL statements known as "Declarative SQL Mode". Please refer 5.8 Working with View Objects in Declarative SQL Mode in Fusion Developer's Guide to learn more about Declarative View Objects.

Declarative SQL Mode generates SELECT and from options, where required column attributes should be populated in programmatic way. So by this way we can control which are the required column attributes to be queried.

Note: - But ADF Dynamic Table in view layer will not have any clue, which are the attributes selected in model layer. So ADF Dynamic Table will still display all the attributes in view layer. In this article, I'm showing how can we "Display ADF Dynamic Table based on Declarative SQL Mode In View Object". 

So the out come of this scenario looks like below. In the webpage employees details will be displayed with all attributes. Click on the "processDeclarativeSqlQuery" button.


Notice in the below image, only three attributes will be displayed which are passed as dynamic attributes to the SQL query at run time.


You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

The below approach is one of the way to handle the dynamic attributes passed to SQL query at run time and display only those attributes in view layer using ADF Dynamic Table.

Implementation Steps

Create Fusion Web Application with business components from tables based Employees table, open EmployeesView.xml and select Query tab. Click on Edit SQL Query and select the mode as "Declarative" as shown in the below image.


Select the Attribute tab and uncheck "Selected in Query" options for all the Attributes.

Next go to Java tab in AppModule and click on edit java options. Generate the application module class: AppModuleImpl.java and open the AppModuleImpl.java file and the below methods code.

Note: - Below attribute values are hard coded.
/**
 * This method will execute the Declarative Sql mode by filtering
 * required attributes in result set.
 **/
public void processDeclarativeSqlQuery() {
 ViewObjectImpl empVoImpl = this.getEmployeesView1();
 empVoImpl.resetSelectedAttributeDefs(false);
 empVoImpl.selectAttributeDefs(new String[] { "FirstName", "LastName", "Email" });
 System.out.println(empVoImpl.getQuery());
 empVoImpl.executeQuery();

        //Since ADF Dynamic Table in view layer will not have any clue, which are the attributes selected in model layer
        //So updating the displayHint values as "Hide", this value can be checked in view layer using column rendered property
 ArrayList attrList = new ArrayList();
 attrList.add("FirstName");
 attrList.add("LastName");
 attrList.add("Email");
 ViewAttributeDefImpl[] attrDefs = empVoImpl.getViewAttributeDefImpls();
 for (ViewAttributeDefImpl attrDef : attrDefs) {
  byte attrKind = attrDef.getAttributeKind();
  //checks attribute kind for each element in an array of AttributeDefs
  if (attrKind != AttributeDef.ATTR_ASSOCIATED_ROW && attrKind != AttributeDef.ATTR_ASSOCIATED_ROWITERATOR) {
   String columnName = attrDef.getName();
   if (!attrList.contains(columnName)) {
    //Setting the displayHint property value as "HIDE"
    attrDef.setProperty("DISPLAYHINT", "HIDE");
   }
  }
 }
}
Go back to AppModule.xml and select Java tab in client interface section move processDeclarativeSqlQuery, from available to selected block.

In ViewController project, create index.jspx page.
  • From data control palette drag and drop EmployeesView1->Table as ADF Read Only Dynamic Table, set RowSelection as "multiple" and surround the table with panel collection component.
  • From data control palette drop processDeclarativeSqlQuery as ADF Button and set the partial trigger to the employees table.
  • Set the rendered property for the column as "#{bindings.EmployeesView1.hints[def.name].displayHint  eq 'Display'}".
Employees Dynamic Table code will looks like below.
<af:table rows="#{bindings.EmployeesView1.rangeSize}"
    fetchSize="#{bindings.EmployeesView1.rangeSize}"
    emptyText="#{bindings.EmployeesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
    var="row" rowBandingInterval="0"
    value="#{bindings.EmployeesView1.collectionModel}"
    selectedRowKeys="#{bindings.EmployeesView1.collectionModel.selectedRow}"
    selectionListener="#{bindings.EmployeesView1.collectionModel.makeCurrent}"
    rowSelection="multiple" id="t1" styleClass="AFStretchWidth" partialTriggers="::cb1">
 <af:forEach items="#{bindings.EmployeesView1.attributeDefs}" var="def">
  <af:column headerText="#{bindings.EmployeesView1.labels[def.name]}" sortable="true"
       sortProperty="#{def.name}" id="c1"
       rendered="#{bindings.EmployeesView1.hints[def.name].displayHint  eq 'Display'}">
   <af:outputText value="#{row[def.name]}" id="ot1"/>
  </af:column>
 </af:forEach>
</af:table>

Sunday, June 3, 2012

Configure Comparison of Row Objects at Run Time

Recently I was working in an application where I need to compare two or more row objects based on selected attributes. In this article I will explain one of the way to configure comparison of row objects at run time, so this pattern will give users the ability to select row objects for comparison and to define which of the available attributes they want to compare at run time.

So the out come of this scenario looks like below. In result page car details table will be displayed, user can select the multiple rows for comparison and click on Compare button.


Next screen will display the shuttle component, where it defines which are the attributes included in the comparison. So user can move attributes from available attributes to selected attributes to compare and click on the Process button.


Note:- In above shuttle component attributes are read from ViewObject programmatically, article written in one of my previous blog - Get ViewObject attributes are  read programmatically and display these attributes in ADF Shuttle component.

Final comparison results table, notice all selected attributes will be showed as first column values and also selected row objects are displayed.


Note:- Above dynamic table is used to display Cars Features Comparison, I followed the solution written on AMIS Technology Blog regarding Creating ADF Faces Dynamic Table with Head to Head comparison using managed bean.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2)]

Implementation steps

Create Fusion Web Application with business components from tables based on Cars table, create a new extended object from Cars View as shown in below image.


Note: Download the application from above link and unzip the application. schema.sql file is in application etc folder.

Open the childCarsView, select Query tab and create bind variable "Bind_CarsID".


Alter the query as below.
SELECT Cars.ID, 
       Cars.NAME, 
       Cars.MSRP, 
       Cars.BASE_ENGINE, 
       Cars.CYLINDERS, 
       Cars.DRIVE_TYPE, 
       Cars.FUEL_CAPACITY, 
       Cars.FUEL_ECONOMY, 
       Cars.FUEL_TYPE, 
       Cars.HORSE_POWER, 
       Cars.TORQUE, 
       Cars.TRANSMISSION
FROM CARS Cars
WHERE Cars.ID in (select regexp_substr(:Bind_CarsID,'[^,]+', 1, level) 
   from dual 
    connect by 
        regexp_substr(:Bind_CarsID, '[^,]+', 1, level) 
            is not null)
Arun Ramamoorthy has explained well in article how to split comma separated string and pass to IN clause of select statement.

Open the AppModule and select Data Model tab move "childCarsView" from available view objects to data model.


Create a CompareAttributes.java and paste the below code.
public class CompareAttributes {
    private String columnName;
    private String columnAliasName;

    public CompareAttributes() {
        super();
    }

    public CompareAttributes(String columnName, String columnAliasName) {
        super();
        this.columnName = columnName;
        this.columnAliasName = columnAliasName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnAliasName(String columnAliasName) {
        this.columnAliasName = columnAliasName;
    }

    public String getColumnAliasName() {
        return columnAliasName;
    }
}
Next go to Java tab in AppModule and click on edit java options. Generate the application module class: AppModuleImpl.java

Open the AppModuleImpl.java file and add the below methods code.
/**
 * This method reads the ViewObject attributes and populate CompareAttributes list
 * @return CompareAttributes list
 */
public List getCompareAttributes() {
	ViewObjectImpl vo = getCarsView1();
	ViewAttributeDefImpl[] attrDefs = vo.getViewAttributeDefImpls();
	int count = 0;
	List compareAttrs = new ArrayList();
	for (ViewAttributeDefImpl attrDef : attrDefs) {
		byte attrKind = attrDefs[count].getAttributeKind();
		//checks attribute kind for each element in an array of AttributeDefs
		if (attrKind != AttributeDef.ATTR_ASSOCIATED_ROW && attrKind != AttributeDef.ATTR_ASSOCIATED_ROWITERATOR) {
			String columnName = attrDef.getName();
			String columnAliasName = attrDef.getAliasName();
			//Excluding the Id and Name fields
			if (!columnName.equals("Id") && !columnName.equals("Name")) {
				compareAttrs.add(new CompareAttributes(columnName, columnAliasName));
			}
			count++;
		}
	}
	return compareAttrs;
}

/**
 * Clean up the childCarsView existing rows from collection.
 */
public void cleanUpChildCarsView1() {
	ViewObject childEmpVO = (ViewObject)this.getChildCarsView1();
	//avoid validation when navigating rows
	childEmpVO.setRowValidation(false);
	while (childEmpVO.hasNext()) {
		childEmpVO.setCurrentRow(childEmpVO.next());
		childEmpVO.removeCurrentRowFromCollection();
	}
}

/**
 * This method will populate the childCarsView 
 * carRowKeysList contains CARS table primiary key - Id and
 * which will be passed as In Clause params 
 * @param carRowKeysList
 */
public void populateSelectedRows(List carRowKeysList) {
	if (carRowKeysList != null && carRowKeysList.size() > 0) {
		//Clean up the childCarsView 
		cleanUpChildCarsView1();
		String carsSelectedString = "";
		ViewObject childcarsVo = getChildCarsView1();
		for (int i = 0; i < carRowKeysList.size(); i++) {
			carsSelectedString += carRowKeysList.get(i) + ",";
		}
		childcarsVo.setNamedWhereClauseParam("Bind_CarsID",
											 carsSelectedString.substring(0, (carsSelectedString.length() - 1)));
		childcarsVo.executeQuery();
	}
}
Go back to AppModule.xml and select Java tab in client interface section move getCompareAttributes and populateSelectedRows from available to selected block.


In ViewController project, create a bounded taskflow as "Compare-btf". Open the Compare-btf taskflow, from component palette drop views as "CarsDetails", "CarsCompare". Generate CarsDetails.jsff, CarsCompare.jsff pages and "CarsDetailsBean.java", "CarsCompareBean.java" respectively. Add the EmployeeDetailsBean.java, CarsCompareBean.java  file in taskflow with scope as viewScope.

Draw the control flow case from CarsDetails to CarsCompare, outcome as compare and draw the control flow case from CarsCompare to CarsDetails, outcome as back.

Open CarsDetails.jsff page
  • From data control palette drag and drop CarsView1->Table as ADF Read Only Table, set RowSelection as "muliptle".
  • Surround the table with panel collection component and add Compare button with text as "Compare". 
  • Create the actionListener method for Compare button as "fectchSelectedCarKeys" and action as "compare".
  • Add the binding for table as "carsTable".
Open the CarsDetailsBean.java file and copy the below methods code.
/**
 * This method will get selected rows primiary key - Id values
 * @param actionEvent
 */
public void fectchSelectedCarKeys(ActionEvent actionEvent) {
	RowKeySet selectedCars = getCarsTable().getSelectedRowKeys();
	if (selectedCars.size() > 0) {
		DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
		DCIteratorBinding deptIter = dcBindings.findIteratorBinding("CarsView1Iterator");
		RowSetIterator deptRSIter = deptIter.getRowSetIterator();


		Iterator selectedCarsIter = selectedCars.iterator();
		List selectedRowKeys = new ArrayList();
		while (selectedCarsIter.hasNext()) {
			Key key = (Key)((List)selectedCarsIter.next()).get(0);
			Row currentRow = deptRSIter.getRow(key);
			selectedRowKeys.add(currentRow.getAttribute("Id"));
		}
		ADFContext.getCurrent().getPageFlowScope().put("selectedCarsRowKeys", selectedRowKeys);
	}
}
Open CarsCompare.jsff page.
  • From component palette drop the shuttle component and Bind to list value as "#{viewScope.CarsCompareBean.shuttleList}", looks like below code.
  • Add the shuttle component value as "#{viewScope.CarsCompareBean.selectedAttributes}"
  • Go to Bindings tab and create method action for "getCompareAttributes".
<af:selectManyShuttle label="" id="sms1" leadingHeader="Available Attributes"
					  trailingHeader="Selected Attributes"
					  value="#{viewScope.CarsCompareBean.selectedAttributes}" valuePassThru="true">
	<f:selectItems value="#{viewScope.CarsCompareBean.shuttleList}" id="si1"/>
</af:selectManyShuttle>
  • Add the button, name as "Process" and  create the actionListener method as "processAction".
  • Go to Bindings tab and create method action for "populateSelectedRows".
  • Create a Tree bindings as shown below.
  • Add the below dynamic table code to the page
<af:table var="row" rowBandingInterval="0" value="#{viewScope.CarsCompareBean.rows}" rowSelection="single"
		  id="t1b" styleClass="AFStretchWidth" partialTriggers=":::cb1">
	<af:forEach items="#{viewScope.CarsCompareBean.columns}" var="col">
		<af:column headerText="#{col['label']}" sortable="true" sortProperty="#{'name'}" id="c1b">
			<af:outputText value="#{row[col['name']]}" id="ot1b"/>
		</af:column>
	</af:forEach>
</af:table>
Open the CarsCompareBean.java and add the below methods code.
//Holds selected values in shuttle component
List selectedAttributes;
//Populates the shuttle component
List shuttleList;
//Populates the comparison table columns
private List> columns;
//Populates the comparison table rows
private List> rows;

public CarsCompareBean() {
}

public void setSelectedAttributes(List selectedAttributes) {
	this.selectedAttributes = selectedAttributes;
}

public List getSelectedAttributes() {
	return selectedAttributes;
}

public void setShuttleList(List shuttleList) {
	this.shuttleList = shuttleList;
}

public BindingContainer getBindings() {
	return oracle.adf.model.BindingContext.getCurrent().getCurrentBindingsEntry();
}

/**
 * This method will read the attributes from CarsView1
 * and popluate the shuttle component
 * @return
 */
public List getShuttleList() {
	BindingContainer bindings = getBindings();
	OperationBinding operBind = bindings.getOperationBinding("getCompareAttributes");
	List compareAttr = (List)operBind.execute();

	List shuttleList = new ArrayList();
	for (int i = 0; i < compareAttr.size(); i++) {
		CompareAttributes attr = compareAttr.get(i);
		SelectItem item = new SelectItem(attr.getColumnName(), attr.getColumnName(), attr.getColumnAliasName());
		shuttleList.add(item);
	}
	return shuttleList;
}

/**
 * This method will populate the dynamic table
 * @param actionEvent
 */
public void processAction(ActionEvent actionEvent) {
	List selectedCarsKeysList = (List)ADFContext.getCurrent().getPageFlowScope().get("selectedCarsRowKeys");
	BindingContainer bindings = getBindings();
	OperationBinding operBind = bindings.getOperationBinding("populateSelectedRows");
	operBind.getParamsMap().put("carRowKeysList", selectedCarsKeysList);
	operBind.execute();
	
	//Calling the populateDynamicTable
	populateDynamicTable();
}

/**
 * This method will populate the dynamic table based in selected row Objects
 * and attributes selected for comparison
 */
private void populateDynamicTable() {
	List attributes = getSelectedAttributes();
	columns = new ArrayList>();
	rows = new ArrayList>();

	Map column = new HashMap();
	column.put("label", "Cars Name");
	column.put("name", "header");
	columns.add(column);

	for (int i = 0; i < attributes.size(); i++) {
		Map row = new HashMap();
		row.put("header", attributes.get(i).toString());
		row.put("attribute", attributes.get(i).toString());
		rows.add(row);
	}
	DCBindingContainer dcBindings = (DCBindingContainer)getBindings();
	DCIteratorBinding iter = dcBindings.findIteratorBinding("ChildCarsView1Iterator");
	Row[] depts = iter.getAllRowsInRange();
	for (Row dept : depts) {
		column = new HashMap();
		column.put("label", dept.getAttribute("Name").toString());
		column.put("name", dept.getAttribute("Name").toString());
		columns.add(column);
		for (Map trow : rows) {
			trow.put(column.get("name"), dept.getAttribute((String)trow.get("attribute")));
		}
	}

}

public void setColumns(List> columns) {
	this.columns = columns;
}

public List> getColumns() {
	return columns;
}

public void setRows(List> rows) {
	this.rows = rows;
}

public List> getRows() {
	return rows;
}
Last step create a index.jspx page and drop Compare-btf as region into the page.

Friday, June 1, 2012

Bean DataControl - Create new table rows based on existing row content

The Create a Duplicate row enables the user to create an object by duplicating an existing object. The duplication aids the user by prefilling some values. The user has full control and can change any of the values during the creation process. So in this article, I'm will show how can we create new table rows based on existing rows using Bean Data Control.

This can be achieved in BC4J using "Create With Parameters" operation, there is an example written by Frank Nimphius in ADF code corner "How-to declaratively create new table rows based on existing row content".

[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2)]

At runtime page looks like below, you can now select a table row and press the "Copy Row" button. New row will be created by prefilling the selected row values.


Implementations Steps:

There are lot of ways to create a new in an iterator and populate the values from existing row, below I'm showing one of the way to achieve that.

Create Fusion Web Application, create the DeptBean.java and GenericBean.java classes in model project. Open the DeptBean.java and paste the below code.
public class DeptBean {
    private String deptNo;
    private String deptName;
    private String deptLocation;

    public DeptBean() {
        super();
    }

    public DeptBean(String deptNo, String deptName, String deptLocation) {
        this.deptNo = deptNo;
        this.deptName = deptName;
        this.deptLocation = deptLocation;
    }

    public void setDeptNo(String deptNo) {
        this.deptNo = deptNo;
    }

    public String getDeptNo() {
        return deptNo;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptLocation(String deptLocation) {
        this.deptLocation = deptLocation;
    }

    public String getDeptLocation() {
        return deptLocation;
    }
}
Open the GenericBean.java and paste the below code. Here static values are populated to show in result list.
/**
 * Populating Dept static values to DeptBean
 * @return DeptBean list
 */
    public List populateBean() {
        System.out.println("populateBean");
        List deptList = new ArrayList();
        {
            DeptBean dept = new DeptBean("10", "Administrator", "1700");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("20", "Marketing", "1800");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("30", "Purchasing", "1700");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("40", "Human Resource", "2400");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("50", "Shippings", "1500");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("60", "IT", "1400");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("70", "Public Relations", "2700");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("80", "Sales", "2500");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("90", "Executive", "1700");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("100", "Finance", "1700");
            deptList.add(dept);
        }
        {
            DeptBean dept = new DeptBean("110", "Accounting", "1700");
            deptList.add(dept);
        }
        return deptList;
    }

Now right click on GenericBean.java file and generate data control. Open the DataControl.dcx file in application navigator and select the GenericBean. Go to the GenericBean property inspector and set SupportsTransactions as true.

In ViewController project, create index.jspx page and "IndexBean.java". Add the  IndexBean.java file in adfc-config.xml file with scope as viewScope.

Open the IndexBean.java file and paste the below code.
private String deptNo;
private String deptName;
private String deptLocation;

public IndexBean() {
}

public void setDeptNo(String deptNo) {
 this.deptNo = deptNo;
}

public String getDeptNo() {
 return deptNo;
}

public void setDeptName(String deptName) {
 this.deptName = deptName;
}

public String getDeptName() {
 return deptName;
}

public void setDeptLocation(String deptLocation) {
 this.deptLocation = deptLocation;
}

public String getDeptLocation() {
 return deptLocation;
}

public void populateCopyRow(ActionEvent actionEvent) {
 //Executing the Create Method
 BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
 OperationBinding operBind = bindings.getOperationBinding("Create");
 operBind.execute();

 DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
 DCIteratorBinding customIter = dcBindings.findIteratorBinding("populateBeanIterator");
 RowSetIterator customRSIter = customIter.getRowSetIterator();
 //Populating the data to newly created row
 Row currentRow = customRSIter.getCurrentRow();
 System.out.println(this.getDeptName());
 currentRow.setAttribute("deptNo", this.getDeptNo());
 currentRow.setAttribute("deptName", this.getDeptName());
 currentRow.setAttribute("deptLocation", this.getDeptLocation());
}

public void copySelectedRow(SelectionEvent selectionEvent) {
 RowKeySet rks = selectionEvent.getAddedSet();
 if (rks != null) {
  System.out.println("Selected Row:");
  RichTable fowTable = (RichTable)selectionEvent.getComponent();
  Iterator iter = rks.iterator();
  while (iter.hasNext()) {
   fowTable.setRowKey(iter.next());
   FacesCtrlHierNodeBinding rowData = (FacesCtrlHierNodeBinding)fowTable.getRowData();
   this.setDeptNo(rowData.getAttribute("deptNo").toString());
   this.setDeptName(rowData.getAttribute("deptName").toString());
   this.setDeptLocation(rowData.getAttribute("deptLocation").toString());
  }
 }
}
Open the index.jspx page and follow the below steps:

  • From data control palette drag and drop populateBean->DeptBean->Table as ADF Table, set RowSelection as "single". 
  • Surround the Table with af:panelCollection component and  has a toolbar facet to which a a single toolbar button is added to initiate the "Copy Row". The button ID is referenced in the table's "partialTrigger" property so that clicking the button initiates a table refresh
  • Map the "Copy Row" ActionListener to "#{viewScope.IndexBean.populateCopyRow}" 
  • Bind the table selectionListener to "#{viewScope.IndexBean.copySelectedRow}"
  • Go to the page bindings and Create Action Binding as show below.