Friday 2 May 2014

ADF : Locking Mechanism in ADF (Find out if a row is Locked or Not)

Hello All,


ADF is primarily designed for developing Enterprise Applications. In an Enterprise Application normally there is more than one user working on the application at a point of time. So it is important to preserve the transaction state of every user. 
ADF  provides Optimistic and Pessimistic locking for maintaining Integrity in the application. 
First, we need to understand what does Optimistic and Pessimistic Locking mean.

1. Pessimistic Locking  : 
In pessimistic locking, when a user modifies an attribute in a row then that row is locked in the database for that user. (The row is locked  until the user commits or rollbacks the transaction.) Any other user trying to acquire the lock on the same row will be forced to wait and will not get the lock until the current user completes his transaction. ( i.e. either he performs Commit or Rollback ). 

Pessimistic locking is used for the Critical Transaction Applications such as Banking Application.
Disadvantage: In Pessimistic locking, the record is locked from the time it is accessed in the transaction until the transaction is complete. This may sometime result in deadlock. For example, if a user edits a record and goes for lunch then the lock is held on the row until he comes back and completes the transaction. In the meantime, no other user will be able to edit the record.

 This is done in the banking application, an account is locked as soon as it is involved in the transaction.

2. Optimistic Locking 
In optimistic locking mode, the lock is acquired at the time of the commit operation performed by the user. That means two users can work on single record simultaneously but at the time of commit only one will be able to commit the record.

In Optimistic locking mode the record is not locked when it is first edited instead the state of the record is saved when it is accessed allowing others to access the record. At commit time the Previously Stored record and the record currently persisting in the database are checked for changes. If the record is changed i.e. the saved record doesn't match the record in the database then the transaction is rollbacked. Otherwise, the record is committed.

For that I have created an ADF Application using the HR Schema.
Here I have created an EntityObject based Employee table. Then created a task flow with two pages search.jsff and detail.jsff.
The search page contains an Employee table and the user edits the current employee details in the details page.
Here is the search the page containing employee table.


When the user clicks on the edit button the corresponding record is available for editing. 


So now when two users try to edit the same record then we have to check for lock and then prompt user with a message.

For doing I have created a method in AMImpl class that checks for the lock on the row.


  public Boolean isRowLocked(){
        ViewObjectImpl employeesView = this.getEmployeesView1();
        Row currentRow = employeesView.getCurrentRow();
        if(currentRow != null){
            try {
                currentRow.lock();
            } catch (Exception e) {
                e.printStackTrace();
                return true;
            }
        }
        return false;
    }

This method tries to lock the current row, if it fails then it means that the row is locked if not then the row is available for editing. When it fails we prompt the user with a message. Here is the code that I have used in the bean.


We have to call the method in the AMImpl in the bean, so for that purpose, I add this method to the AM client interface. Then we can use the code below to check for the record to prompt the message.


    public String editRecordACTION() {
        OperationBinding binding = this.getBindings().getOperationBinding("isRowLocked");
        binding.execute();
        System.out.println("Locked : "+binding.getResult());
        if(binding.getResult().equals((Object)true)){
            FacesMessage msg = new FacesMessage("Sorry, You cannot edit the current record as it is being edited by other user.");
            msg.setSeverity(FacesMessage.SEVERITY_INFO);
            FacesContext.getCurrentInstance().addMessage(null, msg);
            return null;
        }
        return "edit";
    }
    /**Method to get Binding Container*/
    public BindingContainer getBindings() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }


Now running the application on two different browsers to simulate the multiuser environment. When user A clicks to edit the record with employee_id = 199



At the same time if we try to edit the same record in the other browser. Then the message comes.


Now when the user in the first browser commits and returns to the search page  and then the user in the second browser clicks on edit button then he is able to do so as the lock has been released by the first browser.




From http://andrejusb.blogspot.in/2010/03/optimistic-and-pessimistic-locking-in.html

You can download the sample application here: adf.java.codes.rowllock.test.app.rar 

Thursday 1 May 2014

How to get and set Values in SessionScope in ADF

Hello all,

