Please disable your adblock and script blockers to view this page

Search this blog

Wednesday, 30 December 2015

Create REST Web Service with Application Module declaratively in ADF 12.2.1

REST stands for Representational State Transfer, REST is an architectural style not a protocol as SOAP that's why it can use any other protocol like SOAP, HTTP etc.
REST requires less bandwidth and resources (lighter) than SOAP

New ADF 12.2.1 supports creating RESTful web services directly from Application Module, In previous versions we have to do everything manually
See- Create RESTful services on top of ADF Business Components

Tuesday, 22 December 2015

Create SOAP Web Service with Application Module quickly in ADF 12.2.1


SOAP stands for Simple Object Access Protocol, a protocol to exchange information in XML format between two applications over HTTP. This protocol is used to create ,access and consume web services.

SOA (Service Oriented Architecture) focuses on re-usability and exposing application module as web service makes it's methods and objects accessible from any device , any platform and these methods and objects can be further used by any other application

Friday, 18 December 2015

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

Tuesday, 15 December 2015

Checkbox ValueChangeListener problem in af:table - ADF 12.1.3


Recently i faced a problem while working on one of my application, it has an editable table having one check box column and a valueChangeListener is defined on that check box.

Problem is that whenever user selects any row of table , valueChangeListener of check box is called every time for all editable rows, this is weird because VCL should execute only when user selects or deselects check box

Monday, 14 December 2015

Responsive UI with new af:matchMediaBehavior in ADF 12.2.1.0


Jdeveloper and ADF 12.2.1 comes with many new features ( see these posts-
New look of dvt:funnelChart for Data Visualization in Jdeveloper 12.2.1.0
New look of dvt:pieChart as donut chart for Data Visualization in Jdeveloper 12.2.1.0  )
and supports responsive UI design.
Masonry Layout and MatchMediaBehaivor tag is introduced to support responsive UI design

af:matchMediaBehavior allows developer to control properties of components according to screen size. It uses CSS media queries to detect screen size and changes value of specified property of component

Friday, 4 December 2015

New look of dvt:pieChart as donut chart for Data Visualization in ADF 12.2.1.0


Oracle Jdeveloper 12C (12.2.1.0) documentation tells about a new enhancement in look of pie chart

We can now design donut chart using dvt:pieChart , innerRadius property allows us to create donut chart look on the base of default pie chart.
Donut chart is nothing just a variation of pie chart that show data in sections of a circle, I believe everyone knows how to design a pie chart in ADF Faces

Thursday, 26 November 2015

Responsive UI with new Masonry Layout in ADF 12.2.1.0


What is Responsive UI and Why it is Important-

User interface or view of website or web application changes as the screen size of device changes
This type of UI is called Responsive and it is important to design responsive UI for your application because each device have different screen dimension and you can not restrict user to use any specific device to view your application . This is very basic requirement of web development that UI should look good on Mobile, PC, Tablet or any other device

Saturday, 21 November 2015

New look of dvt:funnelChart for Data Visualization in ADF 12.2.1.0

A couple of weeks ago Oracle Jdeveloper and ADF team released new version of Jdevloper 12.2.1 with many cool features
New funnel chart (<dvt:funnelChart>) is introduced instead of funnel graph (<dvt:funnelGraph>)
Old funnel graph looks like this-



Funnel chart is used to show visual distribution of different steps of any cycle
What docs says-

A chart representing data related to steps in a process. The steps appear as vertical slices across a cone-shaped section which represent stages of a procees or target and actual values, showing levels by color.

Here we see how to use this new component to design a better UI, For this I have created a viewObject using this sql




SELECT A.DEPARTMENT_NAME, 
B.FIRST_NAME ||' '|| B.LAST_NAME AS EMPLOYEE_NAME,
B.SALARY,
100000 AS TARGET
FROM DEPARTMENTS A, EMPLOYEES B
WHERE A.DEPARTMENT_ID=B.DEPARTMENT_ID;

Then go to datacontrol and drop this viewObject on page as chart

In dialog select Funnel on left panel and you can select horizontal or vertical layout of funnel at right side


This is the configuration screen for Funnel. Here we can select Actual and Target values and Section Name appears on view port


Click on ok button of this dialog and your Funnel chart is ready
See generated XML-


