Saturday, 11 February 2017

Dynamic Menus in ADF

Hi everyone this tutorial is about, how we can create menus dynamically in ADF

For this post i am using jdeveloper 11.1.2.3.0

1 ) First you need to create a table in database and insert data




2) Create two Query Base VO in ADF Application
after that create view link between Main_menu VO and Sub_menu VO
For creating view link select MId from Main_menu and select ParentId from Sub_menu






3 ) Then create a Home.jsf page and then drag and drop Menu bar on it from components then af:iterator drop on Menu bar , then  drop Menu on  the iterator then again drop af:iterator on Menu and then MenuItem on the second af:iterator , the structure of the jsf page shows in the next pic , try to create the same jsf page like the following structure




4 ) Now go to the Bindings of jsf page
click on green + icon of Bindings part ..
From the InsertItem window select tree and hit ok


After clicking the ok a new window will appear name as "Create Tree Binding"
click on Add button


Then from the "Add Data Source " window select Main_menu1 and click ok

Then click on the green + icon and click on AddRule



Then Select MId and MName as Display as Display Attributes

Again Click on green + icon and then click on AddRule and select select sub_menu, and select all the attributes as Display Attributes



After adding tree item your jsf page Bindings will be looks like this


Now go to Structure window select first af:iterator and set its value
to set the iterator value
clikc on Expression Builder of Value attribute , then open Bindings , then open Main_menu1 and select collectionModel


then set the value 'M' of var attribute  (properties of first iterator)



Then select the af:menu from Structure window and set Text property with the following value

#{M.MName}



until now if you Run your Home.jsf page , the Main Menu will print on screen

To set the value of second iterator , first we need to get the accessor name of Sub_menu
to get the accessor name open the view link 'Main_sub_VL' that we have created between Main_menu and Sub_menu , click on Relationship tab , click on Edit accessor and copy the name of the accessor


and write the following expression in the value property of second af:iterator
also write 'S' for var property



Select the af:commandMenuItem from the Structure window and write the following expression int 'Text' property  #{S.MName}


Now Run your Home.jsf page and see the Results , it will be


Second Part

Now to get the path of jsff or jsf pages by clicking on Menu item

Select the af:commandMenuItem from structure window and  drop a attribute from component palette on it.

write the name of attribute 'P'
and write the following expression in value  #{S.MPath}


Then select af:commandMenuItem from structure window and create a ActionListener binding with a request scope been (in this example the been name is MenuBeen)


Edit your data base table and save the path in M_Path attribute , for this example i just saving a string



Open your MenuBeen and write the following code


Run your Home.jsf page click on SALE RTN menu and see the result on console




Thanks

Friday, 10 February 2017

Login With Database Users Dynamically in ADF OR How to Support Dynamic JDBC CREDENTIALS IN ADF

Hi everyone this post is about how you can perform login by using DB level user name and password..
(DB level users also known as  DB level Schema  like HR Schema or SCOTT Schema)

To read more detail click Here
For this example i am using jdeveloper 11.1.2.3.0

Lets start

1) Create a simple Application , connect to Database ( i have contacted with hr schema) create  DepartmentsView VO and  create two jsf pages   ( i ) Login.jsf  ( ii ) Home.jsf

2) On Login.jsf page drag and drop two input text fields and one button to perform login and drope DepartmentsView VO on Home page





3) Now create a request scope been name as Login , create a login() method and bind it to button of login page, to verify user name and password and  to set user name and password in Global variables (Later we use these Global variables for login in  doFilter() method of ADFBindingFilter  Servlet )

Note :- this Login been will only used to verify the user name and password , to set user name and password in Global variables and  to perform logout

Here is the code to of Login been 

package view;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;

public class Login {
    private String uname;
    private String upw;

        //varify user name and password , set session scope values 
    public Login() {
    }

    public String login() {
        
        if(null != this.uname && null!=this.upw){
                
                Connection conn;
                
                    //set user name and password in session scope variables 
                    FacesContext ctx = FacesContext.getCurrentInstance();
                    HttpSession session = (HttpSession) ctx.getExternalContext().getSession(true);
                    session.setAttribute("uName", this.uname.toUpperCase());
                    session.setAttribute("uPassword", this.upw.toUpperCase());
                   
                   //to varify user name and password 
                try {
                conn = this.getConnection();
                   
        
                    String page="http://127.0.0.1:7101/dye_planing-ViewController-context-root/faces/home.jsf";
                  this.launchNewPage(page);
                    
                   //to refresh the page
                   
                   FacesContext fc = FacesContext.getCurrentInstance();
                         String refreshpage = fc.getViewRoot().getViewId();
                   ViewHandler ViewH =
                   fc.getApplication().getViewHandler();
                         UIViewRoot UIV = ViewH.createView(fc,refreshpage);
                         UIV.setViewId(refreshpage);
                         fc.setViewRoot(UIV);

                
                }
                catch (SQLException e) {
               FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Wrong ID or Password..!"));
                }
                    
                    
            }else
        {
                     FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Please Enter User Name and Password..!"));
                 }
        return null;
        
      
    }
    
    
    
