Monday, February 27, 2017

Intercept ADF Table filters through region controllers

Use case : Intercepting ADF table filters through query listener is a regular approach. In this post i will show you how to do it through region controllers..

Step 1: Drag and drop departments table on to the page with filter mode available.Create binding for the table to a managed bean

<af:table value="#{bindings.DepartmentsEOView1.collectionModel}" var="row"
              rows="#{bindings.DepartmentsEOView1.rangeSize}"
              emptyText="#{bindings.DepartmentsEOView1.viewable ? 'No data to display.' : 'Access Denied.'}"
              fetchSize="#{bindings.DepartmentsEOView1.rangeSize}"
              rowBandingInterval="0"
              filterModel="#{bindings.DepartmentsEOView1Query.queryDescriptor}"
              queryListener="#{bindings.DepartmentsEOView1Query.processQuery}"
              filterVisible="true" varStatus="vs"
              selectedRowKeys="#{bindings.DepartmentsEOView1.collectionModel.selectedRow}"
              selectionListener="#{bindings.DepartmentsEOView1.collectionModel.makeCurrent}"
              rowSelection="single" id="t1" styleClass="AFStretchWidth"
              binding="#{pageFlowScope.view3Bean.richTab}">

Step 2 : Go to page definition file and add a controller class


<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
                ControllerClass="ui.bean.PageFragementController"
                version="11.1.1.64.93" id="view3PageDef" Package="uic">

PageFragementController is a java class that should implement RegionController . 


Step 3 : PageFragementController  implementation

public class PageFragementController implements RegionController {
     
    // This method will be called during page load everytime
    public boolean refreshRegion(RegionContext regionContext) {
       
        int refreshFlag = regionContext.getRefreshFlag();         
        FacesContext fctx = FacesContext.getCurrentInstance();
        Map requestMap = fctx.getExternalContext().getRequestMap();         
        Map pageFlowScopeMap = ADFContext.getCurrent().getPageFlowScope();
        
   // Call the method only during life cycle render model
        if (pageFlowScopeMap != null) {
            if (regionContext.getRefreshFlag() == 2) {

//we have already created a binding for the table to a managed bean which is in pageFlowScope .Access the bean from pageflowscope               


                view3Bean testBan =   (view3Bean)pageFlowScopeMap.get("view3Bean");                

                RichTable rtable = testBan.getRichTab();
                FilterableQueryDescriptor filters = FilterableQueryDescriptor)rtable.getFilterModel();
                Map<String, Object> map = filters.getFilterCriteria();

              if (map != null) {

                String str  = null;
                    for (String key : map.keySet()) {
                        if (map.get(key) != null) {
                            str = (String)map.get(key);
                 }

//Intercept the user filtered column and add the required value. Here user would search for any department ,but i would always want to make it search for Executive only.If the user does empty search then it will work in ordinary way

                                             
               if(str!=null && !str.equals("")){
                            if( key.equals("DepartmentName")){
                                map.put(key, "Executive");
                            }
                        }
                        else{
                            map.put(key, "");
                        }
                    }
                }

//create query Event object with the intercepted filter values. filters is the object which we intercepted through its filter map values.we modified the filters object


 QueryEvent queryEvent =  new QueryEvent(testBan.getRichTab(), filters);


//Invoke the search operation with the below code

  
invokeMethod("#{bindings.DepartmentsEOView1Query.processQuery}",  QueryEvent.class, queryEvent);

            }

        }

        regionContext.getRegionBinding().refresh(refreshFlag);

        return false;
    }


   public static Object invokeMethod(String expr, Class paramType,
                                      Object param) {
        return invokeMethod(expr, new Class[] { paramType },
                            new Object[] { param });
    }

    public static Object invokeMethod(String expr, Class[] paramTypes,

                                      Object[] params) {
        FacesContext fc = FacesContext.getCurrentInstance();
        ELContext elc = fc.getELContext();
        ExpressionFactory ef = fc.getApplication().getExpressionFactory();
        MethodExpression me =
            ef.createMethodExpression(elc, expr, Object.class, paramTypes);
        return me.invoke(elc, params);

    }



Thursday, February 9, 2017

Customizations of Oracle ADF application with MDS.


Firstly there are numerous blogs talk about User Customization in Oracle ADF Applications with MDS feature. I talk nothing new today, but a consolidated information from various docs and blogs collected on how to implement user customization in an Integrated Web logic . The urge to put this post is to give a detailed view of how it works in Integerated web logic server that comes along with JDeveloper. Developers must be having lot of confusion around this topic like Is really ADF security required for Customization , Path to MDS files can be customized , what is customization class .

To begin,customization means when an user using an application built on Oracle ADF and alter the table view columns width,saving af:query saved search all those customizations are saved across session using an inbuilt feature called MDS.

Step 1:

1) Create Employee VO and a View Criteria with some  parameters.
2) Create a page . Drag and drop the criteria from data control section as af:query with the table on to the page. Run the page and you will see some thing like below



Step 2:

Right click view controller project > Project properties > ADF View .apply as below and click ok.


Step 3:

You can configure the location where you would want your customization files should be saved. Default location or you can specify the path

Click Application in file menu > Application Properties > Run > MDS


Step 4 :

Add the below code in adf-config.xml

<adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
    <mds-config xmlns="http://xmlns.oracle.com/mds/config" version="11.1.1.000">
    <persistence-config>
        <metadata-namespaces>
          <namespace path="/persdef" metadata-store-usage="metadata"/>
        </metadata-namespaces>
        <metadata-store-usages>
          <metadata-store-usage id="metadata" deploy-target="true"
                                default-cust-store="true"></metadata-store-usage>
        </metadata-store-usages>
      </persistence-config>
      <cust-config>
        <match path="/"/>
      </cust-config>
    </mds-config>
  </adf-mds-config>


Step 5 :

Run the page ,search the query pane and you will get some results. Click on the save button in the search pane right next to the search,reset buttons. Click OK on the Create Saved Search dialog






Now go to the location C:\JDeveloper\mywork\MDS\ which we configured in the Step:3. you will see a folder persdef and the files inside it. you can see the changes being saved . Next time when you run the page the customization settings will be picked from here..

NOW the setup and task is done. Now these settings are saved in MDS (File Based#when you run the application in Integerated weblogic server with MDS,the default MDS location will be file based. You can configure Database MDS Repository when you run the application in Standalone weblogic server). However the settings are saved without a user i.e these settings are common to all. How about these customization are saved and accessed user based.Lets say Three users accessing the application and wanted to have independent customization. This can also be done.

User based customization can be done in two ways .

1) User can be configured as below. UserCC is a Customization class provided by Oracle ADF. After the settings applied as below in the screen shot in adf-config.xml ,run the page and do the customization and check the folder . This will fail because ,Note : In order to pick the current user for UserCC - ADF security has to be configured for the ADF Application. Means you have to configure ADF Security only when you want the logged in user to be determined automatically. This answers one of our question stated in the start of the post. For more info on adding security to ADF application ADF Security


2) What if i dont have adf-security configured for the application but still want to customize based on user (This is the case when adf authentication is not implemented.). Create a java file as below and configure the same in adf-config.xml under MDS Configuration tab.




you can override getValue method and get the username dynamically from session or properties files  etc ,For now we will hard-code the username

Run the page ,Search and save the query results and check the folder for MDS. you will see the path of the customization settings comes under the username 'Sanvi' as configured in the java class.


In the same way , you can configure customization for adf components  . Go to View tab under adf-config.xml. Click + icon in Tags Section add table,column.Run the page and adjust the width of the table columns .