<dvt:funnelChart id="funnelChart2" var="row" value="#{bindings.DeptEmpView11.collectionModel}">
                        <dvt:funnelDataItem id="di2" targetValue="#{row.Target}" label="#{row.DepartmentName}"
                                            value="#{row.Salary}"/>
                    </dvt:funnelChart>

Now run this application and see how it appears :)


Wow.. it's good :)
If we want to show only Departments Name with salary (No comparison with Target) then just remove this targetValue from xml code and then it looks like this


There are lots of properties to change it's layout , 3D effect , Title , FootNote etc. Try each one and see how it affects Funnel

Cheers :) Happy Learning

Tuesday, 3 November 2015

ADF Basics: Using f:attribute to pass parameter in ActionEvent

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

Friday, 30 October 2015

Read data from Google Spreadsheet without authentication using Java

Google Spreadsheets provides a way to create, edit, save spreadsheets online.
The Google Sheets API (formerly called the Google Spreadsheets API) lets you develop client applications that read and modify worksheets and data in Google Sheets.
Read More about Sheets API

Let's see how to use this API to read data from Spreadsheet, here i am going to use Spreadsheet version 3.0 , if this link doesn't work then check on GitHub , from here you will get  client library for all Google APIs

Saturday, 24 October 2015

Oracle JDeveloper and Oracle ADF 12c (12.2.1.0.0) out (bug fixed and lots of new features introduced)

Time to check new Jdeveloper 12.2.1 , Wait is over Check out new features :)
Download- Oracle JDeveloper 12g (12.2.1.0.0)

1. Alta UI is now default skin for all ADF Faces components , previously it was Skyros
Read more about Oracle Alta UI Design Patterns

4. In Data Visualization some change done in Pie Chart and Thematic Map. New component NBox and funnel chart is introduced

Monday, 19 October 2015

Get domain information (WHOIS) using Apache Commons Net API- ADF & Java

We can get any domain information using Apache commons net library. It supports various protocols and WHOIS information is one of them

WhoisClient class provides access of domain information
See what docs says -

The WhoisClient class implements the client side of the Internet Whois Protocol defined in RFC 954. To query a host you create a WhoisClient instance, connect to the host, query the host, and finally disconnect from the host. If the whois service you want to query is on a non-standard port, connect to the host at that port.

Download required library or if this link doesn't work then goto API page and download from there

This simple java method will fetch information of domain using Apache library

Wednesday, 14 October 2015

Blog Completed 3 awesome years

I am happy to tell you that my (Ashish Awasthi's Blog) blog has completed 3 years today.
On 14-October-2012 i have posted my first blog post on ADF Basics: Show inline Message in Oracle ADF and till now blog has more than 180 posts on ADF, Java, JavaScript, jQuery etc.

I started blogging to help Java & ADF developers, to share what i have learnt and still trying to do same
Initially started this blog with blogspot.com - oracleadf-java.blogspot.com & after one year changed it to a custom domain www.awasthiashish.com

It has 1700+ fan following on facebook -Facebook Page
Now i am trying to put some more interesting stuff to learn, Keep an eye on blog

Taking as a whole it was awesome journey of 3 years :) Thanks for your support , Keep reading Keep Learning :)

Now say Happy B'day to Ashish Awasthi's Blog  :)



Wednesday, 7 October 2015

ADF Basics: Reorder ADF table column using DisplayIndex property

This post is about a very simple use case that is reordering of af:table column at run time. 
Ordering of columns in af:table is controlled by DisplayIndex property of af:column
Check what docs says-

Default Value: -1

The display order index of the column. Columns can be re-arranged and they are displayed in the table based on the displayIndex. Columns are sorted based on the displayIndex property, columns without displayIndex are displayed at the end, in the order in which they appear. The displayIndex attribute is honored only for top level columns, since it is not possible to rearrange a child column outside of the parent column.
Not supported on the following renderkits: org.apache.myfaces.trinidad.core

We can set DisplayIndex property for all columns in a sequence (1,2,3 etc) that we want to see on page

Monday, 5 October 2015

Allow user input in Jdeveloper for Java applications, Using Java Scanner Class to take input from console

Sometimes we have to take input from Keyboard when we use Scanner or BufferedReader class.
and to take input from Jdeveloper we have to change a setting to allow user input in Jdeveloper.

