Monday, January 28, 2019

ADF Table Filter Case Insensitive and Search by Contains Instead of Start With

ADF Table Filter Case Insensitive and Search by Contains Instead of Start With

In ADF table if you enable column filter this filter by default will search by "start with" and it will be case sensitive . For example in table employees if you have employee name = Hermann and you try to search by "man", the search will return no result


but if you search by "Herm" it will return result


If you try to search by "herm" it will return no result.



This is because the filter by default is case sensitive and will search by start with.

In many cases we need the all tables filters be case insensitive and search by contains not start with. You can search by case insensitive by setting filterFeatures="caseInsensitive" for  each af:column but you need to do this in all af:column in your application and it will not be a proper solution.

You can search with contains by typing your string between '%', but we need something to be more easy than typing %.

To make the the ADF table filter be case insensitive and search by contains follow these steps:

1- In model project create new class "CustomViewImpl" this class should extend oracle.jbo.server.ViewObjectImpl


2- In this class override getCriteriaItemClause(ViewCriteriaItem viewCriteriaItem) and write this code:

public String getCriteriaItemClause(ViewCriteriaItem viewCriteriaItem)
{
if (viewCriteriaItem.getAttributeDef().getJavaType().getName().equals("java.lang.String"))
{
viewCriteriaItem.setValue("%" + viewCriteriaItem.getValue() + "%");
}
viewCriteriaItem.setUpperColumns(true);
return super.getCriteriaItemClause(viewCriteriaItem);
}
view rawCustomViewImpl.java hosted with ❤ by GitHub




3- Go to Model --> Project Properties --> ADF Business Components --> Base Classes --> View Object --> change Object to point to your CustomViewImpl class


4- Open ViewObject --> Java --> Java Classes --> Generate View Object Class



5- If you open the generated ViewImpl class you will find it extend the CustomViewImpl class


6- Run the application and test.

custom generic class in model level

import oracle.jbo.ViewCriteriaItem;
import oracle.jbo.server.ViewObjectImpl;

public class CustomViewImpl extends ViewObjectImpl {
    /**
     * Added   for filtering data in Grid using filters.
     * */
    @Override
    public String getCriteriaItemClause(ViewCriteriaItem viewCriteriaItem) {
        if (!viewCriteriaItem.getValue().toString().startsWith(":")) {
            if (viewCriteriaItem.getValue() != null &&
                viewCriteriaItem.getAttributeDef().getJavaType().getName().equals("java.lang.String")) {
                viewCriteriaItem.setValue("%" + viewCriteriaItem.getValue()+ "%");
            }
        }
        viewCriteriaItem.setUpperColumns(true);
        return super.getCriteriaItemClause(viewCriteriaItem);
    }
}


--  --- this method need to write at voimpl class

    public String getCriteriaItemClause(ViewCriteriaItem viewCriteriaItem) {
        System.out.println("--- one");
        String vl=(String)viewCriteriaItem.getValue();
        System.out.println("--- get value :  "+  viewCriteriaItem.getValue()+"  val : "+vl);
        if(viewCriteriaItem.getValue()!=null && !viewCriteriaItem.getValue().toString().startsWith(":")){
            System.out.println("-- start with :");
            if(viewCriteriaItem.getValue()!=null && viewCriteriaItem.getAttributeDef().getJavaType().getName().equals("java.lang.String")){
                viewCriteriaItem.setValue("%" + viewCriteriaItem.getValue());
            }
        }
        viewCriteriaItem.setUpperColumns(true);
        return super.getCriteriaItemClause(viewCriteriaItem);
    }




--- this is another way


ADF: case insensitive filtering in af:table

 
We have default sorting and filtering options in adf table. But table filters are case sensitive by default. If we need to make the filters as case insensitive, we have simple option with properties. We no need to write any custom code to achieve this.
In properties we have filterFeatures attribute. For that we need to declare “caseInsensitive” like below :

Thats all. We got the case insensitive for adf table filters .

Monday, January 21, 2019

totals calculating with rounding 2

new BigDecimal(FaTransDtl.sum('TransAmt') == null ? 0 : FaTransDtl.sum('TransAmt') ).setScale(2,BigDecimal.ROUND_HALF_EVEN)


If u want sum on same VO

object.getRowSet().sum('ExpnsAmt != null ? ExpnsAmt : 0 ')

