Please disable your adblock and script blockers to view this page

Search this blog

Friday, 27 December 2013

Overriding default query listener ,field validation of af:query- Oracle ADF


Hello All,
this post talks about a common requirement - can we apply custom validation in af:query fields ? yes , we can do that by overriding default query listener of af:query component

What af:query is ?

see- Oracle Docs-af:query
"The query component provides the user the ability to perform a query based on a saved search or personalize saved searches. The component displays a search panel with various elements, each of which help the user to accomplish various tasks."


Follow steps to apply validation on af:query-
  • Here i am taking example of Departments table of HR Schema
  • First create business components for Departments table


  • then create  bind variables and a view-criteria in departments view object



  • See the view criteria is applied for LocationId, ManagerId and Department Name
  • Now create a page and drop criteria with table on page- it will look like this

  • Next is to select af:query on page and go to property inspector and copy text of default query listener



  • Now create a managed bean and create a custom query listener for af:query

     
  • In this custom query listener , in this example i am checking for negative Location Id and Manager Id, if there is any negative values ,custom method will show a message otherwise default queryListener will be executed
  • We can get af:query's components value using 2 methods
    First One  - Using Bind Variable (getNamedWhereClauseParam)
    Second One - Using QueryDescriptor and ConjunctionCriterion
  • I'm going to explain both methods - see code of custom query listener using first method, two generic methods will be used in this process to invoke expression language and to get BindingContainer of current context

  •     /**Method to invoke EL Expression
         * @param el
         * @param paramTypes
         * @param params
         * @return
         */
        public static Object invokeEL(String el, Class[] paramTypes, Object[] params) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ELContext elContext = facesContext.getELContext();
            ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
            MethodExpression exp = expressionFactory.createMethodExpression(elContext, el, Object.class, paramTypes);
    
            return exp.invoke(elContext, params);
        }
    
        /**Method to get Binding Container of current page
         * @return
         */
        public BindingContainer getBindings() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    

  • See the first method to get af:query components value and validate that

  •     /**Custome Query Listener- Using getNamedWhereClauseParam
         * @param queryEvent
         */
        public void customQueryListener(QueryEvent queryEvent) {
            String deptName = null;
            Integer locId = null;
            Integer mgrId = null;
    
            /**Get Iterator of Table*/
            DCIteratorBinding iter = (DCIteratorBinding)getBindings().get("DepartmentsView1Iterator");
    
            /**Get ViewObject from Iterator*/
            ViewObjectImpl vo = (ViewObjectImpl)iter.getViewObject();
    
            /**Get Bind Variable's Value*/
            if (vo.getNamedWhereClauseParam("LocIdBind") != null) {
                locId = Integer.parseInt(vo.getNamedWhereClauseParam("LocIdBind").toString());
            }
            if (vo.getNamedWhereClauseParam("MgrIdBind") != null) {
                mgrId = Integer.parseInt(vo.getNamedWhereClauseParam("MgrIdBind").toString());
            }
            if (vo.getNamedWhereClauseParam("DeptNmBind") != null) {
                deptName = vo.getNamedWhereClauseParam("DeptNmBind").toString();
            }
    
            /**Check for Negative values*/
            if ((locId != null && locId < 0) || (mgrId != null && mgrId < 0)) {
                FacesMessage msg = new FacesMessage("Id Value can not be negative");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
            } else {
                /**Execute default query listener with help of invokeEL method*/
    
                invokeEL("#{bindings.DepartmentsViewCriteriaQuery.processQuery}", new Class[] { QueryEvent.class },
                         new Object[] { queryEvent });
            }
        }
    

  • And Second Method using QueryDescriptor is-

  •     /**Custom Query Listener-Using QueryDescriptor
         * @param queryEvent
         */
        public void customqueryProcess(QueryEvent queryEvent) {
            String deptName = null;
            Integer locId = null;
            Integer mgrId = null;
    
            /**Reference-Frank Nimphius Example- ADF Code Corner
           * http://www.oracle.com/technetwork/developer-tools/adf/learnmore/85-querycomponent-fieldvalidation-427197.pdf
           * */
            QueryDescriptor qd = queryEvent.getDescriptor();
    
            ConjunctionCriterion conCrit = qd.getConjunctionCriterion();
            //access the list of search fields
            List<Criterion> criterionList = conCrit.getCriterionList();
            //iterate over the attributes to find FromDate and ToDate
            for (Criterion criterion : criterionList) {
                AttributeDescriptor attrDescriptor = ((AttributeCriterion)criterion).getAttribute();
    
                if (attrDescriptor.getName().equalsIgnoreCase("DepartmentName")) {
                    deptName = (String)((AttributeCriterion)criterion).getValues().get(0);
    
                } else {
                    if (attrDescriptor.getName().equalsIgnoreCase("LocationId")) {
                        locId = (Integer)((AttributeCriterion)criterion).getValues().get(0);
    
                    }
                }
                if (attrDescriptor.getName().equalsIgnoreCase("ManagerId")) {
                    mgrId = (Integer)((AttributeCriterion)criterion).getValues().get(0);
    
                }
            }
            if ((locId != null && locId < 0) || (mgrId != null && mgrId < 0)) {
                FacesMessage msg = new FacesMessage("Id Value can not be negative");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
            } else {
                /**Process default query listener*/
                invokeEL("#{bindings.DepartmentsViewCriteriaQuery.processQuery}", new Class[] { QueryEvent.class },
                         new Object[] { queryEvent });
            }
    
        }
    

  • Now Run your application and check it for negative values

