Friday 13 May 2016

View Criteria

ADF : View Criteria complex code snippets


View Criteria is a declarative representation of View Object where clause. View Criteria contain a criteria row that itself contains attributes/items that the where clause constructs.


vo = this.getEmpVO();

//To get all the view criterias currently applied on a VO

String[] criterias =  vo.getViewCriteriaManager().getApplyViewCriteriaNames();


//To see all the applied view criterias on a VO

        String[] criterias =  vo.getViewCriteriaManager().getApplyViewCriteriaNames();
        if (Tcriterias != null) {
            for (String vcName : criterias) {
                System.out.println("ViewCriteria :" + vcName);
            }
        }


//To unapply a view criterias on a VO which is currently applied.

String[] criterias =  vo.getViewCriteriaManager().getApplyViewCriteriaNames();
        if (Tcriterias != null) {
            for (String vcName : criterias) {
               vo.getViewCriteriaManager().removeApplyViewCriteriaName(vcName);
            }
        }


//To see all the view criteria items inside a view criteria row

List list = vc.getRows(); //(vc is a view criteria)

Iterator iter1 = list.iterator();
while (iter1.hasNext()) {
      

                   ViewCriteriaRow row = (ViewCriteriaRow)iter1.next();

                   row.getCriteriaItem("EmpId");
                   row.getCriteriaItem("EmpName").getValue();

                   List vcitems = row.getCriteriaItems();
                  Iterator itemiter = vcitems.iterator();

                 while (itemiter.hasNext()) {
                             
                   ViewCriteriaItem vcitem = (ViewCriteriaItem)itemiter.next();
                   System.out.println("vcitemname in vcrow:"+vcitem.getName());
                   System.out.println("vcitemvalue in vcrow:"+vcitem.getValue());
                  
         }

}

//Add the row to the existing Criteria
vc.addElement(criteriaRow);

Wednesday 11 May 2016

Conditional Render in ADF Faces

ADF : Conditional Render in ADF Faces/ Manually creating ADF Table display

Use case :

The Employee of a company fills an online form of resigning reason before leaving the organization.
All these comments/reason submitted by various employees who left the organization will be saved in a separate DB table Job History.

Now the list of employees with the feedback  in the UI looks like this


Note: I am constructing these information as a table format without using ADF Table . The reason is to explain the scenario with more of real time case.

To achieve this we can use af:gridrow that can loop over the rows that the iterator has.

<af:iterator value="#{bindings.JobHistory.collectionModel}"    var="row" id="it2"   >
           //Code to loop over the rows
         <af:gridRow>
        <af:gridCell>

        </af:gridCell>
       </af:gridRow>
<af:iterator/>

It just looks like the old jsp code where in the table TR and TD loops over a collection of data.
we generally fix the cell property of the row to fixed to have the limited alignment of the table in the page. The space between each row should be dynamic so that the text in the cells would not get overlapped.

something like this will makes sense

<af:iterator value="#{bindings.JobHistory.collectionModel}"    var="row" id="it2"   >
<af:gridRow id="gr3"height="#{row.comments gt 100 ? '40px' : '20px'}">
 <af:gridCell marginStart="10px" width="100px" id="gc7"       valign="stretch" halign="stretch">
              <af:outputText value="#{row.Name}" id="ot8" noWrap="false"/>
            </af:gridCell>
            <af:gridCell marginStart="10px" id="gc9" width="250px"   valign="stretch" halign="stretch">
              <af:outputText value="#{row.comments}" id="ot10"     inlineStyle="word-wrap:break-word" noWrap="false"/>
            </af:gridCell>
 </af:gridRow>

Also few more EL expressions for the conditional rendering of the ADF Faces components

<af:outputText value="#{pageFlowScope.data.request eq 'YES' and pageFlowScope.data.response eq 'N' ? 'DONE': 'COMPLETED'}"  id="ot3"/>

 <af:outputText value="#{str}" id="ot1" rendered="#{requestContext.flag=='YES'}" />

<af:commandLink id="ci2"     rendered="#{row.flag == 'Y' }"  />

Monday 9 May 2016

How to get input values in Managed bean

ADF : How to get input values in Managed bean

                 
Use case :

When I click a button, I want the button to call a method in a java bean and access the value of an input text fields  from ADF Faces pages .