Let's take an example of java.util.Scanner class-

package client;

import java.util.Scanner;

public class UserInput {
    public UserInput() {
        super();
    }

    public static void main(String[] args) {
        System.out.println("Please Enter your Name-");
        Scanner sc = new Scanner(System.in);
        String name = sc.next();
        System.out.println("Your Name is " + name);
    }

}

Tuesday, 22 September 2015

Using popupFetchListener to execute method on popup launch in Oracle ADF

Everyone must have used ADF Faces popup component , this is one of most used container to show information on top of page
In this post i am talking about popup fetch event suppose we have to perform some operation before opening popup like filtering data inside popup . We can do this by capturing popup fetch event, if you have checked af:popUp documentation then you must have seen concept of popupFetchListener

From Docs-
The PopupFetchEvent is one of two server-side popup events but doesn't have a corresponding client event. The popup fetch event is invoked during content delivery. This means that the event will only queue for popups that have a contentDelivery type of lazy or lazyUncached. Another caveat is that the event will only work when the launch id is set. This is automatically handled by the af:showPopupBehavior but must be provided as a popup hint if programmatically shown.

So here we will see -

How to use popupFetchListener to filter data inside popup ?
How to execute some operation before opening popup ?
How to call AMImpl method before launching popup?

Monday, 14 September 2015

ADF Basics: Call PL/SQL Stored function in ADF Application


This post is about calling stored function in ADF Application , a very basic requirement. Many times we need to call a PL/SQL function in ADF app for any specific requirement.
In this post i am discussing same so for that i have created a PL/SQL function that takes EmployeeId as input parameter and return it's Employees Name (Using Oracle HR Schema)


CREATE OR REPLACE FUNCTION FN_GET_EMPNAME(EMP_NO NUMBER)
RETURN VARCHAR2 IS
   EMP_NAME VARCHAR2(50) := 'N';
BEGIN
   SELECT FIRST_NAME||' '||LAST_NAME into EMP_NAME
   FROM EMPLOYEES WHERE EMPLOYEE_ID=EMP_NO;
   
   RETURN EMP_NAME;
END;

Thursday, 10 September 2015

Jdeveloper installation folder size increasing beyond limit , Reason was hprof (Heap Profiling) files

Recently i faced a problem, i was lacking space on my C drive so  checked all directories and found that the size of Jdeveloper 12.1.3 installation folder Oracle-->Middleware  was approx 30 GB . This is not expected as Jdev. takes approx 1.5 to 2 GB space only


Then i found some java_pidXXXX.hprof file that was taking lot of space in this folder

Saturday, 5 September 2015

Apply ValueChangeListener to programmatically created ADF Faces components

Again a post in series of  Working with ADF Faces Components programmatically
Previously i have posted about Getting value , Applying Action Listener , Applying Client/Server Listener, Creating and applying client Attributes, Setting value expression , Applying Validation to programmatically created component
Now this post post is about applying Value Change Listener to a component that is created at run time
See how to do this (Jdev 12.1.3)-
  • First created a FusionWebApplication and a page in viewController project
  • Dropped a button on page , on this button action i will create an inputText programmatically and assign Value Change Listener method reference to it
  • To create new inputText i have added following code (described in previous post)

Tuesday, 1 September 2015

Apply Validator to programmatically created ADF Faces components

Again a post in series of  Working with ADF Faces Components programmatically
Previously i have posted about Getting value , Applying Action Listener , Applying Client/Server Listener, Creating and applying client Attributes, Setting value expression  to programmatically created component
Now this post post is about applying Validator to a component that is created at run time
See how to do this (Jdev 12.1.3)-
  • First created a FusionWebApplication and a page in viewController project
  • Dropped a button on page , on this button action i will create an inputText programmatically and assign validator method reference to it
  • To create new inputText i have added following code (described in previous post)

Friday, 28 August 2015

ADF Basics: Using setPropertyListener to set value in memory scope variables

Soemtimes we need to set a value in memory scope variable on some event
In ADF af:setPropertyListener does this for you declaratively

The setPropertyListener tag provides a declarative syntax for assigning values when an event fires. The setPropertyListener implements the listener interface for a variety of events, to indicate which event type it should listen for set the 'type' attribute.

Read more about <af:setPropertyListener>

Tuesday, 25 August 2015

