Tuesday, December 3, 2013

Some useful Jdev configurations

Here I am listing out some useful configuration for Jdeveloper

How to change the Jdev user home
 - Goto MW_HOME\jdeveloper\jdev\bin\jdev.boot file  and configure the environment var - "JDEV_USER_HOME" for variable - ide.user.dir.var   and set that env var in the OS Environment variables for the user. Alternatively we can configure the ide.user.dir.var with the hard coded directory path. E.g: C:\myworkspace


How to change Jdev PermGen
 - Goto MW_HOME\jdeveloper\jdev\bin\jdev.conf file,
    change the VMOption - AddVMOption  -XX:MaxPermSize=512M (512M is for example. We can
    set the value as per our requirement)

How to change the heap size for JVM being used by jdev:

- Goto MW_HOME\jdeveloper\jdev\bin\ide.conf and change the Xmx and Xms values as per your requirement.

Monday, December 2, 2013

Preferred Scope for UIComponent bindings

ADF Faces has the feature of binding a UI component with a reference in the managed bean by setting the binding attribute of the component in UI code.

E.g. 
<af:selectBooleanCheckbox label="Select" id="sbc1"   binding="#{managedBean.checkBox}"/> 

Here, the scope of managedBean is very important. Logically speaking, since a UI component is available on a page only until it lasts. Once the page is transitioned, the component in the previous page shouldn't be there and has to be garbage collected. In such scenario, if we are referring the UI component by a reference sitting in a managed bean defined at scope higher than the View scope, it can't be garbage collected thereby increasing the memory footprint. So to avoid this, we need to refer the UI component only from managed beans at scopes - View/Request/Backingbean. The request scope and backingbean scope is justified because it lasts until the page is transitioned and response is sent back to client and often we need to execute some logic in the code behind with the help of UI component reference.

Suppose you have a taskflow that has only one page in it. Can you now use the reference in managed bean defined at taskflow scope to bind the UI components in the only page of that taskflow. Well, from memory management perspective its okay as the pageflow scope here is almost equal to backingBean scope or requestScope because a page transition here will always lead to exit of the current taskflow thereby clearing the pageflow scope. But still this is not acceptable. Lets see why it is so.
 
When your application works in a cluster environment in the high-availability mode (actually, this is not the only case) the session with all memory scopes higher than request might be serialized in order to be restored on a different JVM instance. UIComponent (The super class of all ADF/JSF Components)  is not a serializable class, and you are going to get a serialization exception in case of binding components to the long-living managed beans.

So, in a nutshell, the preferred scopes for UI component bindings are - View Scope/BackingBean/RequestScope.

Commit Execution process of ADF Entity objects

When a creation or updation or deletion of a row happens in ADF VO, the corresponding actual  operations happen against the respective underlying entity instance. When a commit is initiated, the entity instance posts the changes to database and commits them. Below are the steps involved in transaction commit process.

Step1: When commit is initiated on the AM that contains the VO on which create/update/delete operations are done, The transaction manager starts the post cycle of all the entity instances which are dirty(either created/updated/deleted).  Below steps are executed for each dirty entity instance.

- Validation of business data is triggered.  (Entity level validations). EntityImpl::validateEntity()
- EntityImpl::postChanges(...) method is invoke which in turn invokes below methods.
  • EntityImpl::lock() : Locks the row.    
  • EntityImpl::prepareForDML(...) : A pre-notification for preparing rows for posting to DB.        If you need to update some dependency columns or custom history columns then this is the place to add that logic.
  • EntityImpl::doDML(...) : Performs INSERT/UPDATE/DELETE processing for the row.
  Once the postChanges of a dirty entity instance is completed, the following methods gets invoked
  • EntityImpl::beforeCommit(...) : Reports that a commit operation has initiated
  • EntityImpl::afterCommit(...) : Reports that a successful commit operation has occurred

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

Monday, October 28, 2013

Showing Modified rows in a table using filtering feature

I came across a requirement where a table having a list of employee entities. The table is not a updatable table. So each row is modified by a form that comes up in a dialog on selecting a row. A new row is created on clicking + icon in the table toolbar. This table has filtering enabled. I have a flag "Show only to be submitted entities". On selecting the checkbox corresponding to that flag, the table should show only the newly added or modified rows.

To achieve this, I followed a simple approach of using filtering. Firstly I maintained a transient attribute in the entity which is a plain string and is updated on every new row creation or modification. I call that attribute a marker and the values are (N) for newly newly added ones and (M) for modified ones. On clicking the "Show only to be submitted entities"checkbox, I am populating a filter criteria saying marker startswith "(". Then queued the queryevent. This table has filtering enabled. So I also ensured that the existing filters are not disturbed. The "showOnlyToSubmitEntities" is boolean flag that preserves the selection of "Show only to be submitted entities" checkbox. If it is selected, the filter criteria is applied with marker added to it. Else it is removed.

