16 Dec 2012

Building custom where clauses for view criterias

In this post I'm going to show how we can generate custom where clauses for VO's view criterias. Let's consider some example. We have a simple view object:

The ViewObject has a couple of view criterias - Today and Yesterday. We're going to use them in an effort to filter orders submitted today and yesterday correspondingly. Note, that view criterias are absolutely empty:


And we are going to generate where clauses for them manually. The ViewObjectImpl class has a special extension point for cases like this one. We're going to override getCriteriaAdapter() method. The method should return some implementation of CriteriaAdapter interface. By default, the method returns null and the framework takes care of building where clauses in a standard way.
So, our implementation of CriteriaAdapter interface is going to look like this:

public class CustomCriteriaAdapter implements CriteriaAdapter
{

  private static String TODAY_CRITERIA = "Today";
  private static String YESTERDAY_CRITERIA = "Yesterday";


  @Override
  public String getCriteriaClause(ViewCriteria criteria)
  {
    if (criteria.getName().equals(TODAY_CRITERIA)) 
      return "Orderdate = trunc(sysdate)";
    else
      if (criteria.getName().equals(YESTERDAY_CRITERIA))
        return "Orderdate = trunc(sysdate-1)";
       else
         return null;     
  }



And let's return this adapter in getCriteriaAdapter() method of our ViewObjectImpl class:

  private static CustomCriteriaAdapter CUSTOM_CRITERIA_ADAPTER 
    = new CustomCriteriaAdapter();

  public CriteriaAdapter getCriteriaAdapter()
  {
     return CUSTOM_CRITERIA_ADAPTER;
  }


Actually, that's it. For the use-case above this is enough. But what about using Today and Yesterday criterias as nested ones? For example, we have a view criteria containing the Today VC:


In this case our approach will not work. The method getCriteriaClause(ViewCriteria criteria) is going to be invoked by the framework only once per root view criteria. So, in our case, it's going to be invoked for TodayCriteria only.
Let's extend standard CriteriaAdapterImpl class and override getCriteriaClause(AttributeDef[] attrDefs, ViewCriteria criteria) method. This method is going to be invoked recursively for each nested view criteria and view criteria usage. And our implementation of this method is going to look like this:

public class CustomCriteriaAdapter extends CriteriaAdapterImpl 
implements CriteriaAdapter
{

  private static String TODAY_CRITERIA = "Today";
  private static String YESTERDAY_CRITERIA = "Yesterday";

  @Override
  protected String getCriteriaClause(AttributeDef[] attrDefs, 
                                     ViewCriteria criteria) 
  {
    String whereClause = null;
    if (criteria.getName().equals(TODAY_CRITERIA)) 
      whereClause = "Orderdate = trunc(sysdate)";
    else
      if (criteria.getName().equals(YESTERDAY_CRITERIA))
        whereClause = "Orderdate = trunc(sysdate-1)";
       else
         //Let the framework to do the job in all other cases
         whereClause = super.getCriteriaClause(attrDefs, criteria);    
    return whereClause;
  }


That's it!




9 Dec 2012

Managed Bean Scopes for Component Binding

Everybody knows that JSF UI components can be bound to some managed bean property using component's binding attribute. Like this:

<af:selectBooleanCheckbox label="CheckBox" id="sbc2"
                  binding="#{BindingBean.checkBox}"/>

And in the managed bean java code we can work with this property in a convenient way. But there are some dangerous underwater rocks connected to this feature. The ground for these rocks is hidden in the scope of the managed beans. There are lots of various posts and book articles with strong recommendations not to use managed beans for component bindings with lifespan longer than request. And they are right.
Why? The first reason is serialization. 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 an order to be restored on a different JVM instance. UIComponent 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. Someone can say - "Ok, that's not an issue, I don't use high-availability mode at all, moreover I can mark my managed bean property as a transient one and avoid exceptions in case of an unexpected serialization". But there is one much more dangerous rock in this shallow water. This is memory usage. In a normal healthy JSF application UI component tree built for a view is a weakly reachable object between requests. So, it can be easily collected by the garbage collector if the application server decides to free some memory according to the GC policy. Actually, in most cases GC policy is going to be specially tuned to maintain JSF applications in the best way. It's going to be tuned to work with a big number of short living objects. A property in your managed bean is a hard reference and it prevents the entire UI component tree to be collected by GC when it's really needed. So, the UI component tree is going to eat your memory as long as the manged bean is going to live. Who knows how long will it take? And now multiply this problem by a number of simultaneously working users of your system, used to just close browsers when they are going for lunch.
Off-course, we can play with weak and soft references in our managed beans for the component bindings, but I'm not sure whether our JSF framework can cope with that. Actually, there is one standard solution working in a similar way. But a bit later about that.
 
"All right" - someone can say. "I got it. I will use only request or backingbean scopes for the component binding."

But be careful at this point!!! Think about what exactly you are going to do in your request scoped beans. There is another very dangerous rock on your way to the happy future.

Let's consider an example with a TaskFlow like this one:
At each view we have two identical components - a button and a checkBox:

<af:commandButton text="Set selected" id="cb1"
                  actionListener="#{viewScope.BackingBean.button_actionListener}"
                  partialSubmit="true"/>
<af:selectBooleanCheckbox label="CheckBox" id="sbc2"
                          binding="#{viewScope.BackingBean.checkBox}"/>


Note, that the checkBox is bound to the viewScope managed bean property. We have two views in the task flow, so we expect two different instances of the managed bean.  Let's have a look at the button's action listener:

  public void button_actionListener(ActionEvent actionEvent)
  {
    checkBox.setValue(Boolean.TRUE);
    RequestContext.getCurrentInstance().addPartialTarget(checkBox);
  }

It's very simple. We're making the checkBox selected and add it as a partial target to be rerendered.
Let's check how it works. Start the taskflow:


Press "Set selected":

Press "Go":

And we can see, that everything is ok. On the second view the CheckBox is unselected again. It's bound to the second instance of the managed bean.
And now, after reading this post and many others, we've got aware of problems connected to the component bindning using long-living beans and decided to use a request scope bean. Let's change the scope of our BackingBean to request and run the same application:



Press "Set selected":

And press "Go":
Ooops!!! The checkBox on the second view is selected. The explanation is very simple - the checkBox is bound to the same instance of the BackingBean. We cannot have two instances of the request scope bean during one request. Changing the scope to the backingBeanScope will not solve the issue. We are going to get the same wrong behavior. We cannot have two instances of the backingBean scope bean during one request in one region (except declarative components).
So, how to fix it?
As I mentioned before, there is some standard solution which allows us to use components references in long-living managed beans. You can read more about ComponentReference here.
But unfortunately this class is available starting from JDev 11.1.1.4.0 only.
So, the most common and reliable solution is to do some refactoring. We are going store the state of our components (in our case "selected" state of the check box) in a view scope bean and we are going to bind components (if really need that) in a request scope bean.
So, we have two managed beans:

<managed-bean id="__3">
  <managed-bean-name>BackingBean</managed-bean-name>
  <managed-bean-class>com.cs.blog.mbean.view.BackingBean</managed-bean-class>
  <managed-bean-scope>view</managed-bean-scope>
</managed-bean>
    
<managed-bean id="__31">
  <managed-bean-name>BindingBean</managed-bean-name>
  <managed-bean-class>com.cs.blog.mbean.view.BindingBean</managed-bean-class>
  <managed-bean-scope>view</managed-bean-scope>
  <managed-property id="__4">
  <property-name>backingBean</property-name>
     <property-class>com.cs.blog.mbean.view.BackingBean</property-class>
     <value>#{viewScope.BackingBean}</value>
  </managed-property>
</managed-bean>
  
BackingBean is a view scope bean and it's going to be injected into a request scope bean BindingBean as a property. This BindingBean we are going to use for the component binding:

<af:commandButton text="Set selected" id="cb1"
                  actionListener="#{BindingBean.button_actionListener}"
                  partialSubmit="true"/>
<af:selectBooleanCheckbox label="CheckBox" id="sbc2"
                  value="#{viewScope.BackingBean.selected}"
                  binding="#{BindingBean.checkBox}"/>


Note, that the value (state) of the checkBox is going to be read from the view scope bean.  And now let's have a look at the action listener:

  public void button_actionListener(ActionEvent actionEvent)
  {
    backingBean.setSelected(Boolean.TRUE);
    RequestContext.getCurrentInstance().addPartialTarget(checkBox);
  }


So, we are changing the value of the injected view scope bean (which is going to be read by the checkBox) and refreshing the component.

That's it!

28 Oct 2012

Deep Dive into Oracle ADF. Advanced Techniques.

In this post I would like to thank everyone, who managed to attend my session "Deep Dive into Oracle ADF. Advanced Techniques." at Oracle Open World 2012. Special thanks to those guys, who came to Marriott Marquis Golden Gate C2 on the last day of the conference not only to listen to me, and, perhaps, to learn something new, but to support me as well. It was my first (I hope not last :)) experience as a speaker at Oracle Open World.

I promised at the session that the presentation as well as the sample application would be available for download. You can download the presentation from the Oracle Content Catalog or you can use one of the following links:
  http://adf-practice.googlecode.com/files/CON5623_PDF_5623_001.pdf
  http://www.slideshare.net/euegenefedorenko/con5623-pdf-5623001


The sample application can be downloaded here. It requires some database objects created in your database and necessary SQL scripts are included in the application. The application is developed using JDeveloper 11g R2 11.1.2.1.0. So, fill free to use and modify the source code and provided techniques to meet your own requirements.  

Enjoy!

23 Sept 2012

Dynamic view criterias from where clauses

Let's consider a use-case when a system administrator or a business administrator or even a user can define some user-filters. These user filters are going to be stored in some storage, for example a database, and at run-time an end user can apply these filters to their data in UI. These filters contain just simple Where SQL clauses. For example, we have in the application some entity "Boats" and it has some predefined user filters:

It would be cool to dynamically create and add View Criterias to the VO definition and to work with them in a usual way. For example, we could use standard af:query component, where a user can select a criteria from the list and apply it to the data in a table. But the question is: how to create View Criterias having only simple where clause strings?
A View Criteria consists of view criteria rows, and a view criteria row consists of view criteria items, and a view criteria item consists of a view object attribute, an operation type like equal, less, like or whatever and an operand, literal or bind variable. The framework at run-time generates appropriate where clauses from these criteria items and applies them to the SQL query. But we don’t have all these cool things – an attribute, an operation type and an operand, we just have a where clause string and nothing else.
The trick is to put this string into the value property of the view criteria item and override a view object method getCriteriaItemClause responsible for generating a where clause from a view criteria item:

   @Override
  public String getCriteriaItemClause(ViewCriteriaItem crieriaItem) {
      return (String) crieriaItem.getValue(); 
   }  

The method is just going to return back a criteria item’s value. And we can add a method to the custom ViewDefImpl class:

    private void createViewCriterias(RowIterator userFilters){
      while (userFilters.hasNext()) {
        VAgileEntityFilterRowImpl userFilter = (VAgileEntityFilterRowImpl) userFilters.next();
        //Create a View Criteria
        ViewCriteriaImpl viewCriteria =  (ViewCriteriaImpl) createViewCriteria();
        viewCriteria.setName(userFilter.getName());
        
        //Create a View Criteria Row
        ViewCriteriaRow vcr = viewCriteria.createViewCriteriaRow();
        
        //Get the first attribute from the VO's attribute list
        String firstAttributeName = getAttributeDef(0).getName();
        //And create a View Criteria Item for this attribute
        ViewCriteriaItem vci = new ViewCriteriaItem(firstAttributeName, vcr);
        
        //Set the Where clause string as a value of the 
        //View Criteria Item instance
        vci.setValue(userFilter.getWhereclause());
        
        //Add the View Criteria Item instance to the View Criteria Row
        vcr.addCriteriaItem(firstAttributeName, vci);        
        
        //Add the View Criteria Row instance to the View Criteria
        viewCriteria.add(vcr);
            
        //Add the View Criteria instance to the View Definition
        putViewCriteria(viewCriteria.getName(), viewCriteria);
        
      }
    }
 
A View Criteria Item can be created for some VO's attribute only. But we’ve overridden generating of a where clause from a view criteria item. So, it doesn't matter for which particular attribute it's going to be created.  Therefore, we can just take the first attribute from the list and pass it to the ViewCriteriaItem constructor. Actually, that's it. And now we can work with these View Criterias in a usual way.

22 Sept 2012

Dynamic iterator binding and method action call

In my previous post I mentioned that we can use dynamic binding approach in an effort to get the VO instance name evaluated dynamically at run-time. So, in the PageDef file we can have the following definition:


<iterator Binds="#{someViewObjectName}" RangeSize="25"   
               DataControl="AgileDataModelServiceDataControl"  
               id="VAgileIterator"/>



And EL #{someViewObjectName} is going to be evaluated as a name of some view object instance in the AgileDataModelService application module. And let's assume that any VO instance, which name is evaluated by the EL expression, inherits some parent view object VAgile. And its implementation class VAgileImpl contains some public method returning a String:

    public String getSomeString() {
        return ...;
    }


We're going to publish this method in VO's client interface and make it invokable from the UI via  binding layer. So, we're going to define a methodAction in the PageDef file in order to invoke the method for the particular VO instance, which name is going to be evaluated by the #{someViewObjectName} EL expression:

<methodAction id="getSomeString" RequiresUpdateModel="true"
              Action="invokeMethod" MethodName="getSomeString"
              IsViewObjectMethod="true"
              DataControl="AgileMetaDataModelServiceDataControl"
              InstanceName="???"
              ReturnName="data.AgileMetaDataModelServiceDataControl.methodResults.getSomeString_AgileMetaDataModelServiceDataControl_VAgile_getSomeString_result"/>

But a methodAction definition has an InstanceName attribute, supposed to contain a name of the particular VO instance. Since we're using the dynamic iterator binding approach, we don't know the instance name, it's going to be evaluated at run time by the EL expression. Unfortunately we can't use EL expressions in the Instance attribute. The workaround is to use an iterator bindings VAgileIterator to get the instance of the VO. So we can do the following:

<methodAction id="getSomeString" RequiresUpdateModel="true"
              Action="invokeMethod" MethodName="getSomeString"
              IsViewObjectMethod="false"
              DataControl="AgileMetaDataModelServiceDataControl"
              InstanceName="bindings.VAgileIterator.viewObject"
              ReturnName="data.AgileMetaDataModelServiceDataControl.methodResults.getSomeString_AgileMetaDataModelServiceDataControl_VAgile_getSomeString_result"/>

Have a note, that we used bindings.VAgileIterator.viewObject in the InstanceName attribute and the IsViewObjectMethod attribute is false. Actually, that's it. It works.

19 Aug 2012

Hand made dynamic form

There is some interesting component we can use in the UI whenever we need to get input controls rendered dynamically, on the fly.  This is dynamic:form. I really love it, because it's quiet unpretentious and stable. This feature can be extremely useful in use-cases where we have a user page, supposed to render a row of some dynamically created view object. The page is going to be universal one. It has no idea about what particular view object is providing the data. Any dynamically created view object can be accepted as a datasource. For example, in the PageDef file we have the following iterator definition:

<iterator Binds="#{someViewObjectName}" RangeSize="25" 
               DataControl="AgileDataModelServiceDataControl"
               id="VAgileIterator"/>


Notice, that we used dynamic binding approach. The EL #{someViewObjectName} is going to be evaluated as a name of some view object instance in the AgileDataModelService application module. It could be either dynamic VO or static VO, actually it doesn't matter. And we put on the page a dynamic form:

<dynamic:form value="#{bindings.VAgileIterator}" id="f1"/>

And that's it. It works! The result looks like this:


The magic is that we don't have any attribute bindings in the PageDef file. The dynamic form creates all necessary bindings itself at runtime. That's why I sad that dynamic:form is unpretentious component. It requires an iterator binding only.
So, the  dynamic:form component is perfect. But it has some limitations as well. The attributes within dynamic form are going to be rendered in a straight forward way using standard controls derived from the model layer. We can break through the limitations and build our custom, let’s say hand made, implementation of a dynamic form, just using “iterator + switcher” approach. In this case we have a full control of how attributes are being rendered and we are free to use our custom components. For example, a declarative component would be more suitable to represent some complex data structure. But the question is what should be provided as a model for these components? Since we represent the data from a dynamic view object with an arbitrary set of attributes, we don’t have any attribute bindings in the PageDef file. Of course, we could implement some model in a backing bean working with View Object Row directly, but that’s not feng shui. It’s preferable to work with business components model through the bindings layer.
The solution is to ask the framework for help.

We can define in the PageDef file a tree binding with an empty node definition inside it:

<tree IterBinding="VAgileIterator" id="VAgile">
     <nodeDefinition Name="VAgile0" DefName=""/>
</tree>


The trick is to define an empty node definition. It doesn't refer to any view object definition. In this case the framework is going to automatically at runtime investigate the view definition structure including all necessary attributes according to the view object instance specified in the iterator binding. So, at runtime, the framework will build JUCtrlHierNodeBindings for each row according to the attributes of the View Object specified in the iterator bindings.

We're going to use this feature and feed control value bindings, kindly prepared for us by the framework to the components within af:iterator. So, we have a construction like this one:

 <af:iterator value=“#{backingBean.controlList}" var="bind" id="dc_i1">
    <af:switcher id="dc_s1" facetName="#{bind.hints.AgileTypeID}" 
                 defaultFacet="Default">
       <f:facet name="DATE">
          <af:inputDate id="dc_id1"
             label="#{bind.hints.label}”                                 
             value="#{bind.inputValue}”                              
             required="#{bind.hints.mandatory}"
             columns="#{bind.hints.displayWidth}"
             shortDesc="#{bind.hints.tooltip}"/>
        </f:facet>

     …


And we have a method in a backing bean, returning the list of control value bindings (JUCtrlValueBindings):

 private List<JUCtrlValueBinding> getControlList() {
   //Find current bindning container
   DCBindingContainer bindingContainer = 
     (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
   //Find VAgile tree binding   
   JUCtrlHierBinding treeBinding = 
     (JUCtrlHierBinding) bindingContainer.findCtrlBinding("VAgile");

   //Find node binding for the current row of VAgileIterator iterator
   DCIteratorBinding iterator =
      bindingContainer.findIteratorBinding("VAgileIterator");
   Row currentRow = iterator.getCurrentRow();
   JUCtrlHierNodeBinding rowBinding = 
   treeBinding.findNodeByKeyPath(Arrays.asList(new Key[]{currentRow.getKey()}));

   //Resolve it's binding container. 
   //The framework filled it up with attribute bindings
   DCBindingContainer agileContainer = 
     (DCBindingContainer)rowBinding.getBindings();  

   //And build the list
   List<JUCtrlValueBinding> controlList = new ArrayList();
   for (AttributeDef attr: iterator.getAttributeDefs()) {
     JUCtrlValueBinding ctrlBinding = 
       (JUCtrlValueBinding) agileContainer.findCtrlBinding(attr.getName());
     controlList.add(ctrlBinding); 
   }  
   return controlList;
 }

Have a look at the "bind" variable in the af:iterator definition. This is an instance of JUCtrlValueBinding and it can be used in EL expressions as usual #{bindings.} variable in the way we're used to.

That's it!


29 Jul 2012

Resource bundle for dynamic view object

We can use ADF BC API to create dynamic view objects at run-time and present the data in UI with dynamic:table, dynamic:form, "forEach" or with any other approach. The question is: how to setup correct UI hints for the VO's attributes?
The example below creates a dynamic VO VEmployees:
     String queryStmt = "select Employee_ID,  Last_Name from Employees";
     vo = createViewObjectFromQueryStmt("VEmployees", queryStmt);

By default labels of the query fields are equal to the field names. Of course, we can set the labels directly:
     AttributeDefImpl at = (AttributeDefImpl) vo.getAttributeDef(0);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL, "Unique ID");

     at = (AttributeDefImpl) vo.getAttributeDef(1);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL, "Last Name");
 