There are many solutions available . This one is basic and easy approach

Solution : 

you can do this by creating binding for each component in a managed/backing bean so that bean will have getter/setter property created for you . Add a button in the page that will have the action listener method to the same bean where you have created bindings for the input components and you can access the values using this.getId().getValue() .

 <b>in Jsff :</b>

 <af:inputText label="Id" id="it1" binding="#{pageFlowScope.SourceFile1.id}"/>
        
 <b>in Bean</b>



       
JAVA CODE:-
 


private RichInputText id;

 public void setId(RichInputText id) {
this.id = id;
 }

 public RichInputText getId() {
 return id;
  }
       
  public void onClickSubmit(ActionEvent actionEvent) {
  System.out.println(this.getId().getValue().toString());
  }


 

Friday 6 May 2016

Access ADF Bindings from Managed Bean

Access ADF Bindings from Managed Bean

ADF enables bindings through Oracle ADF Model layer. whenever ADF view layer is created JDeveloper creates data bound client and thus enable the bridge between model and view components to access data .In some cases we may want to access page bindings Programatically from managed bean . Lets see how it can be done.

Look at the screen shot of the page bindings section of a jsff page.


When u drag and drop employee data control on to the page, Bindings section will contain the data control instance and executable section contains Employee Iterator .

Now lets see how we can access table bindings from Managed Bean . The Code to access.

        DCBindingContainer bindings2 = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
              
        JUCtrlHierBinding obj = (JUCtrlHierBinding)bindings2.findCtrlBinding("EmployeesEOView1");
        ViewObject vo= obj.getViewObject();
        
        //some operations on it
       
        vo.setNamedWhereClauseParam("BindEmployeeId",101);
        vo.executeQuery();