    //to varify the user name and password 
    public  Connection getConnection() throws SQLException {
        String username = this.uname.toUpperCase();
        String password = this.upw.toUpperCase();
        String thinConn = "jdbc:oracle:thin:@ your system or server ip : your port address :mis";
        DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
        Connection conn = DriverManager.getConnection(thinConn, username, password);
        conn.setAutoCommit(false);
        return conn;
    }
    
    
    
    //to perform logout
    public String onLogout(){  
         FacesContext fctx = FacesContext.getCurrentInstance();  
         ExternalContext ectx = fctx.getExternalContext();  
         //String url = ectx.getRequestContextPath() + "/adfAuthentication?logout=true&end_url=/faces/Login.jspx";  
         String page="http://127.0.0.1:7101/dye_planing-ViewController-context-root/faces/ULogin.jsf";
         this.launchNewPage(page);
           
         HttpSession session = (HttpSession)ectx.getSession(false);  
         session.invalidate();  
           
         return null;  
       }  
    
   

//method to luch new pages 
    public void launchNewPage(String p) {
        String newPage = p;
        FacesContext ctx = FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks = Service.getService(ctx.getRenderKit(), ExtendedRenderKitService.class);
        String url = "window.open('" + newPage + "','_self');";
        erks.addScript(FacesContext.getCurrentInstance(), url);
    }
    
    //method to get gat values from expression
    public static Object getEL(String el) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ExpressionFactory expressionFactory =
        facesContext.getApplication().getExpressionFactory();
        ValueExpression exp =
        expressionFactory.createValueExpression(elContext, el,
        Object.class);
         
        return exp.getValue(elContext);
        }
         //method to set values for expersion 
        public static void setEL(String el, Object val) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ExpressionFactory expressionFactory =
        facesContext.getApplication().getExpressionFactory();
        ValueExpression exp =
        expressionFactory.createValueExpression(elContext, el,
        Object.class);
         
        exp.setValue(elContext, val);
        }


    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUname() {
        return uname;
    }

    public void setUpw(String upw) {
        this.upw = upw;
    }

    public String getUpw() {
        return upw;
    }
}


4) To support Dynamic JDBC Credentials in adf we need to override the doFilter() method of oracle.adf.model.servlet.ADFBindingFilter  Servlet

this ADF Binding Filter is a servlet filter  that is used to sets up the binding context for the ADF application

this filter is fired and request for application module instance before any page is displayed to the end user. But we need to provide user name and password at run time so we need to display a login page to the end user where they can enter user name and password
so we need to override the doFilter() method to perform run time login

to override this method we also need to add "BC4j Client" library in ViewController
to add this edit the ViewController project's properties and add this library..

to override the method  create a java class in ViewController project  name as DynamicJDBCFilter and and exteds ADFBindingFilter


Here is the complete code

package view;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import oracle.adf.model.servlet.ADFBindingFilter;
import oracle.jbo.JboException;
import oracle.jbo.client.Configuration;

public class DynamicJDBCFilter extends ADFBindingFilter{
 
    public DynamicJDBCFilter()
      {
      }

      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
      {
        HttpSession session = ((HttpServletRequest) request).getSession(false);
        if (session != null && session.getAttribute("loggedin") == null)
        {
        System.out.println("i am in doFilter method.........");

          String usrName = (String) session.getAttribute("uName");
          String pswd = (String) session.getAttribute("uPassword");
     
     
        System.out.println("the uname is        "+usrName);
        System.out.println("the pw is             "+pswd);

          if (usrName != null && session.getAttribute("loggedin") == null)
          {
            try
            {
              if (usrName == null || usrName.length() == 0 ||  pswd == null || pswd.length() == 0)
              {
                throw new JboException("Blank User name or Password");
              }

              session.setAttribute(Configuration.DB_USERNAME_PROPERTY, usrName);
              session.setAttribute(Configuration.DB_PASSWORD_PROPERTY, pswd);
              super.doFilter(request, response, chain);
              session.setAttribute("loggedin", "loggedin");
            }
            catch (oracle.jbo.JboException e)
            {
              try
              {
                session.setAttribute("loggedin", null);
                session.invalidate();
              }
              catch (Exception e2)
              {
              }
              request.getRequestDispatcher("/faces/login.jspx").forward(request, response);
            }
          }
          else
          {
            super.doFilter(request, response, chain);
          }
        }
        else
        {
          super.doFilter(request, response, chain);
        }
      }
}