We can do even more. Let's take care of the locale:
     AttributeDefImpl at = (AttributeDefImpl) vo.getAttributeDef(0);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL, "Unique ID");
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL+"_ukr_UA", "Iдентiфiкатор");

     at = (AttributeDefImpl) vo.getAttributeDef(1);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL, "Last Name");
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL+"_ukr_UA", "Прiзвище");     


But what if we want to store UI hints in a resource bundle file (or files for different locales)? Instead of setting some value for the label directly, we have to set resource ID and set particular resource bundle for the VO's ViewDef. In the following example we call getResourceBundleDef() method to get the resource bundle of the current Application Module. This is a common practice to have one bundle per project.
     AttributeDefImpl at = (AttributeDefImpl) vo.getAttributeDef(0);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL +"_ResId", 
                    "VEmployees.Id_LABEL");

     at = (AttributeDefImpl) vo.getAttributeDef(1);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL +"_ResId", 
                    "VEmployees.LastName_LABEL");

     ViewDefImpl viewDef = (ViewDefImpl) ((ViewObjectImpl) vo).getDef();
     viewDef.setResourceBundleDef(getResourceBundleDef());

The resource bundle properties file has the following fragment:
VEmployees.Id_LABEL=Unique ID
VEmployees.LastName_LABEL=Last Name

In order to use a separate properties file or, probably, we want to implement our custom resource bundle, retrieving resources from let's say a database, we have to create a resource bundle definition ourselves:
     AttributeDefImpl at = (AttributeDefImpl) vo.getAttributeDef(0);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL +"_ResId", 
                    "VEmployees.Id_LABEL");

     at = (AttributeDefImpl) vo.getAttributeDef(1);
     at.setProperty(AttributeDefImpl.ATTRIBUTE_LABEL +"_ResId", 
                    "VEmployees.LastName_LABEL");

     ViewDefImpl viewDef = (ViewDefImpl) ((ViewObjectImpl) vo).getDef();
     //Create custom properties bundle definition
     PropertiesBundleDef rb = new PropertiesBundleDef(viewDef);
     rb.setPropertiesFile("com.cs.blog.dynamicbundle.model.VEmployeesBundle");
     
     viewDef.setResourceBundleDef(rb);

 
That's it!

21 Jul 2012

Read-only ViewObject and Declarative SQL mode

Introduction
The declarative SQL mode is considered to be one of the most valuable advantages of the entity-based view objects. In this mode the VO's SQL is generated at runtime depending on the attributes showed in UI. For example, if some page contains a table with only two columns EmployeeId and FirstName, then the query will be generated as "select  Employee_ID, First_Name from Employees".  This feature can significantly improve the performance of ADF application. But what about read-only or SQL-based view objects? JDeveloper doesn't allow you to choose the SQL mode for SQL-based VOs. Оnly "Expert" mode can be used with no chance to have the query generated on the fly. But everything is possible.

In this post we have an example of some SQL-based view object VEmployees:


Let's generate View Object Definition class:

 

We're going to override some methods:

  @Override
  public boolean isRuntimeSQLGeneration()
  {
     return true;
  }

  @Override
  public boolean isFullSql()
   {
      return false;
   }

  @Override
  //In our case we know exactly the clause FROM
  public String buildDefaultFrom(AttributeDef[] attrDefs,
                                 SQLBuilder builder,
                                 BaseViewCriteriaManagerImpl vcManager)
  {
     return "Employees";
  }

  @Override
  //Setting "Selected in Query" property for each attribute except PK
  protected void createDef()
   {
     for (AttributeDef at : getAttributeDefs()) 
      if (!at.isPrimaryKey()) 
        ((AttributeDefImpl) at).setSelected(false);   
   }


 
Actually, that's it! Let's test it.

For the page showing the full set of attributes, we have the result:


And generated query (I use ODL analyzer):



For the page with only two attributes we have the following result:


 And the query:















The sample application for this post requires JDeveloper 11.1.2.1.0 and standard HR schema. 

23 Jun 2012

Dependent LOV in a Search Form

Let's say we have a ViewObject with a LOV enabled attribute.

 The ViewAccessor's ViewObject has a bind variable.


In our use case we have a method in the ViewObjectImpl calculating value for this bind variable.

    public Integer getDealTypeID() {

        return someCalculatedValue;

    }


So, we can put a groovy expression "viewObject.dealTypeID" to the ViewAccessor's definition:


And it works fine everywhere except Search Form. If our LOV enabled attribute is used in a View Criteria and triggered from a Search form we will get something like this: JBO-25077: Name dealTypeID not found in the given object: oracle.adf.model.bean.DCDataVO. The object for the groovy script in case of a SearchForm is DCDataRow that is built internally by the af:query mechanism.
If we change the groovy expression to this "dataProvider.viewCriteria.viewObject.dealTypeID",
the Search Form will start to work, but the normal form will be broken. So, we have to understand somehow where the groovy expression is triggered from. The "adf.isCriteriaRow" expression can help us and our groovy script will look like this:

if (adf.isCriteriaRow)  
  return dataProvider.viewCriteria.viewObject.dealTypeID; 
else   
  return viewObject.dealTypeID;


This script will work in both cases!
But... That's all fine for R1 only . In R2 the expression "adf.isCriteriaRow" is not working in this case and the groovy script for R2 will look a bit ugly:


if (object.getClass().getName().endsWith('DCCriteriaValueRowImpl'))     
   return viewCriteria.viewObject.dealTypeID;  
else   
   return viewObject.dealTypeID;


That's it!.



15 Jun 2012

Oracle OpenWorld 2012. Deep Dive into Oracle ADF.

I am happy to invite everybody to attend my session at Oracle OpenWorld 2012.

Session ID: CON5623
Session Title: Deep Dive into Oracle ADF: Advanced Techniques

You are welcome to have a journey from the surface of the declarative approach into the deep of the real-life hands-on programming. The session is completely technical and concentrates on advanced techniques of creating and manipulating ADF objects programmatically on-the-fly.

Looking forward to seeing you in San Francisco!

31 May 2012

Multiple iterator bindings for one View Object

The common practice (and default option for the declarative approach) is to create one iterator binding per View Object in the Page Def file.  But there's nothing to prevent us from defining several iterators in the PageDef's executable section for the same View Object. By default iterator binding binds to default row set iterator of the View Object. Iterator binding has RSIName attribute which allows us to bind to the named row set iterator of the View Object. When it could be an option? Let's assume we have a View Object with a bind variable in its query and  we need to show on the same page two separate results of the query with different values of the bind variable:

select * from Employees
where job_id = :job_id 