Cheers- Download Sample App Happy Learning :-)


Saturday, 21 December 2013

Using Multiple Selection (selectManyListbox & selectManyCheckbox component) in ADF

Hello All ,
This tutorial is based on use of selectManyListbox & selectManyCheckbox component in ADF to enable multiple selection.
Both component are same in functionality only somewhat different in look-feel.



Follow steps to use these component -



  • Create a fusion web application and create business components for Departments table of HR Schema

  • Now create a page and drop Departments Vo from data control on page as multiple selection (checkbox or listbox) 




  • Now binding for this component is created in page-bindings, add a button on page to get total selected values


  • See how to get selected values in managed bean, JUCtrlListBinding is used to get selected values

  • import javax.faces.event.ActionEvent;
    
    import oracle.adf.model.BindingContext;
    
    import oracle.binding.BindingContainer;
    
    import oracle.jbo.uicli.binding.JUCtrlListBinding;   
    
     public BindingContainer getBindings() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
        public void getSelectedValue(ActionEvent actionEvent) {
    
            JUCtrlListBinding listBindings = (JUCtrlListBinding)getBindings().get("DepartmentsView1");
            Object str[] = listBindings.getSelectedValues();
            for (int i = 0; i < str.length; i++) {
                System.out.println(str[i]);
            }
        }
    

  • this method works for both listbox and checkbox, i have added all selected departments in a FacesMessage and displayed on page

 Select All-


And Check-box component look like this-


Complete code written on 'Get Selected Values' button-


    /**Method to get BindingContainer of page
     * @return
     */
    public BindingContainer getBindings() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }

    /**Method to get Selected Values
     * @param actionEvent
     */
    public void getSelectedValue(ActionEvent actionEvent) {

        JUCtrlListBinding listBindings = (JUCtrlListBinding)getBindings().get("DepartmentsView1");
        Object str[] = listBindings.getSelectedValues();
        StringBuilder saveMsg =
            new StringBuilder("<html><body><b><p style='color:red'>Selected Departments are-</p></b>");

        saveMsg.append("<ul>");
        for (int i = 0; i < str.length; i++) {
            System.out.println(str[i]);
            saveMsg.append("<li> <b>" + str[i].toString() + "</b></li>");
        }

        saveMsg.append("</ul><br>");
        saveMsg.append("</body></html>");
        FacesMessage msg = new FacesMessage(saveMsg.toString());
        FacesContext.getCurrentInstance().addMessage(null, msg);

    }

Cheers- Download Sample

Friday, 20 December 2013

Clear Selected Values of shuttle component (Reset shuttle) programmatically-Oracle ADF

Hello All ,
you have heard about shuttle component in ADF,  it works for multiple selection
to use it -refer my previous blog post
Shuttle Component in Oracle ADF (Allow Multiple Selection)