During the development in ADF sometimes we need to define some values in the user session so that it can be used further in the session.

Suppose we need to put the name of the logged-in user in the session to use it further in the application. We can do so by using HttpSession as it is used in a web based java application.

We can access the session from the FacesContext in ADF Application. 
Here is the java code for doing so.

FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)
// false is passed in getSession method to get the already created session
// If true is passed then a new session will be created
context.getExternalContext().getSession(false);
// Here attribute and value are the name and value to the attribute that you want to set in the session.
session.setAttribute("Attribute", value);
// Here attribute is the attribute name whose value you want to fetch

session.getAttribute("Attribute");


Wednesday 23 April 2014

ADF : Working with LOV Switcher

Hello all,

This is a very basic post on LOV switcher implementation.
First , some background information about it.

First we need to understand what happens when a Lov is added to an attribute in ViewObject.

When we add a Lov to an attribute in a ViewObject, a property is added to the attribute

  LOVName="LOV_Name"

and a viewObject instance of the Lov is added to the viewObject. You can see it in the viewAccesors tab to ViewObject. And an entry of list binding is made in the viewObject to represent attribute mapping for the LOV viewObject.
So the question is how the Framework determines if which LOV is added to the attribute,  at runtime ?
At first Framework looks for the property LOVName of the attrribute of the ViewObject then looks for the List binding of the LOV name.

So inorder to switch the LOV on an attribute we just have to change the value of the LOVName in the attribute.Means we need to give it the name of the lov whichever we want to display. LOV switcher basically does the same thing.

So here is an example for the same.
Here I am creating a transient attribute in a Temporary viewObject made from dual and on this attribute we will switch Departments and Employees LOV. I have also created two viewObjects of Department and Employees to use them to make LOV.






First we have to create a Temporary ViewObject with a transient attribute.
Then we will create a transient attribute in which we will put the name of the LOV and then use it will as name of the LOV which needs to be selected.
Here I am naming it as 'LovNameTrans'.


Then we will create two lov on attribute 'LovAttributeTrans'.
Here I have used 'LOVDept' as the name of the LOV.


And again am creating second LOV on the same attribute and named it 'LOVEmp'.


Now the LOV part is over now we have make the switching arrangement.
So now in the 'List of Values Switcher' select the attribute 'LovNameTrans' which will provide the name of the LOV to be switched.

Now create a page and drop the attributes.For assigning values to the 'LovNameTrans' attribute i have created a radio group with static list containing the LOV names.


Make sure the attribute containing the name of teh LOv have the autosubmit property as true on the page as if the value is not submitted then LOV will not be shown. And also use proper partil triggers.

Now run the page. On selecting LOVDept


On selecting LOVDept

Here is the sample workspace used, you can download it from here :LovSwitcherApp

Thursday 17 April 2014

How to scroll a table in oracle ADF with large number of rows in database (>100K rows)?? Resolved!!

Hello ,

There are times in development when we have to show tables with large number of rows to user on the Page. ADF table contains very good property of Scroll which fetches the data from the database when the user scrolls in the table.
This works well when the number of rows in the table is less i.e we can say around 4-5000 without much problem. But the problem begins when we have Thousands or Lacks of rows in the table.

On the default settings when you scroll to the 10000th row then the table fetches all the data upto the 10000th row and then shows the results in the table. When the table starts fetching the 10000 rows in the memory then it takes time , here comes the problem. So if we can reduce this time then we can solve the problem.

Before solving the problem first we need to know why this problem comes into picture.
The problem is that when the user scrolls on the 10000th row, the framework start loading all the 10000 rows in the memory to show on the page, and this takes time.
For avoiding this problem we can customize the setting in ViewObject tuning section.
Go to the Tuning section of any ViewObject, you will see following options .


We have to focus on following properties.

# Retrieve rows from the database : It can be set to :

  1. All Rows (All the rows will be fetch at a time, when the number of rows are large then it takes so much time.)
  2. Only upto row number (Makes sure that only the rows upto the given number are fetched)
  3.  in batches of (It defines the number of rows fetched in one roundTrip to database. Its value depends on the use case but I this case we keep it to n+1, where n is the number of rows to be shown on the page. )