Facebook, Twitter, Google - Create large share buttons using JavaScript

This post is not like my other posts (ADF & Java), It is about creating custom large share buttons for Facebook, Twitter and Google+
Actually this share functionality of social networking sites (Facebook, Twitter, Google+ etc) works on a particular url pattern

Let's take example of Facebook , to share any url on Facebook just pass that url as a parameter in this url
http://www.facebook.com/share.php?u=url
See when i open this url on browser (I have passed www.awasthiashish.com in url parameter)
http://www.facebook.com/share.php?u=www.awasthiashish.com , it shows standard Facebook share page

Thursday, 20 August 2015

Set EL expression in value (properties) of programmatically created ADF Faces component


When we are working with ADF Faces components programmatically then we  create , set styles,set value of that component from managed bean
This post is about setting an expression as component value that will be resolved at run time and return desired value

Monday, 17 August 2015

Showing HashMap values in af:table using af:iterator

Previously i have posted about populating af:table programmatically using List Data Structure
Populate af:table programmatically from managead bean using POJO

This post covers same topic but this time requirement is different , we have a HashMap in managed bean and requirement is to show it's values on page in a table view
See Managed Bean code-


    //HashMap and it's accessors
    private HashMap<String, String> valMap = new HashMap<String, String>();

    public void setValMap(HashMap valMap) {
        this.valMap = valMap;
    }

    public HashMap getValMap() {
        return valMap;
    }
    // Object array to store key values of HashMap
    public Object[] getKeySet() {
        return getValMap().keySet().toArray();
    }


Added two inputText on page and a button to add new key and value to HashMap,




<af:panelFormLayout id="pfl1">
                    <af:inputText label="Key" id="it1" contentStyle="width:100px;"
                                  binding="#{viewScope.ShowHashMapAsTable.keyTextBind}"/>
                    <af:inputText label="Value" id="it2" contentStyle="width:100px;"
                                  binding="#{viewScope.ShowHashMapAsTable.valueTextBind}"/>
                    <af:button text="Add" id="b1" actionListener="#{viewScope.ShowHashMapAsTable.addValuesToMap}"/>
                </af:panelFormLayout>


Now code on button that get value of both inputText using component binding and add it to HashMap, at run time this form will be used to add new values to HashMap and table


    //Component Binding of inputText to get values
    private RichInputText keyTextBind;
    private RichInputText valueTextBind;

    public void setKeyTextBind(RichInputText keyTextBind) {
        this.keyTextBind = keyTextBind;
    }

    public RichInputText getKeyTextBind() {
        return keyTextBind;
    }

    public void setValueTextBind(RichInputText valueTextBind) {
        this.valueTextBind = valueTextBind;
    }

    public RichInputText getValueTextBind() {
        return valueTextBind;
    }

    /**Add new value to HashMap
     * @param actionEvent
     */
    public void addValuesToMap(ActionEvent actionEvent) {
        if (keyTextBind.getValue() != null && valueTextBind.getValue() != null) {
            valMap.put(keyTextBind.getValue().toString(), valueTextBind.getValue().toString());

        }
    }


Now Bean Part is done , see how to configure af:table to show HashMap values, table is mapped to array of keySet and an iterator is used inside table that derives value using key attribute -
#{cVal[row]}


<af:table var="row" rowBandingInterval="0" id="t1" value="#{viewScope.ShowHashMapAsTable.keySet}"
                              partialTriggers="::b1">
                        <af:iterator id="i1" value="#{viewScope.ShowHashMapAsTable.valMap}" var="cVal">
                            <af:column sortable="false" headerText="Key" id="c2">
                                <af:outputText value="#{row}" id="ot4" inlineStyle="font-weight:bold;color:darkblue;"/>
                            </af:column>
                            <af:column sortable="false" headerText="Value" id="c1">
                                <af:outputText value="#{cVal[row]}" id="ot3"/>
                            </af:column>
                        </af:iterator>
                    </af:table>


Now all done , run and check the application
 Add New Value (1)
  Add New Value (2)

Sample Application- Download (Jdev 12.1.3)
Cheers :) Happy Learning

Saturday, 8 August 2015

Set ADF Faces Component properties using custom javascript