Sometimes we need to reset shuttle (clear selected values) through our code (managed bean)
so in this post I'm going to explain how to do this with simple piece of code
  • I have created a simple jspx page and placed Departments (HR Schema) view-object on this page as an af:selectManyShuttle
  • Created managed bean for a link to clear selected indices of shuttle, see code



  •     public BindingContainer getBindings() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
        /**Method to Clear selected value of shuttle (Reset Shuttle)
         * @param actionEvent
         */
        public void resetShuttleAction(ActionEvent actionEvent) {
            BindingContainer bc = this.getBindings();
            JUCtrlListBinding listBindings = (JUCtrlListBinding)bc.get("DepartmentsView1");
            listBindings.clearSelectedIndices();
    
        }
    

  • Now see how it works- when user click on this link ,it will clear all selected indices of shuttle


Wednesday, 18 December 2013

Changing default text of af:dialog buttons (ok,cancel) in ADF

Hello All,
you all have used pop up component with af:dialog in ADF,
default dialog component look like this inside popup



in ADF there is option to change dialog type , select dialog component and go to property inspector-


But sometimes we need to change default dialog button's text as per our requirement, to do this follow steps mentioned below

  • Drag a popup having dialog as its child component on page
  • select af:dialog in structure window and go to property inspector

  • In property inspector navigate Appearance--->Text 



  • Now set values for Affirmative and cancel text 
     
  • Now run your application and see-
     


  • But it's outcome doesn't get changed as it is static, you can see this in managed bean code, i have created dialog Listener and a cancelListener in managed bean 

  • import javax.faces.application.FacesMessage;
    import javax.faces.context.FacesContext;
    
    import oracle.adf.view.rich.event.DialogEvent;
    import oracle.adf.view.rich.event.PopupCanceledEvent;
    
    
    public class DialogListenerBean {
        public DialogListenerBean() {
        }
    
        public void dialogListener(DialogEvent dialogEvent) {
            FacesMessage msg = new FacesMessage("You have clicked- " + dialogEvent.getOutcome().name());
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    
        public void cancelListener(PopupCanceledEvent popupCanceledEvent) {
            FacesMessage msg = new FacesMessage("You have clicked- cancel");
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }
    

  • When you click on ok and cancel (with changed text), it will return same outcome that was before changing button's text

Cheers- Merry Christmas :-)

Monday, 16 December 2013

Checking Transaction Status of DataControl for Dirty/Modified transaction in ADF


Sometimes we need to check status of data control's transaction, when we have any form or table on page ,initially transaction is not dirty (it means there is no pending changes in binding layer)

If user changes any data set on page that is populated from ADF binding layer, status of transaction is modified as now there is pending changes on page .


When user perform commit or rollback operation then again transaction status changes.

So it is necessary to have basic understanding of Transaction Status and using this we can write some better piece of codes.
Example- suppose we have a save button in our Application that performs commit operation, when user clicks on that button, every time commit gets executed but logically if there is no change in binding layer then commit must not be executed.
So we can check transaction status on this button and if there is any pending changes in ADFm binding layer or transaction is dirty only then commit will be executed

  • I have created a sample application to check this , there is departments and location ViewObjects are on page and a button to check transaction status
  • Code to check transaction status-

  • public BindingContainer getBindings(){
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
    DCBindingContainer dcbind =(DCBindingContainer)getBindings();
    dcbind.getDataControl().isTransactionModified()
    

    OR



    amObject.getDBTransaction().isDirty()
    

  • Initially see page status there is no pending changes so transaction is not dirty


  • Now i have changed DepartmentName attribute , then clicked on Check Transaction button


  • Now when data is committed again status got changed

Friday, 6 December 2013

Show current Date and Time on Page in Oracle ADF (refresh Date/time Programmatically)

Hello All,
in this tutorial i am going to explain that how to show current date and time on your ADF application page
Follow Steps-
  • Create a fusion web application and a page in it (i have used .jspx page)
  • Now drag an output text from component palette and drop it on page

  • Now select the output text and go to its property inspector then select value from Expression Builder as shown in image
  • Now in Expression Builder ,create a Managed Bean of type java.util.Date and assign its value to output text




  •  Now run your page and see current date is there
  • Now to format Date and Time , drag and drop af:convertDateTime  under output text from component palette



  •  Select convertDateTime and go to property inspector and change its pattern and run your page


  •  Now you have done basic configuration for Date/Time, if you want to refresh time (second and minute part) on page periodically then drop a poll component in page and create a poll listener in managed bean
  • Now write this simple code in your managed bean to invoke poll listener

  •     /**Binding of Output text*/
        private RichOutputText dateBind;
    
        public void setDateBind(RichOutputText dateBind) {
            this.dateBind = dateBind;
        }
    
        public RichOutputText getDateBind() {
            return dateBind;
        }
    
    
        /**Poll Listener Method ,handles Poll Event
         * @param pollEvent
         */
        public void refreshTime(PollEvent pollEvent) {
            AdfFacesContext.getCurrentInstance().addPartialTarget(dateBind);
    
        }
    

    And don't forget to set clientComponent property of outputText to true
  • Now Run your application , see in this video clip how your page get refreshed... Cheers ..!

Cheers :) Happy Learning

Tuesday, 26 November 2013

Apply Filter on af:table column programmatically ,Invoke 'FilterableQueryDescriptor' through managed bean

Hello All
This tutorial is about a requirement of filtering af:table column through code,
to achieve this we can invoke FilterableQueryDescriptor (FilterableQueryDescriptor is an abstract subclass of QueryDescriptor. It adds support for filtering of data and is typically used by the table component to filter data from a query )

Suppose i have department table and i have to filter on department column-
  • Create a Fusion Web Application and business components for Departments (HR Schema) table
  • now drag table on page and bind it to bean
  • Now drop a input text and button on page to enter Department Name
  • bind input text to bean and create ActionListener on button to filter Department Table
See XML source of Page-




<?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="filterPage.jspx" id="d1">
            <af:messages id="m1"/>
            <af:form id="f1">
                <af:inputText label="Department Name" id="it5"
                              binding="#{pageFlowScope.FilterProgrammaticBean.deptNmBind}"/>
                <af:commandButton text="Filter" id="cb1"
                                  actionListener="#{pageFlowScope.FilterProgrammaticBean.filterTableAction}"/>
                <af:table value="#{bindings.DepartmentsView1.collectionModel}" var="row"
                          rows="#{bindings.DepartmentsView1.rangeSize}"
                          emptyText="#{bindings.DepartmentsView1.viewable ? 'No data to display.' : 'Access Denied.'}"
                          fetchSize="#{bindings.DepartmentsView1.rangeSize}" rowBandingInterval="1"
                          selectedRowKeys="#{bindings.DepartmentsView1.collectionModel.selectedRow}"
                          selectionListener="#{bindings.DepartmentsView1.collectionModel.makeCurrent}"
                          rowSelection="single" id="t1" styleClass="AFStretchWidth"
                          binding="#{pageFlowScope.FilterProgrammaticBean.deptTabBind}"
                          filterModel="#{bindings.DepartmentsView1Query.queryDescriptor}"
                          queryListener="#{bindings.DepartmentsView1Query.processQuery}" filterVisible="true"
                          varStatus="vs">
                    <af:column sortProperty="#{bindings.DepartmentsView1.hints.DepartmentId.name}" sortable="true"
                               headerText="#{bindings.DepartmentsView1.hints.DepartmentId.label}" id="c1"
                               filterable="true">
                        <af:inputText value="#{row.bindings.DepartmentId.inputValue}"
                                      label="#{bindings.DepartmentsView1.hints.DepartmentId.label}"
                                      required="#{bindings.DepartmentsView1.hints.DepartmentId.mandatory}"
                                      columns="#{bindings.DepartmentsView1.hints.DepartmentId.displayWidth}"
                                      maximumLength="#{bindings.DepartmentsView1.hints.DepartmentId.precision}"
                                      shortDesc="#{bindings.DepartmentsView1.hints.DepartmentId.tooltip}" id="it1"
                                      readOnly="true">
                            <f:validator binding="#{row.bindings.DepartmentId.validator}"/>
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsView1.hints.DepartmentId.format}"/>
                        </af:inputText>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsView1.hints.DepartmentName.name}" sortable="true"
                               headerText="#{bindings.DepartmentsView1.hints.DepartmentName.label}" id="c2"
                               filterable="true">
                        <af:inputText value="#{row.bindings.DepartmentName.inputValue}"
                                      label="#{bindings.DepartmentsView1.hints.DepartmentName.label}"
                                      required="#{bindings.DepartmentsView1.hints.DepartmentName.mandatory}"
                                      columns="#{bindings.DepartmentsView1.hints.DepartmentName.displayWidth}"
                                      maximumLength="#{bindings.DepartmentsView1.hints.DepartmentName.precision}"
                                      shortDesc="#{bindings.DepartmentsView1.hints.DepartmentName.tooltip}" id="it2"
                                      readOnly="true">
                            <f:validator binding="#{row.bindings.DepartmentName.validator}"/>
                        </af:inputText>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsView1.hints.ManagerId.name}" sortable="true"
                               headerText="#{bindings.DepartmentsView1.hints.ManagerId.label}" id="c3"
                               filterable="true">
                        <af:inputText value="#{row.bindings.ManagerId.inputValue}"
                                      label="#{bindings.DepartmentsView1.hints.ManagerId.label}"
                                      required="#{bindings.DepartmentsView1.hints.ManagerId.mandatory}"
                                      columns="#{bindings.DepartmentsView1.hints.ManagerId.displayWidth}"
                                      maximumLength="#{bindings.DepartmentsView1.hints.ManagerId.precision}"
                                      shortDesc="#{bindings.DepartmentsView1.hints.ManagerId.tooltip}" id="it3"
                                      readOnly="true">
                            <f:validator binding="#{row.bindings.ManagerId.validator}"/>
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsView1.hints.ManagerId.format}"/>
                        </af:inputText>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsView1.hints.LocationId.name}" sortable="true"
                               headerText="#{bindings.DepartmentsView1.hints.LocationId.label}" id="c4"
                               filterable="true">
                        <af:inputText value="#{row.bindings.LocationId.inputValue}"
                                      label="#{bindings.DepartmentsView1.hints.LocationId.label}"
                                      required="#{bindings.DepartmentsView1.hints.LocationId.mandatory}"
                                      columns="#{bindings.DepartmentsView1.hints.LocationId.displayWidth}"
                                      maximumLength="#{bindings.DepartmentsView1.hints.LocationId.precision}"
                                      shortDesc="#{bindings.DepartmentsView1.hints.LocationId.tooltip}" id="it4"
                                      readOnly="true">
                            <f:validator binding="#{row.bindings.LocationId.validator}"/>
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsView1.hints.LocationId.format}"/>
                        </af:inputText>
                    </af:column>
                </af:table>
            </af:form>
        </af:document>
    </f:view>
