ADF

How to populate View Object rows programmatically, without SQL?

I think that first thing beginner ADF developer gets familiar with is bussiness components (BC) and in particular View Objects. Thats the base and main axis of ADF BC. Most common usage is definately Entity or SQL Query based View Objects. But when facing a real world requirements, its not as rare case to build BC on some different kind of data sources. It can be a Ref Cursor out of pl/sql function, POJO, in memory array, Java properties file or even some API i.e. one for Oracle BPM Worklist. Lets build here one tiny sample just to get understanding how things work. Will create programmatic View Object based on simple ArrayList which we just hardcode in the same View Object. Of course in real world you’d need to get data out of somewhere else. But this article is not about this, its about how to create View Object itself.

Assuming that you’re fine with creating ADF Application, Application Modules (AM)View Objects(VO) and adding them to AM, creating .jspx pages, displaying data in there via components you need. In this application we already have set up all of this, will just pay attention to programmatic View Object. Will create as simple as possible EmployeesView with just 3 attributes: id, name, surname. Here are the initial steps we will go through:

  • Create a View Object. Please select Programmatic when you’re asked for a type:

  • Make sure all attributes added to a view object are set as always updatable:

  • Generate EmployeesViewImpl.java and EmployeesViewRowImpl.java source files:

So we did an initial preparation for configuring programmatic View Object. Now lets go to the essence. And it is overriding of EmployeesViewImpl class we just generated. Oracle documentation says, that for fully functioning programmatic VO we need to override these methods:

  • create()

This method is called when the view object instance is created and can be used to initialize any state required by the programmatic view object. At a minimum, this overridden method will contain the following lines to ensure the programmatic view object has no trace of a SQL query related to it:

  • executeQueryForCollection()

This method is called whenever the view object’s query needs to be executed (or re-executed).

  • hasNextForCollection()

This method is called to support the hasNext() method on the row set iterator for a row set created from this view object. Your implementation returns true if you have not yet exhausted the rows to retrieve from your programmatic data source.

  • createRowFromResultSet()

This method is called to populate each row of “fetched” data. Your implementation will call createNewRowForCollection() to create a new blank row and then populateAttributeForRow() to populate each attribute of data for the row.

  • getQueryHitCount()

This method is called to support the getEstimatedRowCount() method. Your implementation returns a count, or estimated count, of the number of rows that will be retrieved by the programmatic view object’s query.

  • protected void releaseUserDataForCollection()

Your code can store and retrieve a user data context object with each row set. This method is called to allow you to release any resources that may be associated with a row set that is being closed.

Lets do what we’re asked for. Here are all of those methods one by one overriden in our sample:

  • create()

/**
* Overriden view object's method.
*/
protected void create() {
super.create();

// Wipe out all traces of a query for this VO
getViewDef().setQuery(null);
getViewDef().setSelectClause(null);
setQuery(null);
}

  • executeQueryForCollection()

/**
* executeQueryForCollection - for custom java data source support.
*/
@Override
protected void executeQueryForCollection(Object qc, Object[] params, int noUserParams) {

Map<String, String> employeeData = new HashMap<String, String>();
employeeList = new ArrayList<Map<String, String>>();

employeeData.put("id", "1");
employeeData.put("name", "John");
employeeData.put("surname", "Miller");
employeeList.add(employeeData);

employeeData = new HashMap<String, String>();
employeeData.put("id", "2");
employeeData.put("name", "Peter");
employeeData.put("surname", "Braun");
employeeList.add(employeeData);

setFetchPos(qc, 0);

super.executeQueryForCollection(qc, params, noUserParams);
}

  • hasNextForCollection()

/**
* hasNextForCollection - for custom java data source support.
*/
@Override
protected boolean hasNextForCollection(Object qc) {

boolean hasNext = getFetchPos(qc) < employeeList.size();

return hasNext;
}

  • createRowFromResultSet()

/**
* createRowFromResultSet - for custom java data source support.
*/
@Override
protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) {

int pos = getFetchPos(qc);

EmployeesViewRowImpl empRow = (EmployeesViewRowImpl) createNewRowForCollection(qc);

empRow.setId(employeeList.get(pos).get("id"));
empRow.setName(employeeList.get(pos).get("name"));
empRow.setSurname(employeeList.get(pos).get("surname"));

setFetchPos(qc, pos + 1);

return empRow;

}

  • getQueryHitCount()

/**
* getQueryHitCount - for custom java data source support.
*/
@Override
public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
long value = super.getQueryHitCount(viewRowSet);
return value;
}

  • protected void releaseUserDataForCollection()

protected void releaseUserDataForCollection(Object qc, Object rs) {
ResultSet udc = (ResultSet) getUserDataForCollection(qc);
if (udc != null) {
try {
udc.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
super.releaseUserDataForCollection(qc, rs);
}

  • Also additionally you might miss here definition of  employeeList, which is private class attribute:

private ArrayList<Map<String, String>> employeeList;

  • And couple of helper methods for setting and retrieving fetching position of view rowset:

private void setFetchPos(Object rowset, int pos) {
if (pos == employeeList.size()) {
setFetchCompleteForCollection(rowset, true);
}
setUserDataForCollection(rowset, new Integer(pos));
}

private int getFetchPos(Object rowset) {
return ((Integer) getUserDataForCollection(rowset)).intValue();
}

Complete sample application can be downloaded here.

If you want to test it live, just deploy to local integrated server and open URL http://localhost:7101/ProgrammaticVODemo/faces/index.jspx  to check records displayed.

For more and official information on how to leverage benefits of programmatic view object, please refer to Oracle Documentation.

ADF Version 12.2.1.0.0

If this post was helpful, please visit an advertisement site! Thank You.


Advertisement

Leave a Reply

Your email address will not be published.