https://adfindepth.blogspot.com/2019/01/groovy-examples-in-adf-column-sum-using.html

new BigDecimal(object.getRowSet().sum('DrcrTag=="D"?(TransAmt != null ? TransAmt : 0 ):0')).setScale(2, BigDecimal.ROUND_HALF_EVEN)

Thursday, January 3, 2019

createInstanceFromResultSet at VoImpl class

    public ViewRowImpl createInstanceFromResultSet(QueryCollection queryCollection, ResultSet resultSet) {
        ViewRowImpl viewRowImpl = super.createInstanceFromResultSet(queryCollection, resultSet);
        Map pageFlowScope = ADFContext.getCurrent().getPageFlowScope();
        String compCode = (String)pageFlowScope.get("loginCompCode");
        String stkunit = (String)viewRowImpl.getAttribute("StkUnit");
        String sloc="ALL";
        String prodcode = (String)viewRowImpl.getAttribute("ProdCode");
        String atr1Code = (String)viewRowImpl.getAttribute("Atr1Code");
        String atr2Code = (String)viewRowImpl.getAttribute("Atr2Code");
        String tAtr1Code = atr1Code ==null?"ALL":atr1Code;
        String tAtr2Code = atr2Code ==null?"ALL":atr2Code;
        String obtype ="C";
        System.out.println("**compCode** "+compCode+" "+stkunit+" "+sloc+" "+prodcode+" "+tAtr1Code+" "+tAtr2Code+" "+obtype);
        BigDecimal avbQty = getStockOfProd(compCode,stkunit,sloc,prodcode,tAtr1Code,tAtr2Code,obtype);
        System.out.println("at voimpl avbQty: "+avbQty);
        viewRowImpl.setAttribute("TAvbQty", avbQty);
       
        return viewRowImpl;
    }

Wednesday, January 2, 2019

ADF Good (Best) Practice: Register bean in backingbeans cope

This blog is to highlight why we should register our beans in backing bean scope.

ADF supports following scopes: backingbean, request, view, pageFlow, session and application.

As a good practice we should register our beans in backingbean scope.

1. Why we should not use view, pageFlow, session, application: System needs to serialize any information in these scopes during fail over and also when user times out. Generally we bind UI components with a bean and these components are not serializable so if bean is registered in above scopes it will not get serialized and serialization will fail.


2. Why we should not use requestScope: Serialization is not a problem if bean is registered in request scope because system does not serialize any object that is present in request scope. That make sense also because anything that is in request scope should be lost in next request so what is the point to serialize that information. BUT still we should not register our beans in request scope. That is because if we use a task-flow on a page twice and task-flow has a request-scope bean, both instances of task-flow will start sharing same instance of bean. It can create a lot of confusion.


3. Why should we use backing-bean Scope: Backing bean scope is almost same a request scope in terms of life cyle so system need not to serialize any such bean. Also we get advantage that system create two instances of bean if we use task-flow twice on a page.


4. Is it good enough: Now question is "Can we meet all requirements by storing beans in backing-bean scope?". I would say most of the time YES, you can. Mostly we need to put certain INFORMATION on higher scopes (like pageFlow, session, application) and to store that we don't need to put bean in that scope. We can directly put INFORMATION (or value) in scope. For example we have a 4 page task-flow, which has employee search on first page and user can select an employee on first page. After selecting employee user can navigate to page 2, 3, 4. On page 4 we need to know selected employee record.
To achieve this one developer do following
   a. Bind employee table of first page on a page-flow bean
   b. Bind table with the bean.
   c. On page 4, get page-flow bean and then get table and then try to get selected employee row.

Other developer can follow this approach
   a. Bind employee table of first page on backingbean-scoped bean
   b. Bind table with that bean
   c. While navigating to page-2 get selected row from employee table and store its (employee-id or any other needed information) in page-flow scope. If you need complete employee information you can create employee-pojo (object) and set its attribute and then store employee object in page-flow
   d. Access employee information from page-flow scope. 

[IF you are using bindings and on selection you have selection listener which makes employee row current, you can directly create binding of same vo on page-4. That could be even better]

We see mostly we need to information on different pages, so its better to store those information on needed scope rather than bean.


5. If you really want to store bean in higher scopes: If you really need bean in higher scopes atleast use ComponentReference.

http://myfaces.apache.org/trinidad/trinidad-api/apidocs/org/apache/myfaces/trinidad/util/ComponentReference.html