# Access Mode (This is the property to be concerned)
  1. Scrollable : when acess mode is scrollable it means as the user scrolls all the rows upto which user have scrolled will be loaded in the memory before it is shown on the page.
  2. Page Ranging : when the access mode is Page Ranging then when the user scrolls upto some row then only the rows that need to be displayed currently are loaded in to the memory. Let us take an example. Suppose the user scrolls to 10000th row then the RANGE containing row number 10000 will only get loaded into the memory.
So less time needed to load the rows hence table loads faster

# Range size 

It defines the range, We keep the range size to n+1 where n is the number of rows that the user needs to show on the page. 
Range size basically means the number of rows that will be loaded from the viewObject cache to the binding. This is kept to n+1 because if the we don't want more than one round trip to database as if the range size increases the fetch size then an another roundTrip to fetch values in issued.

Also keep the range of the table in sync with the range size of of the table, it helps. 

Sunday 13 April 2014

ADF : Calling Action from ActionEvent Programmatically

Hello all,

During the development sometimes we need to call the "Action" within "ActionListner". That would be when you have to perform a calculation in ActionListner and then decide whether to navigate or not.

Here is the code for doing so


If you have any questions feel free to ask.

Friday 11 April 2014

ADF : Filtering ListOfValues Effectively, Best way to filter an LOV

Hello all,

This is an initial level post, but still thinks can get tricky at times, so i thought of sharing this.

Here I will try to demonstrate how we can filter the values of an LOV effectively.
First we need to know about what happens when an LOV is added on an attribute in a viewObject.

When a LOV is added on an attribute then an instance of the viewObject ( which is used for creating LOV ) is created and that is added to the attribute as an LOV. This instance is attached to the parent viewObject.
Let us take an example,
Suppose we have to show departments in place of department Id in EmployeeViewObject made from Employees Table.
For doing so we will have create a viewObject containing DeptId and DepartmentName, we can name it LovDeptVO. Then we will select the departmentId field in EmployeeViewObject and add LOV and select LovDeptVO viewObject and do attribute mapping , at this time an instance of viewObject LovDeptVO is created and added to EmployeeViewObject. And then you can view the instance of the lov in viewAccessors Tab of EmployeeViewObject.

So now we come to filtering the LOV on somevalues.

There are two cases :

1. Filtering LOV with the attribute present in the same ViewObject.
We have to create a viewCriteria in the lov ViewObject and pass values to bind variables from the viewObject which contains the LOV.
Let us take an example ;

I have created an ADF Applcation with HR Schema.

Then created a temprory viewObject containing two attributes departmentId and EmployeeId.




Then we have to create EmployeeViewObject to make LOV from it.


Now go to Query Tab and create a viewCriteria filtering the LOVEmployeeVo with DeptId. So now LOV viewObject is also complete.

Now we have to make LOV in the EmployeeId in TempVO. Select the EmployeeId attribute go to ListOfValues section and add an lov by clicking add button.

Now we have to pass the selected DepartmentID to LOV so that i can be filtered. So go to the viewAccessors tab in TempVO. You will see the LOV instance there.
Click edit and pass the values. Drag the available viewCriteia to the left and pass the value to the bindVariable.


New Create a page and drop the TempVO as a form. Set Autosubmit value of DepartmentId field to true. And add partial trigger on EmployeeId attribute to refresh the LOV when value of Department changes.



2. Filtering LOV with the attribute present outside the ViewOject i.e. filtering LOV from outside.

So in the above case we had to filter the lov from the attribute from the ViewObject containing Lov, i mean EmployeeId and DepartmentId both fields were in the same ViewObject. How will we filter when we have to filter the LOV on the basis of value coming from a diffferent ViewObject.

For this purpose i created a text field on the page and created a button to filter the LOV.
For that I have created a method in AmImpl and called it in the bean by adding it to client interface.
Method in AMImpl .
And In Bean I have called the Method in AM


On Running the application


When DepartmentId is entered as 10 and filterLov button is clicked



You can download the sample Application here : LovTestApp.rar

