Monday 22 August 2016

Using f:attribute to pass parameter in ActionEvent and dlelete selected row

f:attribute tag (JSF Tag supported in ADF Faces) is used to pass some additional attribute value to associated component
Sometimes using f:attribute simplify a complex piece of code, this tag has very simple structure. It has two properties

name- Name of tag attribute
value- Value or an EL reference of value

Here in this post we will see how to use this tag with ADF Faces, I am using Departments table of HR Schema and requirement is to delete departments with attribute DepartmentId  greater than 100


So i have added a link in af:table to delete selected department
Now on this delete link action i have to check that DepartmentId for selected row should be greater than 100 and there are multiple way to do this

1. Get current row of iterator and get DepartmentId from that row
2. Get selected row using getSelectedRowKeys


But here i am using f:attribute to get selected DepartmentId, See how to do this



Add f:attribute tag under af:link like this, here i have assigned #{row.DepartmentId} as value reference of f:attribute tag, this will store selected departmentId in attribute


<af:column id="c5">
                        <af:link text="Delete" id="l1"
                                 actionListener="#{viewScope.FAttributeDemoBean.deleteDepartmentAction}">
                            <f:attribute name="DepartmentId" value="#{row.DepartmentId}"/>
                        </af:link>
                    </af:column>

Now see how to get f:attribute value in managed bean and perform delete operation on that basis


import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import oracle.adf.model.BindingContext;

import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;


    /**Get BindingContainer of current view port**/
    public BindingContainer getBindingsCont() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }

    /**
     * Generic Method to execute operation Binding
     * */
    public OperationBinding executeOperation(String operation) {
        OperationBinding createParam = getBindingsCont().getOperationBinding(operation);
        return createParam;

    }

    /**Method to delete Department row on condition basis
     * @param actionEvent
     */
    public void deleteDepartmentAction(ActionEvent actionEvent) {
        //Get attribute value using it's name
        Object obj = actionEvent.getComponent().getAttributes().get("DepartmentId");
        if (obj != null && ((Integer) obj) > 100) {
            // If department id is greater than 100 then call delete operation on it
            executeOperation("Delete").execute();
            executeOperation("Execute").execute();
        } else {
            FacesMessage errMsg = new FacesMessage("Department Id for selected Department is not greater than 100");
            errMsg.setSeverity(FacesMessage.SEVERITY_ERROR);
            FacesContext.getCurrentInstance().addMessage(null, errMsg);
        }
    }

All done , Run application and check (tried deleting Department with DepartmentId 100)


Sunday 21 August 2016

Scroll to particular component using af:scrollComponentIntoViewBehavior tag in ADF Faces

You all must have seen HTML Anchor links, this is actually called link within page and used to navigate between page sections
Same as HTML anchor tag ADF Faces has <af:scrollComponentIntoViewBehavior> tag that allows user to jump to a particular component on page

So in this post i am using 5 images and 5 buttons to navigate to each image, set clientComponent property of all af:image to true because this tag is supported only by client rendered components.

Dropped scrollComponentIntoViewBehavior under all buttons and provided id of respective af:image component
See XML source of page -