5) Modify web.xml file

we need to update filters and filter Mapings , to update Filter open web.xml file , click on Filter tab
and update or add adfBindings  and filter Mappings  like the following ...




i have added this statement System.out.println("i am in doFilter method.........");
in DynamicJDBCFilter  class..
now Right click on Login.jsf page and click on Run , the above statement should print on console



until now your application can connect to database ... but for ADF Business Components we need to do the following steps

6 ) ADF Business Components need to connect to the current user at run time , So for this ADF Business components uses oracle.jbo.common.ampool.EnvInfoProvider interface . This interface will invoked by ADF Business Components at run time when it is necessary to connect AM instance to DB.

to implement this interface create a new java class and implement oracle.jbo.common.ampool.EnvInfoProvider ....

The operations declared by the EnvInfoProvider interface are all invoked at different points in the AM creation / connection life cycle by the ADF Bussiness Components at run time.

But we implement getInfo method , because it is used to connect ADF Business Components at run time

Here is the complete code

package view;
import java.util.Hashtable;
import oracle.jbo.common.ampool.EnvInfoProvider;
import oracle.jbo.client.Configuration;

public class DynamicEnvInfoProvider implements EnvInfoProvider  {
 
    private final String un;
      private final String upw;

      public DynamicEnvInfoProvider(String uname, String upassword)              
      {
         un = uname;
         upw = upassword;
      }

      public Object getInfo(String info, Object connEnvironment)
      {
        if(un != null)                                                              
        {
          ((Hashtable)connEnvironment).put(Configuration.DB_USERNAME_PROPERTY, un);
        }
        if(upw != null)                                                            
        {
          ((Hashtable)connEnvironment).put(Configuration.DB_PASSWORD_PROPERTY, upw);
        }
        return null;                                                                          
      }

      public void modifyInitialContext(Object p0)
      {
      }

      public int getNumOfRetries()
      {
        return 0;
      }
}

7 ) Reference this DynamicEnvInfoProvider

To uniquely identify every session in application pool , the Application Pool use oracle.jbo.common.ampool.SessionCookie  class . So , every HTTP request that requires AM instance from Application pool will create a Session Cookie and remains live until the session ended. At run time this Session Cookie instance will reuse every time when ever the session requires an AM instance from application pool.

to connect the ADF Business Components with session ,an  object of  EnvInfoProvider   save in Session Cookie

ADF Business Components API provides the SessionCookie.setEnvInfoProvider (EnvInfoProvider) method to store a reference of EnvInfoProiver instance in SessionCookie. The Application Pool also check the existence of EnvInfoProvider instance when AM instance need to connect .

Create SessionCooike Implementation

create a java class in ViewController and extends it with HttpSessionCookieImpl

Here is the complete code

package view;
import oracle.jbo.common.ampool.ApplicationPool;
import oracle.jbo.http.HttpSessionCookieImpl;
import oracle.jbo.common.ampool.EnvInfoProvider;

public class DynamicSessionCookieImpl extends HttpSessionCookieImpl {
 
    public DynamicSessionCookieImpl(java.lang.String applicationId,
        java.lang.String sessionId, ApplicationPool pool)
      {
        super(applicationId, sessionId, pool);
      }

      public DynamicSessionCookieImpl(java.lang.String applicationId,
        java.lang.String sessionId, ApplicationPool pool, java.security.Principal userPrincipal,
        javax.servlet.http.HttpServletRequest request)
      {
        super(applicationId, sessionId, pool, userPrincipal, request);
      }

      public DynamicSessionCookieImpl(java.lang.String applicationId,
        java.lang.String sessionId, ApplicationPool pool, java.security.Principal userPrincipal,
        javax.servlet.http.HttpSession session)
      {
        super(applicationId, sessionId, pool, userPrincipal, session);
      }

      public void setEnvInfoProvider(EnvInfoProvider envInfoProvider)
      {
        if (envInfoProvider != null)
        {
          super.setEnvInfoProvider(envInfoProvider);
        }
      }
}

