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");