The same way we can get Iterator bindings too ..

     DCBindingContainer bindings =(DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
              
        DCIteratorBinding roleIter = bindings.findIteratorBinding("EmployeesEOView1Iterator");

        ViewObject obj = roleIter.getViewObject();

Execution of Operation binding

BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding operationBinding = bindings.getOperationBinding("CreateInsert");
        Object result = operationBinding.execute();
       
        //Custom Method
        BindingContainer bindings1 = BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding method = bindings1.getOperationBinding("methodBindingId");
        Map args = method .getParamsMap();
        args.put(“argument1”, argument1Value);
        method .execute();
        

 

Programmatic access to View Accessor

ADF : Programmatic access to View Accessor / Dependent LOV

View Accessor is often used to bring List of Values . In simple way , it is used to access a view object from another view object . why in the world should i need to access the view accessor programmatically when ADF View object has the privilege to handle it automatically.. well , thats a point.. There we have a use case //

In general,dependent LOV based on another attribute gets its value by executing view accessor.suppose i have an attribute whose view accessor is defined but the value which is required to be passed comes from various other action like previous page input. There is no view link between two view objects,no relationship .so its completely two independent view objects, but LOV in VO2 depends on VO1 input ..
























In Vo2RowImpl :

//VA defined

 public RowSet getMoney() {
        return (RowSet)getAttributeInternal(MONEY);
    }

//custom method
public Object executeViewAccessor(String val) {
      RowSet rs=(RowSet)getAttributeInternal(MONEY);
      rs.setNamedWhereClauseParam("str", str);
      rs.executeQuery();        
      return rs;
    }

//Code to invoke the VA from AmImpl class. AM method is the bridge between two taskflow to pass parameters since we added TF2 as region in main TF. you should add the below AmImpl method as method action before PAGE 2 in TF2

AmImpl Method :

public void executeAction(String str) {
     
        ViewObjectImpl vo = this.getVo2();
        Row row = vo.createRow();
        vo.insertRow(row);
        VO2RowImpl rImpl = (VO2RowImpl )vo.getCurrentRow();
        rImpl.executeViewAccessor(str);

    }

Now you have executed the View accessor of Money VO and your attribute in VO2 containing the LOV prepared based on the input being passed.

Note : There could be certainly many ways to achieve this functionality. This is one of the use case to explain ..

Thursday 5 May 2016

Task Flows

ADF task flows provide a modular approach for defining control flow in an application. Instead of representing an application as a single large JSF page flow, you can break it up into a collection of reusable task flows. Each task flow contains a portion of the application's navigational graph. The nodes in the task flows are activities. An activity node represents a simple logical operation such as displaying a page, executing application logic, or calling another task flow. The transactions between the activities are called control flow cases.
shows two view activities called Create and Confirm. These view activities are similar to page nodes within a JSF page flow.

Figure :- ADF Task Flow
Simple ADF Task Flow.
Task flows can invoke managed beans.

About Unbounded Task Flows

A Fusion web application always contains an ADF unbounded task flow, which contains the entry point or points to the application. An entry point is a view activity that can be directly requested by a browser. A Fusion web application only has one unbounded task flow. By default, the source file for the unbounded task flow is the adfc-config.xml file. Although you can create additional source files for unbounded task flows, the application combines all source files at runtime into the adfc-config.xml file. Figure displays the diagram for the unbounded task flow from the Fusion Order Demo Application. This task flow contains a number of view activities that are all entry points to the application.
Figure
Unbounded Task Flow in Fusion Order Demo Application
Unbounded Task Flow in Fusion Order Demo
You typically use the unbounded task flow instead of a bounded task flow if:
  • You want to take advantage of ADF Controller features not offered by bounded task flows, such as bookmarkable view activities.
  • The task flow will not be called by another task flow.
  • The application has multiple points of entry. In Figure, the task flow can be entered through any of the pages represented by the view activity icons on the unbounded task flows.

The unbounded task flow cannot declaratively specify parameters. In addition, it cannot contain a default activity, an activity designated as the first to run in the unbounded task flow. This is because the unbounded task flow does not have a single point of entry. To perform any of these requires a bounded task flow.
In order to take advantage of completely declarative ADF Controller transaction and reentry support, use a bounded task flow rather than the unbounded task flow.

18.1.2 About Bounded Task Flows

An ADF bounded task flow is used to encapsulate a reusable portion of an application. A bounded task flow is similar to a Java method in that it:
  • Has a single entry point
  • May accept input parameters
  • May generate return values
  • Has its own collection of activities and control flow rules
  • Has its own memory scope and managed bean lifespan (a page flow scope instance)
The checkout-task-flow activity in Figure is a call to a bounded task flow. The unbounded task flow can call a bounded task flow, but cannot be called by another task flow. A bounded task flow can call another bounded task flow, which can call another and so on. There is no limit to the depth of the calls.
The checkout process is created as a separate bounded task flow, as shown in Figure 
Figure  Checkout Bounded Task Flow in Fusion Order Demo Application
Checkout bounded task flow
The reasons for creating the checkout-task-flow activity as a called bounded task flow are:
  • The bounded task flow always specifies a default activity, a single point of entry that must execute immediately upon entry of the bounded task flow.
    In the checkout task flow, the activity labeled reconcileShoppingCart invokes a method that returns a list of items that an anonymous user (one who has not yet logged in to the application) may have chosen to purchase. Any items chosen before authentication are included in the shopping cart after the user has logged in. Because it is the default activity, the method is always invoked before the shopping cart order page displays.
  • checkout-task-flow is reusable. For example, it can be included in other applications requiring an item checkout process. The bounded task flow can also be reused within the same application.
  • Any managed beans you decide to use within checkout-task-flow can be specified in page flow scope, so are isolated from the rest of the application. These managed beans (with page flow scope) are automatically released when the task flow completes.


Create a Bounded Task Flow:-
 
With the TaskFlow application loaded in JDeveloper, you create a bounded task flow diagram including views, and returns. To do this, perform the following steps:
    ADF task flows provide a modular approach for defining control flow in an application. 

  1. In the Application Navigator, right click the ViewController node and select New from context menu.

    An ADF bounded task flow is used to encapsulate a reusable portion of an application. 

    invoking the New gallery from application navigator
  2. In the New Gallery, click the Web Tier | JSF/Facelets node and select ADF Task Flow.
    new gallery with adf task flow selected
  3. In the Create Task Flow dialog, type emp-update-flow as the File Name. Select the following checkboxes.

    Then click OK.
    Property Value
    Create as Bounded Task Flow Checked
    Create with Page Fragments Checked
    Create Train Checked
    namning the task flow
  4. A new empty task flow diagram displays and a new entry is created in the Application Navigator.
    navigator and blank task flow diagram
  5. Select the View component View icon from the Component Palette and drag and drop it onto the diagram surface.


    The primary type of task flow activity is a view, which displays a JSF page or page fragment. .

    creating a new view on the diagram
  6. Change the default name to intro.
    view on the diagramrenaming view to 'intro'
  7. Create a new view View icon on the diagram next to the intro one.
    creating second view on diagram

    Rename it search.
    renaming view to search
  8. Create a third view view icon on the diagram.
    create a third view on diagram

    Rename it update. Your diagram should look similar to the image below.
    renaming third flow 'update'
  9. Save all your work.

Wednesday 4 May 2016

Programatic handle to ADF Query Component

Programatic handle to ADF Query Component - see Query Input values


You can create ADF Query search forms that will allow users to search based on some input fields. The results of the query can be displayed as ADF Table , form or any other ADF UI Component . In general search forms are based on af:query and af:quickquery components.


ADF Search forms are based on view criteria defined at ADF VO level or implicit view criteria defined by the framework . Once you define the View criteria ,drag and drop it from the data control palette on the the page as ADF Query pane with table . ADF will take care of the rest of the things. Everything will be configured on its own ranging from search button binding  to the particular model and to the table which is being refreshed whenever results are being fetched .

Suppose we may want to modify the query values / see the current query values / validate the user input . we will see how to get handle to the ADF Query component to do this .


you will see the ADF:Query pane code in the page like this :

<af:query id="qryId1" headerText="Search" disclosed="true"
value="#{bindings.VOCriteriaQuery.queryDescriptor}" 
model="#{bindings.VOCriteriaQuery.queryModel}" queryListener="#{bindings.VOCriteriaQuery.processQuery}" 
queryOperationListener="#{bindings.VOCriteriaQuery.processQueryOperation}" resultComponentId="::resId1"/> 

queryListener having an expression that deals with invoking of corresponding binding dynamically. In order to get handle to this component we will write our custom method and bind it to the queryListener.

After modifying it looks like queryListener="#{backingBeanScope.managedBean1.onSearch}"

 The Below custom method will tell you everything in clear

  public void onSearch(QueryEvent queryEvent) {
       
        String EmployeeId = null;
        // Query Event is delivered when a query action is triggered
        QueryDescriptor qd = queryEvent.getDescriptor();
       
        // This line will represent group of criterion objects
        ConjunctionCriterion conCrit = qd.getConjunctionCriterion();
       
        //access the list of all search fields
        List<Criterion> criterionList = conCrit.getCriterionList();

        for (Criterion criterion : criterionList) {
            AttributeDescriptor attrDescriptor =  ((AttributeCriterion)criterion).getAttribute();

            if (attrDescriptor.getName().equalsIgnoreCase("EmployeeId")) { // EmployeeId is one of the query items in the search pane
             EmployeeId  =  (String)((AttributeCriterion)criterion).getValues().get(0);
             
            //This is how we will access the query field
             System.out.println("EmployeeId :" + EmployeeId );

            }
        }


        DCBindingContainer bc =
            (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
        ViewCriteria vc = getViewCriteria(bc, qd);

    System.out.println("View Object"+ vc.getViewObject);

    //Execute the query Listener using EL. This will execute the query component .If u see the exp , this was initially applied to QueryListener.. Later we assigned QueryListener to our custom method.
     
   invokeMethodExpression("#{bindings.VOCriteriaQuery.processQuery}", queryEvent); 
       
    }
    
      //helper method to execute the QueryListener EL

       private void invokeMethodExpression(String expr, QueryEvent queryEvent) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        ELContext elContext = fctx.getELContext();
        ExpressionFactory eFactory =
            fctx.getApplication().getExpressionFactory();
        MethodExpression mexpr =
            eFactory.createMethodExpression(elContext, expr, Object.class,
                                            new Class[] { QueryEvent.class });
        mexpr.invoke(elContext, new Object[] { queryEvent });
    }
 


    private ViewCriteria getViewCriteria(DCBindingContainer bc,
                                         QueryDescriptor qd) {

        Object execBinding =  bc.findExecutableBinding("VOCriteriaQuery"); // This will be seen in the page executable section as we have dropped for af:query
        ViewCriteria vc =
            JUSearchBindingCustomizer.getViewCriteria((DCBindingContainer)execBinding,
                                                      qd.getName());
        return vc;

    }