</jsp:root>

Managed Bean Code-


package filter.view;

import java.util.Map;

import javax.faces.event.ActionEvent;

import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.component.rich.input.RichInputText;
import oracle.adf.view.rich.context.AdfFacesContext;
import oracle.adf.view.rich.event.QueryEvent;
import oracle.adf.view.rich.model.FilterableQueryDescriptor;


public class FilterProgrammaticBean {
    private RichInputText deptNmBind;
    private RichTable deptTabBind;

    public FilterProgrammaticBean() {
    }

    public void setDeptNmBind(RichInputText deptNmBind) {
        this.deptNmBind = deptNmBind;
    }

    public RichInputText getDeptNmBind() {
        return deptNmBind;
    }

    public void setDeptTabBind(RichTable deptTabBind) {
        this.deptTabBind = deptTabBind;
    }

    public RichTable getDeptTabBind() {
        return deptTabBind;
    }

    /**Method to invoke FilterableQueryDescriptor and Filter Department table
     * @param actionEvent
     */
    public void filterTableAction(ActionEvent actionEvent) {
        RichTable tbl = this.getDeptTabBind();
        FilterableQueryDescriptor filterQD = (FilterableQueryDescriptor)tbl.getFilterModel();
        Map filterCriteria = filterQD.getFilterCriteria();
        filterCriteria.put("DepartmentName", deptNmBind.getValue());
        getDeptTabBind().queueEvent(new QueryEvent(getDeptTabBind(), filterQD));
        AdfFacesContext.getCurrentInstance().addPartialTarget(this.getDeptTabBind());
    }
}

Run your Application-





Cheers- Download Sample App