8 ) Create a Session Cookie Factory

This Session Cookie Factory will use to initialize the new SessionCookies along with EnvInfoProvider instance

create a new java class in ViewController Project and extends it with HttpSessionCookieFactory

Complete code here

package view;
import oracle.jbo.common.ampool.SessionCookie;
import oracle.jbo.common.ampool.ApplicationPool;
import oracle.jbo.common.ampool.EnvInfoProvider;
import java.util.Properties;
import java.util.Hashtable;
import oracle.jbo.http.HttpSessionCookieFactory;
import oracle.jbo.client.Configuration;
import javax.servlet.http.HttpSession;

public class SessionCookieFactory extends HttpSessionCookieFactory {
 
    public SessionCookie createSessionCookie(String name, String value, ApplicationPool pool, Properties properties)
     {
       SessionCookie cookie = super.createSessionCookie(name, value, pool, properties);

       if (properties != null)
       {
         HttpSession session = (HttpSession) properties.get(HTTP_SESSION);
         if (session != null)
         {
           Hashtable env = pool.getEnvironment();
           env.remove(Configuration.DB_USERNAME_PROPERTY);
           env.remove(Configuration.DB_PASSWORD_PROPERTY);
           pool.setUserName(null);
           pool.setPassword(null);
           EnvInfoProvider provider = new DynamicEnvInfoProvider(
               (String) session.getAttribute(Configuration.DB_USERNAME_PROPERTY),
               (String) session.getAttribute(Configuration.DB_PASSWORD_PROPERTY));
           cookie.setEnvInfoProvider(provider);
         }
       }
       return cookie;
     }

     public Class getSessionCookieClass()
     {
       try
       {
         return Class.forName("view.DynamicSessionCookieImpl");// path to DynamicJDBCHttpSessionCookieImpl class
       }
       catch (ClassNotFoundException cnfe)
       {
         cnfe.printStackTrace();
         return null;
       }
     }
}

9 ) AppModule Setting

Finally after creating your own SessionCookieFactory  , to force the Application pool to use this factory instead of default , we need to update the jbo.ampool.SessionCookieFactory property

So open the AM Configurations update the following setting for both

AppModuleShared and
AppModuleLocal



Set connection type to JDBC URL



update jbo.ampool.SessionCookieFactory property




now run your Application , i am connecting with HR Schema , it Will show the data of Department table




Then i create another user as gul and login by using this user name and password




and the out put will be


Thanks







Wednesday, 27 July 2016

Programmatically execute view criteria in ADF (With two different Approaches ) part 2


Hi everyone this is the second part of  "Programmatically execute view criteria in ADF (With two different Approaches ) "

In first part i have explained in detail how you people can execute the view Criteria in AppModuleImpl class and ViewObjectImpl class
if you don't have seen yet please visit the following link

http://adfindepth.blogspot.com/2016/07/programmatically-execute-view-criteria.html

In this post i simply show the code and which method we should adopted

1) Execute View Criteria in AppModuleImpl class 



2) Execute View Criteria in ViewObjectImpl class 





The best place to execute the View Criteria 

In my point of view The view object Impl class is the best place to execute the view criteria
because in this way we can manage our application in a better way
Secondly we need less code in View object Impl class to execute View criteria



Please Feel Free To Ask if you Face any Difficulty 
Like and share to help others
Thanks
Date 27-06-2016

Tuesday, 26 July 2016

Programmatically execute view criteria in ADF (With two different Approaches ) part 1

Hi everyone in this post we will see two different approaches to call the view criteria Programmatically

1) In First Method we can execute View criteria in AppModuleImpl Class
2) In Second Method we can also do the same thing in View object Impl class with less code

1) Execute Through AppModuleImpl class

Suppose you create a view criteria , 'select employees where departmetnId =:bind_parameter' on EmployeesView

To create view criteria just click on query tab of EmployeesView
1) Then click on green + icon of view criteria
2) Then click on group and select Add items
3) Then Select "DepartmentId" from Attributes
4) Then create a bind parameter by click on green + icon



Now to generate AppModuleImpl class gust select java tab of AppModule
then click on pencil icon
and select the check box just like in the following pic




Now at the end of AppModuleImpl class write the following method



Now call this method in been and pass the parameter in been
If you don't know how to call AppModuleImpl class method in been then plz visit the following link

http://adfindepth.blogspot.com/2016/06/how-to-call-appmoduleimpl-class-method_26.html