Wednesday 9 April 2014

ADF : Programmatic ViewObjects in ADF, Populating programmatic viewObject with an ArrayList

Hello all,

Today I am going to demonstrate about how to make programmatic viewObject in ADF.
There are basically 4 types of viewObjects.

1. ViewObjects based on Entity.
2. ViewObjects based on SqlQuery (also called Readonly viewObject)
3. Static viewObjects (contains fix now of rows)
4. Programmatic viewObjects (Programmatic viewObjects are viewObjects that are not populated from an sql query).

For understanding  the working of programmatic viewObjects, you must first understand the lifecycle of a viewObject. You need to know what methods are called when a viewObject is executed. Here is the sequence of methods that are called when a viewObject is executed.

LIFECYCLE

When a viewObject is called the following methods are executed in the given sequence. 
  • At first when the viewObject is first executed the method first called in the ViewObjectImpl is
    executeQueryForCollection(Object qc, Object[] params, int noUserParams)
    This method executes the Database Query in the viewObject and then calls the next method.

  • After executeQueryForCollection is executed then method hasNextForCollection(Object qc) is called. This method checks if the collection returned have a row or not. If hasNextForCollection(Object qc) returns True then the next method of the lifeCycle is called which converts the row to ADF understandable form i.e. into ViewObjectRowImpl from.

  • So when method hasNextForCollection retuns true then method createRowFromResultSet(Object qc, ResultSet resultSet) is called and this method converts the row into ADF understandable form.

  • This goes on until all the rows are covered and there is no rows left in collection. When there are no rows in the collection then the method hasNextForCollection returns false .

  • Then method setFetchCompleteForCollection(java.lang.Object qc,boolean val) is called and it sets the flag for fetch completion. This indicates that the rows from the collection are fetched.
- See more at: http://adfjavacodes.blogspot.in/2013/12/how-viewobjects-get-executed.html#sthash.whg7AwM9.dpuf

Now create an ADF Application and create a programmatic viewobject



Then press next and define attributes for the viewObject




Generate the following java classes




Click Finish.


Now we have made the viewObject. We will have to override the lifeCycle methods. Here is the code that I have used for this viewObject.


package programmaticvotestapp.model.views;

import java.sql.ResultSet;

import java.util.ArrayList;

import oracle.jbo.Row;
import oracle.jbo.server.ViewObjectImpl;
import oracle.jbo.server.ViewRowImpl;
import oracle.jbo.server.ViewRowSetImpl;