<af:panelStretchLayout id="psl1" topHeight="25px" bottomHeight="25px" dimensionsFrom="parent">
                    <f:facet name="bottom">
                        <af:panelGroupLayout id="pgl3" layout="horizontal">
                            <af:button text="Paragliding" id="b4">
                                <af:scrollComponentIntoViewBehavior componentId="i1"/>
                            </af:button>
                            <af:button text="Rope Way" id="b5">
                                <af:scrollComponentIntoViewBehavior componentId="i5"/>
                            </af:button>
                        </af:panelGroupLayout>
                    </f:facet>
                    <f:facet name="center">
                        <af:panelGroupLayout id="pgl1" layout="scroll">
                            <af:image source="#{resource['images:1.jpg']}" id="i1"
                                      inlineStyle="width:700px;height:400px;" shortDesc="Paragliding"
                                      clientComponent="true"/>
                            <af:image source="#{resource['images:3.jpg']}" shortDesc="Rope Way" id="i5"
                                      inlineStyle="width:700px;height:400px;" clientComponent="true"/>
                            <af:image source="#{resource['images:2.jpg']}" id="i2"
                                      inlineStyle="width:700px;height:400px;" shortDesc="Green Ground"
                                      clientComponent="true"/>
                            <af:image source="#{resource['images:8.jpg']}" id="i3"
                                      inlineStyle="width:700px;height:400px;" shortDesc="Beautiful Cottage"
                                      clientComponent="true"/>
                            <af:image source="#{resource['images:9.jpg']}" id="i4"
                                      inlineStyle="width:700px;height:400px;" shortDesc="Sheeps"
                                      clientComponent="true"/>
                        </af:panelGroupLayout>
                    </f:facet>
                    <f:facet name="start"/>
                    <f:facet name="end"/>
                    <f:facet name="top">
                        <af:panelGroupLayout id="pgl2" layout="horizontal">
                            <af:button text="Green Ground" id="b1">
                                <af:scrollComponentIntoViewBehavior componentId="i2"/>
                            </af:button>
                            <af:button text="Beautiful Cottage" id="b2">
                                <af:scrollComponentIntoViewBehavior componentId="i3"/>
                            </af:button>
                            <af:button text="Sheeps" id="b3">
                                <af:scrollComponentIntoViewBehavior componentId="i4"/>
                            </af:button>
                        </af:panelGroupLayout>
                    </f:facet>
                </af:panelStretchLayout>

Page looks like this -

Tuesday 16 August 2016

Iterate over master detail viewObject using view link accessor

Here I am using Departments and Employees table of HR Schema to create Master-Detail relation and due to view link relation, Department viewObject has view link accessor of Employees viewObject


This view link accessor containes rows for corresponding row of master (Departments) viewObject, It returns different rowset (list of Employees) for each record of Departments viewObject and we can programmatically access this view link accessor for each master record


Code in AMImpl to Iterate over Master and Detail view object records



import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.RowSetIterator;
import oracle.jbo.ViewObject;


    /**
     * This is the method to iterate over Departments and corresponding Employees records
     */
    public void iterateMasterDetail() {
        //Get Master ViewObject
        ViewObject deptVo = this.getDepartmentsView();
        //Create iterator to iterate over master viewObject
        RowSetIterator rsi = deptVo.createRowSetIterator(null);

        while (rsi.hasNext()) {
            //Get Master ViewObject Row
            Row departmentsRow = rsi.next();
            System.out.println("Department Name :" + departmentsRow.getAttribute("DepartmentName"));
            //Get Corresponding child viewobject accessor
            RowSet rs = (RowSet) departmentsRow.getAttribute("EmployeesView");

            //Iterate over child viewObject rows for corresponding master record
            while (rs.hasNext()) {
                Row r = rs.next();
                System.out.println("      Employee : " + r.getAttribute("FirstName") + " " +
                                   r.getAttribute("LastName"));
            }
        }
        //Close Master viewObject iterator
        rsi.closeRowSetIterator();
    }

Add this method to client interface of Application Module and Run Application Module to check it

 Output on log

Monday 15 August 2016

Programmatically populate values in a af:selectOneChoice component in ADF

In this tutorial you will see that how to populate selectOneChoice list from managed bean, sometimes we need to use custom list that are not model driven, this scenario can be implemented there