This post is about using JavaScript in ADF Faces to change default properties , sometimes using JavaScript can make task easier and all scenarios covered in this post are based on very common requirement. One important point is - set clientComponent property of component to true when using JavaScript on that
Why this is important ? (Check what docs say)

whether a client-side component will be generated. A component may be generated whether or not this flag is set, but if client Javascript requires the component object, this must be set to true to guarantee the component's presence. Client component objects that are generated today by default may not be present in the future; setting this flag is the only way to guarantee a component's presence, and clients cannot rely on implicit behavior. However, there is a performance cost to setting this flag, so clients should avoid turning on client components unless absolutely necessary

Read more about clientComponent property - Understanding ADF Faces clientComponent attribute


Set panel group layout properties-


Use this JavaScript function to set panel group layout's layout and other properties

 <!--Function to set panelGroupLayout properties-->
              function changeGroupLayout(evt) {
                  var pgl = AdfPage.PAGE.findComponent('pgl1');
                  pgl.setProperty("layout", "vertical");
                  pgl.setProperty("inlineStyle", "background-color:red");
              }

I have called this function using client listener on a image that is inside my panel group layout

<af:panelGroupLayout id="pgl1" layout="horizontal" clientComponent="true">
                    <af:image source="#{resource['images:5-10.jpg']}" id="i1" inlineStyle="width:250px;height:200px;"/>
                    <af:image source="#{resource['images:13.jpg']}" id="i2" inlineStyle="width:250px;height:200px;">
                        <af:clientListener method="changeGroupLayout" type="dblClick"/>
                    </af:image>
                    <af:image source="#{resource['images:1.jpg']}" id="i3" inlineStyle="width:250px;height:200px;"/>
                </af:panelGroupLayout>

Initially group layout is horizontal-




After executing JavaScript on double click on second image-



Set input component property (inlineStyle, contentStyle, value etc)-


This function is same as previous one , this function sets value in input text , changes it's contentStyle

<!--Function to set af:inputText properties-->
              function changeInputText(evt) {
                  var iText = AdfPage.PAGE.findComponent('it1');
                  iText.setProperty("value", "Ashish Awasthi");
                  iText.setProperty("contentStyle", "background-color:red;color:white;font-weight:bold;");

              }

Called this function on double click event in inputText-

<af:inputText label="Label 1" id="it1" clientComponent="true" unsecure="disabled">
                        <af:clientListener method="changeInputText" type="dblClick"/>
              
                    </af:inputText>


Output is like this-
 on double click inside inputText

In same way we can set disabled property of component . It is a secure property of component , that should not be changed from a client side event normally but if this is a requirement then we have to set disabled in unsecure property of input component. Only disable property is supported as of now
Read more about this property -<af:inputText>


Set panelSplitter width according to browser window width-


This JavaScript function divides af:panelSplitter in equal parts to fit in browser

 <!--Function to set panel Splitter position-->
              function changePanelSpliterPosition(evt) {
                  var width = window.innerWidth;
                  var ps = AdfPage.PAGE.findComponent('ps1');
                  ps.setProperty("splitterPosition", width / 2);
              }

In same way try setting other properties of different components. Soon i will update this post with some more JavaScript functions and examples

Cheers :)  Happy Learning

Monday, 3 August 2015

Iterate over HashMap to get Key and Value in Java , Add records to HashMap


Iterating over HashMap is not same as other collections , It's a bit tricky than normal iteration ;)
See in this code -
How to add values to HashMap ?
and How to iterate over HashMap to get Key and Values?






package client;

import java.util.HashMap;
import java.util.Iterator;

public class IterateHashMap {
    public IterateHashMap() {
        super();
    }

    public static void main(String[] args) {
        HashMap<Integer, String> mapVal = new HashMap<Integer, String>();

        //Add values to Map
        mapVal.put(1, "value 1");
        mapVal.put(2, "value 2");
        mapVal.put(3, "value 3");
        mapVal.put(4, "value 4");

        //Create Iterator from keySet
        Iterator iter = mapVal.keySet().iterator();
        //Iterate over hashmap to get key
        while (iter.hasNext()) {
            int key = (Integer) iter.next();
            //Use this key to find value
            String value = mapVal.get(key).toString();
            System.out.println("**KEY**  " + key + " AND VALUE**  " + value);
        }

    }
}


Cheers :) Happy Learning

Saturday, 1 August 2015

