Please disable your adblock and script blockers to view this page

Search this blog

Showing posts with label prepareRowSetForQuery. Show all posts
Showing posts with label prepareRowSetForQuery. Show all posts

Friday, 16 January 2015

Setting view object bind variable (Override bindParametersForCollection, prepareRowSetForQuery, executeQueryForCollection )

Hello All,
This post is about a very basic question- How to set bind variable of a view object ?
and there are multiple posts about it that describes multiple ways to do this
Using setNamedWhereClause
Using VariableValueManager 
Using setter method in VOImpl class

But Sometimes we can not assign bind variable value in declarative way for first time execution as value source for bind variable is fixed but it's value may change at runtime from n number of events



So for this type of requirement we can set bind variable's value in such a way so that we need not to write code everywhere to set changed value.
See how can we do this -

  • Create a Fusion Web Application and prepare model using Departments table of HR Schema




  • Open Departments viewObject add a bind variable in it's query , this bind variable is further used to set value and filter result set





  • Create Java class for Department view object, goto java tab of Departments VO and click on edit icon of Java Classes and select "Generate ViewObject Class"





  • Now we can set bind variable's value by overriding 3 methods of DepartmentVOImpl class

1. Overriding bindParametersForCollection in ViewObject java class -

This method is used to set bind variable's value by framework, framework supplies an array of all bind variable to this method We can override this method to set value of bind variable ,
Open DepartmentVOImpl class and click on override methods icon on top of editor
It will open a window that consist all methods , search by name and click on ok



See the code in DepartmentVOImpl-


    /**@override Method to set bind variable's value at runtime (Framework Internal Method)
     * @param queryCollection
     * @param object
     * @param preparedStatement
     * @throws SQLException
     */
    protected void bindParametersForCollection(QueryCollection queryCollection, Object[] object,
                                               PreparedStatement preparedStatement) throws SQLException {
        for (Object bindVar : object) {
            // Iterate over bind variable set and find specific bind variable
            if (((Object[])bindVar)[0].toString().equals("BindDeptId")) {
                // set the bind variable's  value
                ((Object[])bindVar)[1] = 100;

            }
        }
        super.bindParametersForCollection(queryCollection, object, preparedStatement);

    }

2. Overriding prepareRowSetForQuery in ViewObject java class -

This method (introduce in 11.1.1.5 release) executes before bindParametersForCollection , same thing can also be done in this method 
Override method in Impl class 


See the Code in DepartmentsVOImpl-


    /**@override Method to prepare RowSet for execution(Framework Internal Method)
     * @param viewRowSetImpl
     */
     public void prepareRowSetForQuery(ViewRowSetImpl viewRowSetImpl) {
        //Set Bind Variable's value 
        viewRowSetImpl.ensureVariableManager().setVariableValue("BindDeptId", 100);
        super.prepareRowSetForQuery(viewRowSetImpl);
    } 

3. Overriding executeQueryForCollection in ViewObject java class -


This method invokes just before framework executes rowset , avoid setting bind varibale in this method because it is not called before some methods as getEstimatedRowCount(), So whenever you try to get rowcount it will return wrong values 
still it works and sets the bind varible value and executes rowset, again override method



See the Code in DepartmentsVOImpl-


    /**Method to excute viewObject rowSet(Framework Internal Method)
     * @param object
     * @param object2
     * @param i
     */
    protected void executeQueryForCollection(Object object, Object[] object2, int i) {
        for (Object bindVar : object2) {
            // Iterate over bind variable set and find specific bind variable
            if (((Object[])bindVar)[0].toString().equals("BindDeptId")) {
                // Set the bind variable value
                ((Object[])bindVar)[1] = 100;

            }
        }
        super.executeQueryForCollection(object, object2, i);
    }

Now use anyone of these methods to set bind variable value and run application module, check result
It is showing data for DepartmentId 100.

Thanks, Happy Learning :)

Wednesday, 13 August 2014

Use View Link Accessor to call aggregate functions, set attribute value , set bind variables value (Oracle ADF)


Hello All

This post is about various usage of view link accessor  , when we create viewLink between two viewObjects , destination accessor is created by default in master viewObject, there is check box to create source accessor also at same time

We can use this view link accessor for calculating attribute's sum, setting value of attributes etc



here Departments is master viewObject and Employees is it's detail, after creating viewLink you can see in viewObject xml source there accessor is present

In Departments ViewObject- 




<ViewLinkAccessor
    Name="Employees"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.RowIterator"
    IsUpdateable="false"/>

In EmployeesViewObject- 
 

<ViewLinkAccessor
    Name="Departments"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.Row"
    Reversed="true"
    IsUpdateable="false"/>

So what is the use of these view link accessors ?
Master accessor in detail viewObject returns current Row of master viewObject, when you generate RowImpl class for detail viewObject , it also has a method for this accessor


    /**
     * Gets the associated <code>Row</code> using master-detail link Departments.
     */
    public Row getDepartments() {
        return (Row) getAttributeInternal(DEPARTMENTS);
    }

    /**
     * Sets the master-detail link Departments between this object and <code>value</code>.
     */
    public void setDepartments(Row value) {
        setAttributeInternal(DEPARTMENTS, value);
    }

Detail accessor in master viewObject returns a row set of all row of details viewObject that are currently referenced by master record

    /**
     * Gets the associated <code>RowIterator</code> using master-detail link Employees.
     */
    public RowIterator getEmployees() {
        return (RowIterator) getAttributeInternal(EMPLOYEES);
    }

Now see what we can do with viewLink Accessor

1. Get master attribute value in detail viewObject

suppose i have to get a attribute's value from Master viewObject (Departments) in a attribute of detail viewObject (Employee)
in this example i am getting managerId from Departments ViewObject so for this just write in expression of Employee's ManagerId field
viewLinkAccesorName.AttributeName


now run BC4J tester and check - create new record in Employee and see managerId from Departments is auto populated

 on creating new record-


2. Call aggregate function to calculate sum of an attribute of detail viewObject

suppose now i have to calculate total salary of a Department (sum of Employees salary of that department)
for this purpose just call sum function to calculate sum of all rows of detail RowSet 
take a transient attribute in Departments ViewObject and write in it's expression
viewLinkAccesorName.sum("AttributeName")


 Run ApplicationModule and see-


3. Set bind variable value as per master viewObject's attribute (pass value from master viewObject)

This  is tricky part as we can not set bind variable value through expression as it doesn't recognize view link accessor name.
created a viewCriteria and bind variable for managerId in Employee viewObject




applied this criteria to Employees viewObject instance in Application Module (Just Shuttle criteria to selected side)


now to set bind variable's value we have to override prepareRowSetForQuery method in Employees VOImpl class

this method gets the value of managerId from currentRow of master ViewObject (Departments)and sets in bind variable of Employees viewObject


    @Override
    public void prepareRowSetForQuery(ViewRowSetImpl viewRowSetImpl) {
        RowSetIterator[] masterRows = viewRowSetImpl.getMasterRowSetIterators();
        if (masterRows != null && masterRows.length > 0 && masterRows[0].getCurrentRow() != null &&
            masterRows[0].getCurrentRow().getAttribute("ManagerId") != null) {
            Integer managerId = (Integer) masterRows[0].getCurrentRow().getAttribute("ManagerId");
            viewRowSetImpl.ensureVariableManager().setVariableValue("BindManagerId", managerId);
            System.out.println("ManagerID in bind Var-" + managerId);

        }
        super.prepareRowSetForQuery(viewRowSetImpl);
    }

now run AM and check it-

Happy Learning :)