maandag 6 augustus 2012

ADF: Programmatical views made simple

Challenge

How do I build a simple programmatical view object in ADF BC? I want to know what action to perform in which method and what the order of execution is of these different methods.

Context

JDeveloper version : 11.1.1.5.0 OS: Windows 7

Solution

We are going to build a programmatical view object based on static values. These are the different steps:

Create the Programmatical View

Launch the "New View Object" wizard
    Fill in the name of the view object and select the "Rows populated programmatically, not based on a query" data source type
    Create the attributes that you need.  Here we only created the primary key (Id) and the name (CountryName) attributes.
    Make sure that you always indicate at least one attribute as "Key Attribute" and also make sure that you put the "Updatable" property to "Always"
    Make sure you create the View Object Class, creating the View Row Class can be handy.  I'm using the View Row class in my example, so I need to generate this one also.

Create the necessary java code to override standard behavior

Here is the complete java code of the AllCountriesViewImpl class:
package model.hr.vo;

import java.sql.ResultSet;

import oracle.jbo.server.ViewObjectImpl;
import oracle.jbo.server.ViewRowImpl;
import oracle.jbo.server.ViewRowSetImpl;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Mon Aug 06 17:47:14 CEST 2012
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class AllCountriesViewImpl extends ViewObjectImpl {
    /**
     * This is the default constructor (do not remove).
     */
    public AllCountriesViewImpl() {
    }
    
    // A simple structure to hold the different countries
    private String[] allCountries;
    

    /**
     * executeQueryForCollection - overridden for custom java data source support.
     */
    protected void executeQueryForCollection(Object qc, Object[] params, int noUserParams) {
        // Initialize the list of countries
        // This can be a call to anything returning your list of countries
        allCountries = new String[5];
        allCountries[0] = "Belgium";
        allCountries[1] = "The Netherlands";
        allCountries[2] = "Germany";
        allCountries[3] = "France";
        // Set the initial position
        setFetchPos(qc, 0);
        // Call the original method implementation
        super.executeQueryForCollection(qc, params, noUserParams);
    }

    /**
     * createRowFromResultSet - overridden for custom java data source support.
     */
    protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) {
        // Get the current fetch position
        int pos = getFetchPos(qc);
        // Create a new row
        AllCountriesViewRowImpl newRow = (AllCountriesViewRowImpl)createNewRowForCollection(qc);
        // Set the necessary fields 
        // This is why you need the RowImpl implementation
        newRow.setId(pos);
        newRow.setCountryName(allCountries[pos]);
        // Change the fetch position
        setFetchPos(qc, pos + 1);
        // Return the newly created row
        return newRow;
    }

    /**
     * hasNextForCollection - overridden for custom java data source support.
     */
    protected boolean hasNextForCollection(Object qc) {
        // Determine wether there are still countries to fetch from the array
        return getFetchPos(qc) < allCountries.length;
    }


    /**
     * getQueryHitCount - overridden for custom java data source support.
     */
    public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
        long value = super.getQueryHitCount(viewRowSet);
        return value;
    }
    
    /**
     * Method to set the new fetch position
     * @param rowset
     * @param pos
     * @writer Filip Huysmans
     */
    private void setFetchPos(Object rowset, int pos) {
        if (pos == allCountries.length) {
            setFetchCompleteForCollection(rowset, true);
        }
        setUserDataForCollection(rowset, new Integer(pos));
    }

    /**
     * Method to get the current fetch position
     * @param rowset
     * @return
     * @writer Filip Huysmans
     */
    private int getFetchPos(Object rowset) {
        int value = ((Integer)getUserDataForCollection(rowset)).intValue();
        return value;
    }

}

The order in which these methods are executed, is:
  1. executeQueryForCollection: this is start of the query. Here you can do your initilizations and the fetching of the values that you need.
  2. createRowFromResultSet: this method will actually create a new row. This method is called for each iteration of the records you have.
  3. hasNextForCollection: this method determines whether there are still rows to be created. If it returns true, the createRowFromResultSet-method will be executed again. If it returns false, the creation of the records will end.
Now you can use this view object to create a table or use it as a LOV for an attribute.

Conclusion

With this simple example you should be able to start working with programmatical views.  This example only focusses on showing information.  There are circumstances where more complicated operations are needed.
I hope this was helpfull for you.

 

References

2 opmerkingen:

  1. Thanks for such a clear explaination..

    BeantwoordenVerwijderen
  2. Hi i tried the above approach
    able to show the data in the UI
    But sorting doesn't work
    On click of sort icon createRowFromResultSet is getting called multiple times
    Did I miss anything ?

    BeantwoordenVerwijderen