follow steps -

  • First of all create a fusion web application and a page in it
  • Now create a variable of type java.util.List in managed bean, and generate its accessors

  •     List<SelectItem> customList;
    
        public void setCustomList(List<SelectItem> customList) {
            this.customList = customList;
        }
    
        public List<SelectItem> getCustomList() {
            return customList;
        }
    

  • this list contains value of type javax.faces.model.SelectItem; that is supported by af:selectOneChoice
  • now time to add values in list, so to add values in this list i have written this code in getter of variable

  •     public List<SelectItem> getCustomList() {
            if (customList == null) {
                customList = new ArrayList<SelectItem>();
                customList.add(new SelectItem("i1","Item 1"));
                customList.add(new SelectItem("i2","Item 2"));
                customList.add(new SelectItem("i3","Item 3"));
                customList.add(new SelectItem("i3","Item 4"));
                customList.add(new SelectItem("i5","Item 5"));
        }
            return customList;
        }
    

  • Managed bean part is done, now add this to view layer



  • Drop choice list in page from component palette
  •  Now bind choice list to bean List


  • See the page source after whole setup-

  • <?xml version='1.0' encoding='UTF-8'?>
    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
              xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
        <jsp:directive.page contentType="text/html;charset=UTF-8"/>
        <f:view>
            <af:document title="listPage.jspx" id="d1">
                <af:form id="f1">
                    <af:panelGroupLayout id="pgl1" layout="vertical" halign="center">
                        <af:spacer width="10" height="10" id="s1"/>
                        <af:selectOneChoice label="Custom List" id="soc1" contentStyle="font-weight:bold;color:darkgreen;">
                            <f:selectItems value="#{ListPolulatebean.customList}" id="si1"/>
                        </af:selectOneChoice>
                    </af:panelGroupLayout>
                </af:form>
            </af:document>
        </f:view>
    </jsp:root>
    

  • Run this page and see programmatic choice list-

Monday 1 August 2016

Range validator Using ADF BC Declarative Built-in Rules

The "Range Validator" is another entity attribute validator which can be be defined at either the entity or attribute level but pertains to an entity attribute just like the "Compare", "Key Exists", "Length" and "List" validators.

As it's name suggests you can use the "Range" validator to ensure that an attribute value falls either within or outside some specified minimum and maximum values. For example, ensure that an employee's salary is between $10,000 and $20,000.

For the purpose of demoing the "Range" validator I have created an ADF Fusion Web Application and created the basic business components that I will be using in this demo; an entity object based on the Employees HR table, a default view object based on the Employees entity object and a default application module.

Next let’s define a "Range" validator on the Employees entity object to ensure that an employee's salary is within a specified minimum and maximum values. So on the  “Business Rules” tab of the Employees entity object, click on the green plus icon “Create new validator”.  This will open the “Add Validation Rule” editor for defining the validation specifics.

In the “Type” combo select “Range”, select the attribute that you want to define the validator, in my demo it's the "Salary" attribute and then select an operator, either Between or NotBetween. In my demo I have selected the "Between" operator.

Under the range section define a minimum and a maximum value.

In the "Failure Handling" tab define a failure message and click "OK". In my example I have used a message token expression to construct a dynamic error message, passing to the failure message the new salary value using the newValue keyword.


If you inspect the Employee’s entity source code you will see that JDeveloper added a RangeValidationBean tag to the XML entity definition file.

Run the Application module to test your "Range" validator and try to update an employee's salary to a value greater than 20,000. The "Range" validator should have fired displaying your error message.

Download sample application: Range Validator

List validator, Using ADF BC Declarative Built-in Rules

The "List Validator" is yet another validator that can be defined at either the entity level or the attribute level but pertains to an entity object attribute to ensure that a value is either in a list or not.

So the "List Validator" compares an attribute against a list of

a) literal values ensuring that the value is in or not in the list of literal values that you define,
b) against an SQL query ensuring that the value is in or not in the first column of the query's result set,
c) against a view attribute ensuring that the value is in or not in the attribute of the specified view object or
d) against a view accessor ensuring that the value is in or not in the specified attribute in all rows of the view object retrieved by the view accessor.

Let's see a demo of the "List Validator". I have created a new ADF Fusion Web Application and created the basic business components that I will be using in this demo, an entity object based on the Departments HR table, a view object based on the Departments entity object and a default application module.


Next let’s define a "List" validator on the Departments entity object to ensure that a department is in the list of literal values that we will define. So on “Business Rules” tab of the Departments entity object, click on the green plus icon “Create new validator”.  This will open the “Add Validation Rule” editor for defining the validation specifics.

In the “Type” combo select “List” and select the attribute on which you want to define the list validator. In my demo I have selected “DepartmentName”. Select the operator (In or NotIn) and the List Type (Literal Values, Query Result, View Object Attribute or View Accessor Attribute). In my demo i have selected the "In" operator and "Literal Values" as the List Type.