import programmaticvotestapp.model.EmpDC;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Wed Apr 09 14:28:40 IST 2014
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class ProgrammaticVOImpl extends ViewObjectImpl {
    private ArrayList<EmpDC> empList = new ArrayList<EmpDC>(); 
    /**
     * This is the default constructor (do not remove).
     */
    public ProgrammaticVOImpl() {
    }

    /**
     * executeQueryForCollection - overridden for custom java data source support.
     * This method is executed at first.
     * So in this method we need to load our data source . 
     * In simple words initialize the list
     */
    protected void executeQueryForCollection(Object qc, Object[] params, int noUserParams) {
        // Populate the list for the firstTime
        populateArrayList();
        //To set the initial position for fetch to start
        setFetchPosition(qc,0);
        super.executeQueryForCollection(qc, params, noUserParams);
    }

    /**
     * hasNextForCollection - overridden for custom java data source support.
     * This method is called after executeQueryForCollection to check if any row exist in the datasource or not.
     * When returned true, createRowFromResultSet is called and a new row from the rowset is created.
     */
    protected boolean hasNextForCollection(Object qc) {
        return getFetchPosition(qc) < empList.size();
    }

    /**
     * createRowFromResultSet - overridden for custom java data source support.
     * creates a newRow and adds it to viewObject
     */
    protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) {
        int fetchPosition = getFetchPosition(qc);
        System.out.println("Fetch Position is : "+fetchPosition);
        ViewRowImpl newRow = (ViewRowImpl)createNewRowForCollection(qc);
        EmpDC c = empList.get(fetchPosition);
        // Setting value in the new row which is created.
        newRow.setAttribute("EmpId", c.getEmpId());
        newRow.setAttribute("EmpName", c.getEmpName());
        newRow.setAttribute("Salary", c.getSalary());
        // Updating the fetch Position
        setFetchPosition(qc, fetchPosition+1);
        
        return newRow;
    }

    /**
     * getQueryHitCount - overridden for custom java data source support.
     */
    public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
        long value = empList.size();
        return value;
    }
    /**
         * Method to set the new fetch position
         * @param rowset
         * @param position
         * To set the position on the nextRecord to fetch i.e. next record of arrayList
         */
        private void setFetchPosition(Object rowset, int position) {
            if (position == empList.size()-1) {
                setFetchCompleteForCollection(rowset, true);
            }
            setUserDataForCollection(rowset, new Integer(position));
        
    }
    /**
         * Method to get the current fetch position
         * @param rowset
         * @return
         * 
         * This method gets the fetchPosition to fetch the row from the arrayList to retrieve the data
         */
        private int getFetchPosition(Object rowset) {
            int value = ((Integer)getUserDataForCollection(rowset)).intValue();
            return value;
        }
    
    public void populateArrayList(){
        empList.clear();
        empList.add(new EmpDC(1,1100,new StringBuffer("First Employee")));
        empList.add(new EmpDC(2,2100,new StringBuffer("Second Employee")));
        empList.add(new EmpDC(3,1300,new StringBuffer("Third Employee")));
        empList.add(new EmpDC(4,1700,new StringBuffer("Fourth Employee")));
        empList.add(new EmpDC(5,1200,new StringBuffer("Fifth Employee")));
        empList.add(new EmpDC(6,5100,new StringBuffer("Sixth Employee")));
        empList.add(new EmpDC(7,1900,new StringBuffer("Seventh Employee")));
        empList.add(new EmpDC(8,1200,new StringBuffer("Eight Employee")));
        empList.add(new EmpDC(9,1200,new StringBuffer("Ninth Employee")));
        empList.add(new EmpDC(10,1100,new StringBuffer("Tenth Employee")));
    }
}

on running the application you can see



You can download the sample application here ProgrammaticVoApp

Likewise you can use other datasources to populate the programmatic viewObject. The above model shows a very simple implementation, use cases can be much complex.


References :
1 .http://huysmansitt.blogspot.in/2012/08/adf-programmatical-views-made-simple.html?showComment=1397033254692#c2288712975950397947
2 .http://adfjavacodes.blogspot.in/2013/12/how-viewobjects-get-executed.html


Tuesday 8 April 2014

ADF : Making three level dependent LOV (List Of Values)

Hello all,

During the development we often come across a scenario in which we need to filter the List Of Values dependent on other List Of Values. Suppose you want only the cities of the selected country.

Here am about to show how we can make a three level dependent ListOfValues.
I will make a LOV which the user will select a location from locationLOV , then the other departmentLOV will show the department of the selected location, then the user will select a department and the employeeLOV will show the Employees of the selected department.

So, I have created an ADF application and made a connection to HR Schema. Also created three viewObject LovDepartmentVO,LovLocationsVO and LovEmployeeVO to make LOV's.

Now our main purpose is to filter the department on the basis of locations and employees on the basis of department.

For that we have to create a viewCritria in DepartmentsVo to filter departments on the basis of locations.


And then create view criteria for EmployeesVO.


Now we have viewObjects for LOV ready, we need to make a viewObject on whose attributes we will put these lovs.

So here I am creating a query from dual.
And then add three transient attributes as location , department and employees.
Make sure that property "updatable" is true.


Select locationsTrans and go to List of Values and add the lov by selecting LovLocationsVO.
Select departmentTrans and make a lov from lovDepartmentsVO.
Now go to view Accessors tab of the TemporaryVO you will see the lovs added to temporaryVO, now select the lovDepartment and click on edit button.

Select the viewCritera and in the bind value parameters select locationsTrans as value. This will filter the departments Lov on the basis of selecetd location.

Now add the lov on employeesTrans too and then go to viewAccessors select and mapp the bindVarible value to departmentTrans.



