Wednesday, November 27, 2013

Application of af:setPropertyListener

The af:setPropertyListener comes very handy when we use af:iterator and need some processing to be done on an event fired by a component within the iterator.

af:iterator dynamically creates the multiple component instances of the component defined within in during design time. If we want to do some processing on event handling of a component instance within that, af:setPropertyListener is very useful.

Consider a scenario where we have a list of booleans to be rendered in a UI page. We can use af:iterator as below:

<af:panelGroupLayout id="pgl8" layout="vertical">
<af:iterator id="i1" value="#{pageFlowScope.accessGroups}"
                                 var="accessGroup">
                  <af:selectBooleanCheckbox text="#{accessGroup.name}"
                                                                value="#{accessGroup.selected}"
                                                                label=""
                                                                id="sbc1" autoSubmit="true"
                                                                disabled="#{ !accessGroup.canModify}"
                                                                rendered="#{accessGroup ne null}"
                                    valueChangeListener="#{myBean.onSelectionChangeOfAccessGroup}">
                        
                            <af:setPropertyListener from="#{accessGroup.name}"
                                                                to="#{requestScope.selChangedAccessGroupName}"
                                                                type="valueChange"/>
                  </af:selectBooleanCheckbox>
</af:panelGroupLayout>

In the above example, the iterator iterates over the collection of booleans accessGroups. As per the layout in which it is contained, we get n checkboxes vertically aligned for n entries in the collection.

If the user wants to change a particular checkbox selection and do some processing on the value change of that checkbox by depending on the instance of accessGroup's other attributes, it is definitely necessary to have a reference of that accessGroup instance which is impossible to to know during the design time. Hence I used setPropertyListener to capture the accessGroup instance into a requestScope variable "selChangedAccessGroupName". I will use this in my event handling logic to do some processing as per the requirement. Sample code shown below.


myBean.java:

public class myBean implements Serializable{
        
             public void onSelectionChangeOfAccessGroup(valueChangeEvent e){
                    AccessGroup ag = ADFContext.getCurrent().getRequestScope().get("selChangedAccessGroupName")

                if(e.getNewValue){
                   // Invoke business service method by passing ag.getName() and e.getNewValue
                }

            }
}

The setPropertyListener from attribute is configured with value to be read and to attribute captures it into a requestScope variable. The type attribute is configured with event when the value need to be captured. This type attribute can be changed to different event types based on the requirement.


Tuesday, November 26, 2013

Testing AM Activation and Passivation

The Application Module activation and passivation phenomenon can't be practically tested with default AM parameters as shown below. This is because the passivation happen only when a fresh AM instance can't be acquired from the pool. The max pool size is 4096 by default.

We can set the parameters to certain values which will enforce the passivation to happen every time a fresh instance of AM is required. The activation will happen when the client which was using the AM instance that got passivated comes back with a request to access AM. 



  Alternatively we can disable application module pooling in which case, regardless of the pool sizes passivation and activation happens everytime an AM instance is requested.


If a user wants passivation to happen everytime an AM instance state is changed, so that in case we have our Application Server in failover mode, we can achieve that by setting jbo.dofailover = true.


Wednesday, November 13, 2013

Implementing Select All in adf table getting the data from a Pojo datacontrol

There is a af table where one of the column has checkbox that enables user to select or deselect. There is no row selection in that table and hence selection of checkbox is  treated as selection of row.

There is checkbox in the column header of that column and on checking that checkbox, I want all the checkboxes in the respective column to be selected and viceversa. This can be achieved by following solution approach.

The table is getting populated by bindings corresponding to a collection in a POJO data control. Below is the code snippet for Pojo DC. The Pojo is chosen here instead of ADF ViewObject because the list of employees is obtained from Session here.

public class myPojoDc{
       private List<Employee> employeeList;

       public List<Employee> getEmployeeList(){
             if(employeeList == null) {
                 prepareEmployeeList();
             }
             return employeeList;
       }

       private void prepareEmployeeList(){
          //Access the list from Session and set it to employeeList.
       }
}

This data control is looked up and the employeeList is dragged and dropped on a ADF jsff form. This creates bindings in pagedef and af:table in the jsff.

Below is the code snippet for value change event handler of selectAll checkbox in the af:table.


    public void handleAccountsSelectAll(ValueChangeEvent ve) {
     
        BindingContainer bindings =
            BindingContext.getCurrent().getCurrentBindingsEntry();
        DCIteratorBinding it =
            (DCIteratorBinding)bindings.get("employeeListIterator");

        RowSetIterator rit = it.getRowSetIterator();
        rit.reset();
        int count = 0;
        if (selectAll != null) {
            if (rit.first() != null) {
                Row r = rit.first();
                r.setAttribute("selected", selectAll);
                if (selectAll) {
                    count++;
                }
            }
            while (rit.hasNext()) {
                Row r = rit.next();
                if (r != null) {
                    r.setAttribute("selected", selectAll);
                    if (selectAll) {
                        count++;
                    }
                }
            }
        }
        //The count here represents the total count selected rows which is nothing but all rows. The count is kept in pageFlowScope so that is used by outputtext located in below to af:table in the jsff.               
        getPageFlowScope().put(respectiveCount, count);
        it.executeQuery();
        //table instance below is obtained by component binding to af:table.
        addPartialTarget(table);
    }