2) Execute Through View Object Impl class

For this we need  to create view object impl class , for this example we are using EmployeeView
So to create java classes of  EmployeeView , click on java tab of
Then click on pencil icon
and select the check box like in picture



Now at the end of EmployeesViewImpl class write the following code



Now add this method in Client Interface of EmployeeView



Now access this method in been and execute it

Continue ...............
Link of part 2  (Describe the difference)

http://adfindepth.blogspot.com/2016/07/programmatically-execute-view-criteria_27.html






 Please Feel Free To Ask if you Face any Difficulty 
Like and share to help others
Thanks

Date 27-07-2016

Get Multiple Selected Rows In ADF

Hi everyone In this Post i will describe how to get multiple selected rows in  View Object Impl Class

you can implement this logic to multiple deletion or to update multiple rows

For this example i am using jdeveloper 11.1.2.3.0

First of all add a Transient attribute in view object with Data type Boolean and make it Update able Always


Then click on Ui Hints Tab and select Check Box from Control Type



Now create a JSF page drop a panel collection from component palette
then drop  VO on JSF page as Read only table
move the Selection Attribute at the top
and make sure the selection of Multi Rows



when your drop the VO on JSF page the Selection Attribute not appears as a check Box
so right click on inside of selection attribute and select Delete



Now from Data Control select the Selection attribute and drop it as a check box
like this


Now go to java  of view object and create java classes of view object
to create classes click on pencil i con then checked the check boxes in the following way



Now open the view object "EmployeesViewImpl" class



and the at the end of this class write the following method


To add this method to the client Interface of the view object
click on java Tab of  view object
click on pencil icon
then select and move method





Now to access this method in been follow the following steps
1) First add this method in client side bindings , for this
click on bindings of JSF page
Then from bindings click on green + icon
Then from Insert Item window select method action and click  OK








After clicking OK "create Action binding" windows appear in front  of you
Expend the "AppModuleDataControl"
Then select "EmployeesView1" and you will see the "getSelectedRow()"  method
Now just click OK
and then click on Design Tab



Now on JSF page
drag and drop a button from component palette
then create a been with request scope and create a method in been name as "button method"
then bind the button with been method ("buttonMethod")
Now in "buttonMethod " call the "getSelectedRow" Method in the following way

firstly copy the id of the method from bindings



Then write the following code in been method


Now just Run you Application select some rows hit the "getRows" button and see the result in log file




Please Feel Free To Ask if you Face any Difficulty 
Like and share to help others
Thanks
Date 26-07-2016

Sunday, 26 June 2016

How To Call AppModuleImpl Class Method In Been Through Binding (Second Method)

Hi Every one in this post we will see how to call custom method from AppModuleImpl class pragmatically

In my previous post i have call AppModuleImpl class method in an other way , if you don't have seen yet please visit the following link

http://adfindepth.blogspot.com/2016/06/how-to-call-appmoduleimpl-class-method.html

For this post
Firstly i create a SQL Query base view object  name as EmpVo that takes two parameter

select * from employees e where e.department_id=:bind_deptID and e.first_name like :bind_fName||'%'

we pass the value dept_id and :fName in been and will execute query in AppModuleImpl class

Now create a jsf page drag and drop  EmpVo on page from Data Control  and also drop a button on page
Then create a been with request scope and a button method
 your page will be look like this



Now go to AppModuleImpl class create following method to bind the variable values with query
This method takes two parameter dept_id and fName , attach these values with query and then execute the Query



 Add this method to client Interface of AppModule ,
click on right side pen icon (Edit application module client Interface)
Select exeEmpQ Method from Available side and move to selected side , then click Ok







Now add this method in bindings
Open your JSF page and click on Bindings


Click on + icon of Bindings
Select methodAction from Insert Item and click OK



Now in Create Action Window
Select AppModuleDataControl
In Operation you will see exeEmpQ Method , just click OK



Now From Bindings select exeEmpQ method
Copy the Id of this method
After copy click on Design


Now in been write the following code





Now Run your JSF page and click on button Execute Query






Please Feel Free To Ask if you Face any Difficulty 
Like and share to help others
Thanks
Date 27-06-2016


Query to get Business unit (ORGANIZATION_ID) Detail in oracle Fusion

  SELECT HAO.ORGANIZATION_ID AS BUSINESS_UNIT_ID,         HAOT.NAME,         HAO.BUSINESS_GROUP_ID,         HAO.EFFECTIVE_START_DATE,       ...