Now create am Applicaiton Module and add temporaryVo to AM and create a page and drag all the three attributes in the page and run the application.

Run the page and Select LocationTrans as London, then you will see DepartmentTrans filtered and you will see only 'Humar Resource' department in the lov as it resides in London. And in EmployeeTrans you will see Employees of Selected  department.


Make sure that the all the attribute have their autosubmit attribute to 'true' and attributes are partial trigged on basis of the source.

And the most important thing is that this technique will work on when the three attributes are on the same viewObject.. like in this case is the TemporaryVO.

You can Download the sample from here DependentLovTest.jar

If you have any questions regarding this, feel free to ask.






Monday 7 April 2014

Validator in oracle ADF, Using af:attribute to make validation easy.

Hello all,

This post I will try to focus on how we can make validations in an editable table more effectively.

So what would we do if we have two attributes in a row in a table and we need to validate one on the basis of the other?

The answer is simple.

  • We will get the instance of the viewObject 
  • Then get the current row 
  • Then we will get the attribute with which we need to compare and then we will compare and check the validation.
This process is fine, but i have a more easy and effective way to do so.

I have created a Transient attribute in EmployeeVO where the newSalary of the Employee is to be entered. We have to make sure that the new Salary is greater than old salary.

Drag the EmployeeVO into the page. Then add an af:attribute component in the inputText of newSalaryTrans . Give attribute name and a value here i have used 'oldSal' and assigned with value of old Salary i.e. #{row.Salary}.



Now we need to implement the validation and for that I created a Validator on the NewSalaryTrans field.


In the bean I have used the code given below :


    public void newSalaryVAL(FacesContext facesContext, UIComponent uIComponent, Object object) {
        Object val = uIComponent.getAttributes().get("oldSal");
        System.out.println("New Sal is  : "+object+" Old Sal is  : "+val);
        if(val != null){
            BigDecimal oldVal = (BigDecimal)val;
            BigDecimal newVal = (BigDecimal)object;
             if(oldVal.compareTo(newVal) >=0 ){
                throw new ValidatorException(new FacesMessage("New Salary Cannnot be less than Old Salary!"));
            }
        }
    }

On putting less value in newSalaryTrans



Here is the sample example : NewValidatorTestApp


Friday 4 April 2014

ADF : af:table or adf form or adf page taking too much time to load

During the development sometimes we come across this problem. In our case we had a table on a page and it was taking too much time to load, even though there were only one row in the database table but then also it was taking more than enough time to load. After the analysing the problem finally we were able to solved the problem.

The main problem was with the List of Values with SingleSelection which was inserted in the table. In a column we had to show the name in place of the id, so the developer created a List of Values in the viewObject and put it in the table on page. At first it was working fine but later as the number of rows grown in the List of values the list started taking time to load.

The main cause was the number of rows in the list of values. Single selection list of values matches the id with the value and shows values, so inorder to map it needs all the rows, so whenever the table was being load the ListOfValues started to fetch all the rows, and as the number of rows was too much so abviously it was taking too much time. So, we had to replace the list of values but we also had to show the name in place of id. 

So there are many ways to do that : 

1. We can include the name that we have to display in the query of the table itself, because of which we can simply display it in a column.

2. Otherwise we have to use a viewobject with query that returns a less number of rows and better if it returns one row with the id and DisplayName. 
Suppose we have to show Department Name in place of department id in Employees Table. The query will be something like this : SELECT DEPARTMENT_NAME FROM DEPARTMENTS WHERE DEPARTMENT_ID = :DeptIdBind

And then we need to show the display name so we created a transient attribute.
Then in the getter of the transient attribute, get the viewObject and pass the bindVariables and execute the query. The query will return a row and then we can fetch the name from the view object and show it by returning it.

There is a disadvantage of using this method, as the query is executed for all the rows fetched in the table. But page load problem will be solved. 

This may depend on the use case.  For us both worked well.

I will suggest never to use SingleSelection List of Values that contains large number of rows in the page. Not even on the adf form. Because due to that it will take too much time to load.

Thanks for reading. If you have any question, Please feel free to ask.