In the "Enter List of Values" text box enter the possible values a department can have (enter each values without quotes on a new line).
In the "Failure Handling" tab define a failure message and click "OK". In my example I have used a message token expression to construct a dynamic error message, passing to the failure message the department name.

If you inspect the Department’s entity source code you will see that JDeveloper added a ListValidationBean tag to the XML entity definition file.
Before testing our validator please ensure that your application module has the Departments view selected under the “Data Model”.

To test your validator, run the Application module and try to update a department's name to "Sales" (if you recall i did not include sales in my list of allowed literal values). You should get your custom dynamic error message displayed.

Please note that list validators based on SQL queries or View Object attributes retrieve all rows of a query each time a validation is perform, therefore you should be very careful when you choose to use these list types. It it recommended that you use these list types only for relatively small value sets.

Download sample application: List Validator

Length Validator Using ADF BC Declarative Built-in Rules

The “Length Validator” is another validator that can be defined at either the entity level or the attribute level but pertains to an entity object attribute to compare the number of characters or bytes in an attribute value against a specified length.

For the purpose of this demo I have created a new ADF Fusion Web Application and created the basic business components that I will be using in this demo, an entity object based on the Employees HR table, a view object based on the Employees entity object and a default application module.


Next let’s define a “Length” validator on the Employees entity object to ensure that an employee’s first name is less than 10 characters. So on “Business Rules” tab of the Employees entity object, click on the green plus icon “Create new validator”.  This will open the “Add Validation Rule” editor for defining the validation specifics.

In the “Type” combo select “Length” and select the attribute on which you want to define the length validator. In my demo I have selected “FirstName”. Select the operator (Equals, NotEquals, LessThan, GreaterThan, LessOrEqualTo, GreaterOrEqualTo, Between), the comparison type (either Character or Bytes) and set the length value.

In the "Failure Handling" tab define a failure message and click "OK". In my example I have used a message token expression to construct a dynamic error message, passing to the failure message the employee’s first name.

If you inspect the Employee’s entity source code you will see that JDeveloper added a LengthValidationBean tag to the XML entity definition file.

Before testing our validator please ensure that your application module has the Employees view selected under the “Data Model”.

To test your validator, run the Application module and try to update an employee’s first name, providing a name greater than 10 characters. You should get your custom dynamic error message displayed.

Download sample application: Length Validator

Key Exists Validator, Using ADF BC Declarative Built-in Rules

The “Key Exists” Validator is validator that can be defined at either the entity level or the attribute level but pertains to an entity object attribute to check whether a key exists based on a primary key, foreign key or an alternate key. The “Key Exists” validator will check first the cache querying rows not committed yet to the database and if the key is not found in the cache will run a check in the database.
So let’s start by creating a new ADF Fusion Web Application and create the basic business components that we will be using in this demo, two entity objects based on the Countries and Regions HR tables, their associated view objects and a default application module.
Next let’s define a “Key Exists” validator on the Countries entity object. So on “Business Rules” tab of the Countries entity object, click on the green plus icon “Create new validator”.  This will open the “Add Validation Rule” editor for defining the validation specifics.
In the “Type” combo select “Key Exists” and you will see that in the “Validation Target Type“ there are three options; to target the validation at the “Entity Object” level meaning that this validation will be used for all view objects that use this entity attribute, “View Object” or “View Accessor”. In my demo I will be targeting my “Key Exists” validator at the entity object.
In the “Association Name“ combo you will get displayed with all the associations pertaining the entity object. In my case I have only one association, the “CountryRegFkAssoc”.
 
In the "Failure Handling" tab define a failure message and click "OK". In my example I have used two message token expressions to construct a dynamic error message, passing to the failure message the country’s name and country’s region id.
Before testing our validator please ensure that your application module has the Countries view and Regions View selected under the “Data Model”.
To test our newly defined "Key Exists Validator" run the Application module and and try to create a country with an invalid region id. You should get your custom dynamic error message displayed.
Now create a new region, do not commit the new region and try to create a new country based on the new region’s id. The “Key Exists” validator will check the cache and will identify that the region id exists (even though it’s not committed in the database).
 Download sample application: Key Exists Validator

Contact Me

Name

Email *

Message *