Queuing event on selecting checkbox: (getTable() method returns the binding of the RichTable)

                  FilterableQueryDescriptor queryDescriptor =
                        (FilterableQueryDescriptor)getTable().getFilterModel();
                  getTable().queueEvent(new QueryEvent(getTable(), queryDescriptor));
----------------------------------------------------------------------------------------------------------------------

Handling the query event:

          FilterableQueryDescriptor fqd =
              (FilterableQueryDescriptor)queryEvent.getDescriptor();
          Iterator itr = null;

          if (showOnlyToSubmitEntities != null && showOnlyToSubmitEntities) {
              fqd.getFilterCriteria().put("marker", "(");
          } else {
              itr = fqd.getFilterCriteria().entrySet().iterator();
              while (itr.hasNext()) {
                  if (((Map.Entry)itr.next()).getKey().equals("legend")) {
                      itr.remove();
                  }
              }
          }

          ADFUtil.invokeEL(el, new Class[] { QueryEvent.class },
                           new Object[] { queryEvent });

Thursday, October 24, 2013

some best practices



The ADF Framework promotes the MVC pattern through the use of a well defined view, controller and model layers. The view layer is the JSPX fragments and associated backing bean code, the controller is the binding layer (ADFc) and the model is the business layer, typically ADF BC. A central tenet of the MVC pattern is that view and model communication is orchestrated by the controller layer. 

In some implementations, the backing bean code often directly invokes the Business tier directly without using the binding layer. The end result of this is a tight coupling between the view and model layer, where changes to the model layer could easily break the view layer code.Such implementation is also at risk since the benefits of the controller layer like contextual events, or deferred execution cannot now be performed. This also makes the code difficult to customize and change later.

Recommendation:
Re-factor the view layer code to use the binding layer. The view layer code should not directly invoke business methods, bypassing the ADF controller or the binding layer.

For example if you need to use any method define inside the applicationModule class, DON’T make a reference of the applicationModule in your code instead bind this method to the page and use the below code to access it:

         BindingContainer bindings =BindingContext.getCurrent().getCurrentBindingsEntry();
         OperationBinding submitTable = bindings.getOperationBinding("OperationName");
         submitTable.getParamsMap().put( "Parameters" , "data" );
         submitTable.execute();

---------------------------------


Best Practice for iterating over View Object rows
Create a secondary RowSetIterator if the business logic needs to iterate over rows of view. Note that the default RowSetIterator is typically bound to the UI components and use of it in
business logic will give inconsistent results at runtime. Call closeRowSetIterator() on the RowSetIterator instance once the business logic is done with the iteration. An example would be as follows:
public void checkAllPolicies() {
RowSetIterator policyRSI = null;
try {
ViewObject vo = findViewObject("PolicyVO");
vo.setNamedWhereClauseParam("policyNumber", getPolicyNumber());
vo.executeQuery();
//Create secondary row set iterator
policyRSI = vo.createRowSetIterator("customRowSet");
while (policyRSI.hasNext()) {
Row policyRow = policyRSI.next();
// -- business logic
}
} finally {
//Close the secondary row set iterator
if (policyRSI!= null)
policyRSI.closeRowSetIterator();
}
}


When iterating over view objects that are also used in the UI, the access mode can be set programmatically at runtime. You can restore the original access mode later based on the use case. The advantage of doing this programmatically is that you can use the forward-only mode only when needed, while other users of the view object, like the UI, will not be affected.
public void iteratePolicyVO() {
ViewObject vo = findViewObject("PolicyVO");
byte origMode = empVO.getAccessMode();
vo.setNamedWhereClauseParam("policyNumber", getPolicyNumber());
//Set access mode to FORWARD_ONLY
empVO.setAccessMode(ViewObject.FORWARD_ONLY);
vo.executeQuery();
while (vo.hasNext()) {
Row policyRow = vo.next();
// -- Business logic
}
//Restore the access mode
empVO.setAccessMode(origMode);
}
  ----------------------------------------------------------

Please make sure that you take care of the following in your code.

1      All the beans that you use in your code irrespective of the scope should implement searializable.
2      As a best practice for ADF, try as much as you can to not use binding for the UIcomponent and if you really need to use it, don’t use it in a memory scope more than Request or Back bean
scope. UIcomponent binding is only valid in request scope and backing bean scope. UIComponents are non-serializable, and therefore cannot be stored into any memory that would cause them to live longer than one request. If you need to keep a reference to a component longer than that you may use a component reference.

Please check the below link:

See “2.6.3 What You May Need to Know About Component Bindings and Managed Beans”

        Review your code and make sure you do the following:

1      Remove UIComponent Binding if there is a alternative way to do the same logic
2      If you must use it, make sure that you don’t use UIComponent bindings in beans that live longer than request scope and backing bean scope.
3      This is the last option. In case you have used component binding in beans with scope higher than request scope and backing bean scope, you can use  the component reference API to make the UI component also searializable.