As we know View Object can have many secondary row sets besides its main default row set which is used by default. Every row set can store its own set of bind variable values. The view links functionality is based on this feature. We are going to use it as well. So, we have our ViewObjectImpl class with two overridden methods:

  protected void create() { 
    super.create(); 
    
    //Create Row Set for clerks and define value for the job_id bind variable
    ViewRowSetImpl rsClerk = (ViewRowSetImpl) createRowSet("ClerkRSI");
    rsClerk.setExecuteParameters(null, 
                    new Object[] { new Object[] {"job_id", "ST_CLERK"}}, false);       

    //Create Row Set for managers and define value for the job_id bind variable
    ViewRowSetImpl rsMan = (ViewRowSetImpl) createRowSet("ManRSI");
    rsMan.setExecuteParameters(null,
                    new Object[] { new Object[] {"job_id", "ST_MAN"}}, false);       

    }
  
   public oracle.jbo.RowSetIterator findRowSetIterator(java.lang.String p1) {
       RowSetIterator rsi = super.findRowSetIterator(p1);        
       if (rsi == null) 
          //Probably we are looking for  ClerkRSI or ManRSI
           return findRowSet(p1);
        return rsi; 
      }


And in our Page Def file we have two iterator bindings:

    <iterator Binds="VEmp" RangeSize="25" DataControl="AppModuleDataControl"
              id="VEmpClerkIterator" RSIName="ClerkRSI"/>
    <iterator Binds="VEmp" RangeSize="25" DataControl="AppModuleDataControl"
              id="VEmpManagerIterator" RSIName="ManRSI"/>


 
These bindings can be used to put two separate tables on our page with clerks and managers.

That's it!

20 May 2012

Working with VO's built-in aggregation functions

When we work with View Link accessors or Association accessors we can use Groovy for aggregation calculations in a very convenient way. Groovy API provides five predefined functions:
  • accessor.sum("expr")
  • accessor.count("expr")
  • accessor.avg("expr")
  • accessor.min("expr")
  • accessor.max("expr")
This API is commonly used to calculate values of transient attributes in the master VO's.  But what if we don't have any master-detail relationship and don't have any accessors? We just have a ViewObject and we need to do some aggregation calculations on it - this is very common use case.  The common practice for this issue is to write custom Java method in the ViewObjectImpl class. But we have already five (that is enough for most cases) built-in methods used by the Groovy API. These methods are implemented by the ViewRowSetImpl (extends RowSetHelper) class and as any useful methods these ones are private. Groovy API uses InvokerHelper class to invoke them as it could be easily seen from the call stack. Let's do the same. Off-course these built-in methods can be deprecated in the future in the latest versions of ADF and we should be aware of that, but until it has not happened we do the following:
 
     1. Create an inner helper class in our ViewObjectImpl
   private class AgrFuncHelper extends HashMap
  {
    private String funcName;

    public AgrFuncHelper(String funcName) 
    {
      super();
      this.funcName = funcName;  
    }


    public Object get(Object key) 
    {
      //Invoke private method
      //of our DefaultRowSet (sum,count,avg,min,max)
      //key is argument expression for the aggr funcion being called
      //sum("Salary")

      return InvokerHelper.invokeMethod(getDefaultRowSet(), funcName, key);
    }

  }

 
    2. Publish aggregation methods
  public Map getSum() 
  {
    return new AgrFuncHelper("sum");
  }
  
  public Map getCount() 
  {
    return new AgrFuncHelper("count");
  }

 
   3. Use the methods in jspx
<af:outputText value="#{bindings.EmployeesView1Iterator.viewObject.sum['Salary']}"                        
   id="ot12"/>
<af:outputText value="#{bindings.EmployeesView1Iterator.viewObject.count['*']}" 
  id="ot13"/>
 


That's it!

29 Apr 2012

Backing bean scope in ADF task flow finalizer

Introduction
This is very common and recommended practice to use task flow finalizers when we need to do some final job (clean resources, close connections, etc) before the task flow is gone. As usual we work with managed beans declared inside the task flow. The managed beans can have different scopes - request, page flow, view, backing bean, etc. The scope depends on what the bean is actually used for. There is a small problem when we access to the backingBean scope managed bean in the finalizer. Let's have a look at the example bellow.

We have a bounded task flow with page fragments:

And we have manged beans inside the task flow of three different scopes - page flow, view and backingBean:

 <managed-bean id="__3">
  <managed-bean-name id="__5">FlowBean</managed-bean-name>
  <managed-bean-class id="__4">view.BackBean</managed-bean-class>
  <managed-bean-scope id="__2">pageFlow</managed-bean-scope>
 </managed-bean>
 <managed-bean id="__9">
  <managed-bean-name id="__6">ViewBean</managed-bean-name>
  <managed-bean-class id="__7">view.BackBean</managed-bean-class>
  <managed-bean-scope id="__8">view</managed-bean-scope>
 </managed-bean>
 <managed-bean id="__10">
  <managed-bean-name id="__11">BackBean</managed-bean-name>
  <managed-bean-class id="__12">view.BackBean</managed-bean-class>
  <managed-bean-scope id="__13">backingBean</managed-bean-scope>
 </managed-bean>


On the page we have three buttons binded to managed beans of each scope:
  <af:commandButton text="commandButton 1" id="cb1"
     action="go" binding="#{backingBeanScope.BackBean.button}">
  </af:commandButton>

  <af:commandButton text="commandButton 1" id="cb2"  
    binding="#{viewScope.ViewBean.button}"/>

  <af:commandButton text="commandButton 1" id="cb3"  
    binding="#{pageFlowScope.FlowBean.button}"/>

The bean class has the button attribute and testString attribute that signals whether the button is assigned:
  private RichCommandButton button;
  
  public void setButton(RichCommandButton button)
  {
    this.button = button;
  }

  public RichCommandButton getButton()
  {
    return button;
  }

  public String getTestString()
  {
    if (this.button == null)
      return "The button is not assigned";
    else
      return "The button is assigned";
  }



When we press cb1 we go to the return activity and the finalizer gets executed:

public static String resolveExpression(String expression)
 {
   FacesContext fc = FacesContext.getCurrentInstance();
   return (String) fc.getApplication().evaluateExpressionGet(fc, expression,
                                                    String.class);
 }

public void theFinalizer() 
{
  //Just to have test access to the managed beans
  //and to be sure we work with the same instances
  System.out.println(resolveExpression("#{pageFlowScope.FlowBean.testString}")+
                     " " + resolveExpression("#{pageFlowScope.FlowBean.button}"));
  System.out.println(resolveExpression("#{viewScope.ViewBean.testString}")+
                     " " + resolveExpression("#{viewScope.ViewBean.button}"));
  System.out.println(resolveExpression("#{backingBeanScope.BackBean.testString}")+
                     " " + resolveExpression("#{backingBeanScope.BackBean.button}"));
}




Run the application, press the cb1 button and see the following in the system log:

The button is assigned RichCommandButton[UIXFacesBeanImpl, id=cb3]
The button is assigned RichCommandButton[UIXFacesBeanImpl, id=cb2]
The button is assigned RichCommandButton[UIXFacesBeanImpl, id=cb1]