ADF Baiscs: Define and remove named bind variable in viewObject at runtime programmatically

This post is about creating named bind variable in viewObject at run time and filter viewObject using this bind variable in WHERE Clause of ViewObject programmatically .

Defining WHERE Clause and Bind Variable name and default value -

        //Get ViewObject
        ViewObject vo = iter.getDepartments();

        //Apply desired WHERE Clause and declare bind variable name
        vo.setWhereClause("DEPARTMENT_NAME=:BindDepartmentName");

        //Define this variable as ViewObject Bind Variable , You can also set default value for this
        vo.defineNamedWhereClauseParam("BindDepartmentName", "Purchase", null);

        // Execute ViewObject to finally apply where clause
        vo.executeQuery();




Setting value of Bind Variable-


        //Setting Value of Bind Variable
        vo.setNamedWhereClauseParam("BindDepartmentName", "Finance");
        vo.executeQuery();


Getting value of Bind Variable-


        //Get value of Bind Variable
        vo.getNamedWhereClauseParam("BindDepartmentName");


Removing WHERE Clause and Bind Variable after use-


        //Remove where clause
        vo.setWhereClause(null);
        //Remove Bind Variable
        vo.removeNamedWhereClauseParam("BindDepartmentName");
        vo.executeQuery();

Cheers :) Happy Learning

Saturday, 25 July 2015

ADF Skinning : Change label, content, design and 'Update' button style of af:inputFile

This post is about skinning af:inputFile, see how default inputFile looks on page



See how ADF Skin changes it's appearance :)
Change basic inline style of af:inputFile (background color and design) :

/**Skin Selector to change inline style of af:inputFile**/
af|inputFile {
    background-color: Green;
    border-radius: 20px 20px 20px 20px;
    padding: 5px;
}

Output on page-

Change label style of af:inputFile :


/**Skin Selector to change label style of af:inputFile**/
af|inputFile::label {
  font-weight:bold;
  color:white;
  font-family: cursive;
}

Output on page-





Change content style of af:inputFile (background color, design of content only) :


/**Skin Selector to change content style of af:inputFile**/
af|inputFile::content {
    color: #ff6363;
    font-weight: bold;
    border-color: #79bc79;
    border-style: solid;
    border-width: thin;
    border-radius: 15px 15px 15px 15px;
    padding: 5px;
    background-color: #d6ffd6;
    font-family: cursive;
}


Output on page-

After selecting a file, update button appears -


On click of update button a popup with af:inputFile appears-



Change update button style of af:inputFile:


/**Skin Selector to change style of update button of af:inputFile**/
af|inputFile af|commandButton {
    color: white;
    font-weight: bold;
    background: #00b55a;
    border-radius: 15px 15px 15px 15px;
    font-family: cursive;
}

/**Skin Selector to change style of update button of af:inputFile in case of hover**/
af|inputFile af|commandButton:hover {
    color: white;
    font-weight: bold;
    background: #940000;
    border-radius: 15px 15px 15px 15px;
    font-family: cursive;
}


Output on page-
On hover-
Cheers :) Happy Learning
o

Friday, 17 July 2015

Apply sorting to POJO based af:table programmatically , Using custom sort listener in ADF

Again a post about POJO based table , previously i have posted about-

1.Populating and adding records in POJO based table
Populate af:table programmatically from managead bean using POJO
2. Gettting selected rows from POJO based table
Get selected row (single/multiple) from POJO based table in ADF

This post is about applying sorting to POJO based table , when we drop a viewObject as af:table on page then framework provides sorting and filtering features declaratively, but when populating table from managed bean using List(POJO) then it is not there so we have to do it manually

To understand this post completely , go through previous posts and check attached application there
I have used a PersonBean java bean class to contain columns of table or you can say there is a List of PersonBean type that populates data in af:table. (This is the basic information about application)




Now what to do , see step by step implementation-
  • Select table on page editor and create a sortListener in managed bean to handle sortEvent


  • Now what we have do in sort listener ?
    1.Get active sort criteria using sortEvent
    2.Remove that sort criteria
    3.Sort List Data Structure that is used to populate af:table
    4.Apply sort criteria again on af:table

    See code written in managed bean-

  •     //List to store sort criteria
        private List<SortCriterion> sortedTableList = new ArrayList<SortCriterion>();
    
        public void setSortedTableList(List<SortCriterion> sortedTableList) {
            this.sortedTableList = sortedTableList;
        }
    
        public List<SortCriterion> getSortedTableList() {
            return sortedTableList;
        }
    
        /**Custom Sort Listener for POJO based af:table
         * @param sortEvent
         */
        public void tableSortListener(SortEvent sortEvent) {
            //Get active sortCriteria on table
            List<SortCriterion> activeSortCriteria = sortEvent.getSortCriteria();
            SortCriterion sc = activeSortCriteria.get(0);
            // Remove active criteria from table
            this.removeSortCriteria(sc);
            //Sort List that populates table using Comparator interface
            applySortAsPerColumn(sc.getProperty());
    
            // Add the current criteria to the list
            this.sortedTableList.add(0, sc);
            // Apply sort criteria to table
            RichTable richTable = (RichTable) sortEvent.getComponent();
            richTable.setSortCriteria(sortedTableList);
    
        }
    
        /**Removes sort criteria*/
        private boolean removeSortCriteria(SortCriterion sortCriterion) {
            //Checks that if any sortCirteria is present in list , if yes then remove it
            if (sortedTableList != null && sortedTableList.size() > 0) {
                for (SortCriterion sc : sortedTableList) {
                    if (sc.getProperty().equals(sc.getProperty())) {
                        sortedTableList.remove(sc);
                        return true;
                    }
                }
            }
            return false;
        }
    

    Now logic to apply programmatic sort starts from here , we have to sort List using Java Comparator interface
    To Read more - How to sort ArrayList using Comparator?     Comparator interface

        private void applySortAsPerColumn(String criteria) {
            //Get List that populates table
            List<PersonBean> list = getPersonList();
            //Check which column's sorting is triggered from UI
            //and then sort list on basis of that attribute
            //Sorting of collection makes use of Comparator interface, Read about it
            if ("name".equalsIgnoreCase(criteria)) {
                Collections.sort(list, new ProgTableBean.PersName());
            } else if ("mobNo".equalsIgnoreCase(criteria)) {
                Collections.sort(list, new ProgTableBean.MobNo());
            } else if ("salary".equalsIgnoreCase(criteria)) {
                Collections.sort(list, new ProgTableBean.Salary());
            }
        }
        // Comparator for all attributes to sort List according to different attributes
    
        public static class PersName implements Comparator<PersonBean> {
            private int flag = 1;
    
            @Override
            public int compare(PersonBean o1, PersonBean o2) {
                return flag * o1.getName().compareTo(o2.getName());
            }
        }
    
    
        public static class MobNo implements Comparator<PersonBean> {
            private int flag = 1;
    
            @Override
            public int compare(PersonBean o1, PersonBean o2) {
                System.out.println("In 2**");
                return flag * o1.getMobNo().compareTo(o2.getMobNo());
    
            }
        }
    
    
        public static class Salary implements Comparator<PersonBean> {
            private int flag = 1;
    
            @Override
            public int compare(PersonBean o1, PersonBean o2) {
                return flag * o1.getSalary().compareTo(o2.getSalary());
            }
        }
    


  • Now on page ,select table and set sortable true for each column and set sortProperty same as column name
    Check af:table source after setting all properties

  • <af:table var="row" rowBandingInterval="1" id="t1" value="#{viewScope.ProgTableBean.personList}"
                              partialTriggers="::b1" rowSelection="multiple" binding="#{viewScope.ProgTableBean.tableBind}"
                              selectionListener="#{viewScope.ProgTableBean.tableSelection}"
                              sortListener="#{viewScope.ProgTableBean.tableSortListener}">
                        <af:column sortable="true" headerText="Name" id="c1" width="150" sortProperty="name">
                            <af:outputText value="#{row.name}" id="ot1"/>
                        </af:column>
                        <af:column sortable="true" headerText="Mobile Number" id="c2" sortProperty="mobNo">
                            <af:outputText value="#{row.mobNo}" id="ot2"/>
                        </af:column>
                        <af:column sortable="true" headerText="Salary" id="c3" align="right" sortProperty="salary">
                            <af:outputText value="#{row.salary}" id="ot3"/>
                        </af:column>
                    </af:table>
    

  • All done :) , Run and check application


Sample ADF Application -Download
Cheers :) Happy Learning