Everything seems to be ok. The task flow is finished and in the finalizer we work with correct managed bean instances. In this test the task flow is finished correctly using Return activity.
And now let's abandon our task flow - just go away from the page the task flow is put on. The finalizer is executed as well, and have a look at system out:

The button is assigned RichCommandButton[UIXFacesBeanImpl, id=cb3]
The button is assigned RichCommandButton[UIXFacesBeanImpl, id=cb2]
The button is not assigned 

This means that we work with different instance of the backingBeanScope.BackBean! In case of abounded task flow the controller don't see correct backingBeanScope in the finalizer, it is empty and the controller create new instance of the BackBean. At the same time pageFlowScope and viewScope work perfect. So, be careful when you use backingBean scope managed beans within task flows, especially when you access them in finalizers. But in any case you can use the same trick described in the previous post.

That's it!


Get access to the BackingBeanScope of the inner TaskFlow

Let's say we have a page with a region and some bounded task flow inside the region. The task flow has some backingBean scope managed bean:

 <managed-bean id="__1">
  <managed-bean-name id="__2">BackBean</managed-bean-name>
  <managed-bean-class id="__3">view.BackBean</managed-bean-class>
  <managed-bean-scope id="__4">backingBean</managed-bean-scope>
 </managed-bean>

We need to have an access to this bean outside of the task flow. For example we need to disable a button on the main page depending on some property of the BackBean.  We can do the following:

  // taskflow is <taskFlow id="taskflowdefinition1" from our pageDef
  public Map getBackingBeanScope4TaskFlow(String taskflow) 
  {
    Map resultMap = null;
    
    //We need the full name of our taskflow
    DCBindingContainer dcb =
        (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
    DCTaskFlowBinding dfb = (DCTaskFlowBinding) dcb.findExecutableBinding(taskflow);
    String fullName = dfb.getFullName();                                 
  
    //Get the provider
    BackingBeanScopeProviderImpl bbProvider =
            ((BackingBeanScopeProviderImpl)AdfFacesContext.getCurrentInstance().getBackingBeanScopeProvider());
    
    //Left parenthesis
    bbProvider.begin(fullName);
    
    //Now the current backing bean scope is the scope of our task flow
    try {
       resultMap = bbProvider.getCurrentScope();
    } finally {
    //Right parenthesis
        bbProvider.end();
    }
    
    return resultMap; 
  }

  public Object getBackBean() 
  {
    return getBackingBeanScope4TaskFlow("taskflowdefinition1").get("BackBean"); 
  }
  

 Of-course using this technique is a little bit against the encapsulation concept - we should not have access to the details of the inner/child objects. We have to be aware of that. And for our use-case it'd be probably better to use contextual events or something else. But in any case we know how to do the trick, and Knowledge is Power :).

That's it!

21 Apr 2012

How to avoid validation of immediate inputs

Introduction
Setting the immediate attribute of JSF/ADF command components to true is not the silver bullet that can help you to avoid validation. This is explained in the Understanding the JSF Immediate attribute post. If you have immediate input controls on the same form, these controls are going to be validated in any case. But immediate input controls could be quite useful as it was shown in the Update model in the ValueChangeListener post.  So, let's say you have immediate required inputText and immediate commandButton (some "Cancel" button) on the same form. Leaving the inputText empty will cause a validation error when the commandButton is pressed.


This post is showing a technique of using some "super" Immediate button, that can help us to really avoid validation in any case. So, our "super" Immediate button looks like this:

   <af:commandButton text="Cancel" id="cb1" 
                      actionListener="#{TestBean.buttonActionListener}"        
                      immediate="true"
                      action="someAction">
                      
      <af:clientAttribute name="superImmediate" value="#{true}"/>                
      <af:clientListener method="catchActionEvent" type="action"/>
      <af:serverListener type="customButtonAction"
                         method="#{TestBean.customButtonActionListener}"/>

    </af:commandButton>                   


And a little bit of Java Script:
   <af:resource type="javascript">  
     
     // This hack avoids client-side validation for the "superImmediate"
     // commandComponents
     AdfActionEvent.prototype.isValidationNeeded = function()
       {
         return !this.getSource().getProperty("superImmediate");
       } 
       
    // Action event will cause server-side validation at the
    // Apply Request Values phase (for immediate button).
    // So we'll get validation error even if the client-side validation is suppressed
    // We need to catch the original Action event, cancel it and replace with our
    // custom event customButtonAction.
    function catchActionEvent(evt){
      AdfCustomEvent.queue(evt.getSource(), 'customButtonAction' , null, true); 
      evt.cancel();                  
    }   
    
   </af:resource>


And finally we need to emulate an Action Event in our customButtonActionListener in order to get the button's actionListener executed and the action processed:

  public void customButtonActionListener(ClientEvent clientEvent) {
      UIXCommand cb = (UIXCommand) clientEvent.getComponent();
      cb.broadcast(new ActionEvent(cb));
  }


That's it!

31 Mar 2012

Update model in the ValueChangeListener

After reading of the Understanding the JSF Immediate Attribute post, my friend asked me whether there is any sense to use the Immediate attribute for inputTexts. The answer is Yes, off course. In general we set the Immediate to true when we need to validate the component and execute its value change events before the common validation process, before the Process Validation phase. We move up the validation and the value change events processing to the Apply Request Values phase. In other words, we split our components into two parts: front-line or Immediate inputs that are validated first at the Apply Request Values and all others that are validated later at the usual Process Validation phase. In this post I'm going to show one of use-cases when the Immediate attribute for inputTexts could be useful.
Let's say we have two inputTexts:

        <af:inputText label="Label Value" id="it1"
                      value="#{backing_Main.labelValue}" autoSubmit="true"
                      />

        <af:inputText label="#{backing_Main.labelValue}" id="it2"
                      partialTriggers="it1"/>

The first one stores its value in some backing bean property (in the model), and the second input reads this property to render its label. The first input is autosubmit and it partially triggers the second input, so when we change value of the first input and press Tab, label of the second one is going to be changed immediately. At this point both inputs are not Immediate and everything works fine:

Let's change the required attribute of the second input to true and we get validation error:

To resolve this issue let's set Immediate of the first input to true and add a valueChangeListener. In the valueChangeListener we need to manually update model for the first input because we are going to skip all the subsequent phases (including Update Model phase) except Render Response:

   public void labelListener(ValueChangeEvent valueChangeEvent)
  { UIComponent c = valueChangeEvent.getComponent();
    
    //This step actually invokes Update Model phase for this 
    //component
    c.processUpdates(FacesContext.getCurrentInstance());
    
    //Jump to the Render Response phase in order to avoid 
    //the validation
    FacesContext.getCurrentInstance().renderResponse();
  }

And it works fine again:



That's it!

11 Mar 2012

Managed bean scopes for page fragments in ADF Task Flow

Introduction
When we work with ADF Task Flows and need to implement some flow specific business logic or store some information connected with the flow, we usually use pageFlowScope managed beans. And when we need to service view activities of the flow (pages or page fragments) we use shorter scopes for such managed beans. The common practice is to use requestScope, backingBeanScope and viewScope scopes for pages/fragments backing beans. In this post I'm going to play with these three options and discover the differences in the behavior of fragment based Task Flow.

Let's say I have some simple task flow template task-flow-template.xml:


   <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__2">com.cs.blog.ViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.FlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>

    <view id="MainView">
      <page>/MainView.jsff</page>
    </view>
    

It has one view activity MainView and two backing beans. The flowBean has pageFlow scope and is responsible to store flow information. The viewBean has request scope (we will play with that) and it services the ManView view activity.

The flowBean has the following method returning the tittle of the task flow:

    public String getFlowTitle() {
        return null;
     }   

The viewBean has some string field testString to store input value:

    protected String testString;
    
    public void setTestString(String testString) {
        this.testString = testString;
    }

    public String getTestString() {
        return testString;
    }

The MainView shows the task flow's title and has an inputText for the testString. It looks like this:


We also have two task flows built on the task-flow-template - first-flow-definition and second-flow-definition. They have overridden managed beans.

For the  first-flow-definition:

    <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__21">com.cs.blog.FirstViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>    
    
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.FirstFlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>
 

public class FirstFlowBean extends FlowBean {
    public FirstFlowBean() {
        super();
    }
    
    public String getFlowTitle() {
        return "FirstFlow";
     }   
   
}

public class FirstViewBean extends ViewBean {
    public FirstViewBean() {
        super();
        
    }
    
    @PostConstruct
    public void init() {
        testString = "FirstFlow";  
    }
}

So the title and default value for testString is "FirstFlow".


For the  second-flow-definition:

    <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__21">com.cs.blog.SecondViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>    
    
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.SecondFlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>

public class SecondFlowBean extends FlowBean {
    public SecondfFowBean() {
        super();
    }
    
    public String getFlowTitle() {
        return "SecondFlow";
     }   
    
}

public class SecondViewBean extends ViewBean {
    public SecondViewBean() {
        super();
       
    }
   
    @PostConstruct
    public void init() {
        testString = "SecondFlow"; 
    }
   
}

So the title and default value for testString is "SecondFlow".


Ok. It's time to experiment. Let's put on our page two regions with first-flow-definition and second-flow-definition task flows:

              <af:region value="#{bindings.firstflowdefinition1.regionModel}"
                         id="r1"/>
              <af:separator id="s1"/>           
                         
              <af:region value="#{bindings.secondflowdefinition1.regionModel}"
                         id="r2" />

requestScope
Leaving the scope for the viewBean as requestScope we will get the following result:

In the SecondFlow we see the testString from the FirstViewBean instance. We can have only one instance of the requestScope bean per request. The viewBean was created for the FirstFlow task flow and the same instance was used again for the SecondFlow.

backingBeanScope
Somebody could recommend to use backingBeanScope for the viewBean instead of requestScope. The backingBeanScope is commonly used to manage regions and declarative components. It has the same length of life as the requestScope but for different instances of regions/declarative components you will have separate instances of backingBean scoped managed beans. In our case we have two different regions, so let's try:

And, Yes, the backingBeanScope has fixed the problem. We have two instances of the viewBean - for the regions r1 and r2.
But let's make the first-flow-definition task flow a bit more complicated:


Now we can call child task flow (of the same definition) from the MainView. And let's repeat the experiment. On the initial rendering:

So far, so good. Let's input something in the input text of the FirstFlow and press "call child task flow":


Oooops! We have only one instance of the viewBean for the region r1 during the request. So, value "FirstFlow111111" entered in the parent task flow was rendered again in the child task flow.


viewScope
And now let's change the viewBean's scope to the viewScope and have the same experiment. On the initial rendering:

 Ok. Inputting the same garbage in the inputText:

And pressing the "call child task flow":
And everything is ok. We have not only separate viewScope beans instances for different viewport IDs (for different regions and task flow instances), but additionally the controller is resetting the viewScope during the navigation process. But the cheese is not free. You have to pay by memory. If requestScope or backingBeanScope live not longer than the request, viewScope lives in memory until the viewport ID is changed. Perhaps in my further posts I will show how to manage the issue with the backingBeanScope.

So, when you choose the appropriate scope for your fragment managed beans, consider how the task flow is going to be used. Probably, in order to get really high reusable task flow, using the viewScope is the best approach for fragment beans.

That's it!


 

19 Feb 2012

Understanding the JSF Immediate Attribute

There is very common myth among ADF and JSF developers that using Immediate attribute will avoid unnecessary validation in any case. It is only partly true. The myth is growing up because of misunderstanding how the Immediate attribute actually works. Using the attribute without understanding of the mechanism very often lead to bugs and unpredictable behaviour of the application. I hope, this post will be useful for developers to understand and to remember when the Immediate attribute is a good option and when it is not.

I think, we should be aware of the following key points:
  • Processing  of any components with Immediate attribute is moved up to the Apply Request Values phase of the lifecycle. But there is a big difference in processing of editableValueHolder (inputText) and actionSource (commandButton) components.
  • For EditableValueHolder components (like inputText) with Immediate attribute validation and valueChangeEvent delivering are done in Apply Request Values phase instead of usual Process Validation phase. This is the only change. The lifecycle is not stopped, it is going on, there is no any lifecycle phase skipping!
  •  Restore View->Apply Request Values->Process Validations->Update Model->Invoke App->Render Response 
     
  • For ActionSource components (like commandButton) with Immediate attribute, action event is delivered to Apply Request Values phase instead of usual  Invoke Application phase. But!!! After that the lifecycle is jumping to the end, to Render Response phase. Validation and Model Update phases are skipped.
  •   Restore View->Apply Request Values->Render Response 

In order to understand how these points actually affect the system's behaviour,  I'm going to have some experiments with very simple form:


And the jspx for the form:

<af:form id="f1">
  <af:inputText label="Label 1" id="it1"
                value="#{TestImmediateBean.firstInputValue}"
                valueChangeListener="#{TestImmediateBean.firstInputListener}"                
                binding="#{TestImmediateBean.firstInputText}"/>

  <af:inputText label="Label 2" id="it2"
                value="#{TestImmediateBean.secondInputValue}"
                valueChangeListener="#{TestImmediateBean.secondInputListener}"                      
                binding="#{TestImmediateBean.secondInputText}"/>

  <af:commandButton text="commandButton 1" id="cb1" 
                    actionListener="#{TestImmediateBean.buttonActionListener}"/>
</af:form>

I've added log messages to the valueChangeListeners, setters, and actionListener in order to follow the request process:

private void printCurrenPhaseID() {
  FacesContext fctx = FacesContext.getCurrentInstance();
  Map requestMap = fctx.getExternalContext().getRequestMap();
  PhaseId currentPhase=(PhaseId)requestMap.get("oracle.adfinternal.view.faces.lifecycle.CURRENT_PHASE_ID");
  System.out.println("currentPhase = "+currentPhase);
}
          
          
public void firstInputListener(ValueChangeEvent valueChangeEvent) {
    System.out.println("firstInputListener {");
    printCurrenPhaseID();
    System.out.println("NewValue = " + valueChangeEvent.getNewValue());
    System.out.println("}");
}

public void secondInputListener(ValueChangeEvent valueChangeEvent) {
    System.out.println("secondInputListener {");
    printCurrenPhaseID();
    System.out.println("NewValue = " + valueChangeEvent.getNewValue());
    System.out.println("}");
}

public void setFirstInputValue(String firstInputValue) {
    this.firstInputValue = firstInputValue;
    System.out.println("firstInputValue setter {");
    printCurrenPhaseID();
    System.out.println("}"); 
}

public void setSecondInputValue(String secondInputValue) {
    this.secondInputValue = secondInputValue;
    System.out.println("secondInputValue setter {");
    printCurrenPhaseID();
    System.out.println("}"); 
}

public void buttonActionListener(ActionEvent actionEvent) {
    System.out.println("actionEventListener {");
    printCurrenPhaseID();
    System.out.println("firstComponentValue = " + firstInputText.getValue());
    System.out.println("secondComponentValue = " + secondInputText.getValue());        
    System.out.println("firstModelValue = " + getFirstInputValue());
    System.out.println("secondModelValue = " + getSecondInputValue());        
    System.out.println("}");
}

So, Experiment #1. Standard situation, nobody has Immediate attribute:

Immediate

AutoSubmit

Required

FirstInput
false false  false 

SecondInput
false  false  false 

CommandButton
false  X X

Input values and click the button:

In the system log we can see the following:
firstInputListener {
currentPhase = PROCESS_VALIDATIONS 3
NewValue = 1
}
secondInputListener {
currentPhase = PROCESS_VALIDATIONS 3
NewValue = 2
}
firstInputValue setter {
currentPhase = UPDATE_MODEL_VALUES 4
}
secondInputValue setter {
currentPhase = UPDATE_MODEL_VALUES 4
}
actionEventListener {
currentPhase = INVOKE_APPLICATION 5
firstComponentValue = 1
secondComponentValue = 2
firstModelValue = 1
secondComponentValue = 2
}

Everything is good. ValueChangelisteners are delivered to the Process Validation phase, setters are fired at the Update Model phase and actionListener is delivered to the Invoke Application phase.

Experiment #2. FirstInput  has Immediate attribute:

Immediate

AutoSubmit

Required

FirstInput
true false  false 

SecondInput
false  false  false 

CommandButton
false  X X

And the log:
firstInputListener {
currentPhase = APPLY_REQUEST_VALUES 2
NewValue = 1
}
secondInputListener {
currentPhase = PROCESS_VALIDATIONS 3
NewValue = 2
}
firstInputValue setter {
currentPhase = UPDATE_MODEL_VALUES 4
}
secondInputValue setter {
currentPhase = UPDATE_MODEL_VALUES 4
}
actionEventListener {
currentPhase = INVOKE_APPLICATION 5
firstComponentValue = 1
secondComponentValue = 2
firstModelValue = 1
secondComponentValue = 2
}

Note, that valueChangeListener for the FirstInput was delivered to Apply Request Value phase (because of Immediate). All other phases don't have any changes.

Experiment #3. CommandButton has Immediate attribute:

Immediate

AutoSubmit

Required

FirstInput
false false  false 

SecondInput
false  false  false 

CommandButton
true X X

And the Log:
actionEventListener {
currentPhase = APPLY_REQUEST_VALUES 2
firstComponentValue = null
secondComponentValue = null
firstModelValue = null
secondComponentValue = null
}


ValueChangeListeners and setters are not fired at all! Component values and Model values are null. They should be updated in Process Validations and Update Model phases, but they were skipped (key point #3). Very predictable result.


Experiment #4. FirstInput and CommandButton have Immediate attribute:

Immediate

AutoSubmit

Required

FirstInput
true false  false 

SecondInput
false  false  false 

CommandButton
true X X

And the Log:
firstInputListener {
currentPhase = APPLY_REQUEST_VALUES 2
NewValue = 1
}
actionEventListener {
currentPhase = APPLY_REQUEST_VALUES 2
firstComponentValue = 1
secondComponentValue = null
firstModelValue = null
secondComponentValue = null
}

This is very important! Process Validations and Update Model phases are skipped as in the previous experiment because commandButton has Immediate , but valueChangeListener for FirstInput is fired because it has Immediate as well (key point #2). And value of the component (RichInputText) is updated too. So, when you click the "Immediate" button, valueChangeListeners for every "Immediate" input fire as well. Be aware of that! I've recently fixed some bug connected with that. And vice-versa, if you need in an actionListener of the "Immediate" button any components' values, set their Immediate to true.
What do you think will happen if Required of the FirstInput is set true?!

Experiment #5. FirstInput and SecondInput are required. FirstInput and CommandButton have Immediate attribute:

Immediate

AutoSubmit

Required

FirstInput
true false  true

SecondInput
false  false  true

CommandButton
true X X

Let's leave inputs empty and click the button. In this case we don't have any log, we have the following:

Note! The button has immediate attribute set to true, but validation is failed. Because validation process for the FirstInput is moved up to Apply Request Values (Key Point #2). The myth is busted! On the other hand, the SecondInput is required as well, but there is no any problem with its validation. The SecondInput is not Immediate. It was going to be validated at Process Validation phase, but the phase was skipped because of Immediate button (Key Point #3). So, the myth is partly true :).  

Experiment #6. FirstInput is autoSubmit. SecondInput is a partial target for the FirstInput:

Immediate

AutoSubmit

Required

FirstInput
true true true

SecondInput
false  false  true

CommandButton
true X X

Let's input something into the FirstInput and press Tab. We have validation exception:

 Note! The FirstInput is Immediate, but we still have the exception. The myth is busted again. Processing of editableValueHolder components does not  skip Process Validation phase.  It doesn't skip any phase at all. (Key Point #2)
How to avoid this exception? We have to move up the lifecycle to the end manually. In the valueChangeListener we add the following:

 public void firstInputListener(ValueChangeEvent valueChangeEvent) {
    System.out.println("firstInputListener {");
    printCurrenPhaseID();
    System.out.println("NewValue = " + valueChangeEvent.getNewValue());
    System.out.println("}");
    //Jump to the Render Response phase
    FacesContext.getCurrentInstance().renderResponse();        
}

And the exception's gone.

So, in order to use the Immediate attribute properly, remember three key points mentioned at the beginning of the post.  


You can download my sample application and play with your own experiments.

Thank you!