Monday, April 28, 2014

How to display Page expire popup to the user in an ADF application


This blog explains about how to configure web.xml in order to display warning message to user just before session expires, so that user can make the session alive by clicking on 'Ok' button.

Configure below element in web.xml, this will show 'Session Expire' warning popup
If you don't want to display any session expire popup message, then set the value to '-1'
<context-param>
    <param-name>oracle.adf.view.rich.sessionHandling.WARNING_BEFORE_TIMEOUT</param-name>
    <param-value>10</param-value>
  </context-param>

How to redirect to custom page whenever session time out in ADF application ?


This blog explains about how to redirect to any custom page whenever session time out in an  ADF application.

This blog demonstrates about redirecting to www.google.com automatically whenever session time out occurs.

You need to understand about Implementing Page Phase Listener prior to implementing this.

Step1 : Create Page Phase Listener as shown below, This gets the value for Session time out interval from the web.xml and prepares dynamic java script call as shown below

       

  package com.atd.tirepro.view.filter;


import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import oracle.adf.controller.v2.lifecycle.Lifecycle;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.controller.v2.lifecycle.PagePhaseListener;

import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;


public class TimeOutListener implements PagePhaseListener {
    @SuppressWarnings("compatibility:-1406793285197613021")
    private static final long serialVersionUID = 1L;

    public TimeOutListener() {
        super();
    }

    /**
     * This method determines whether session timed out or not,
     * If session timed out , redirects to corresponding Apps Login page
     * based on configured properties file
     * @param phaseEvent
     */
    public void beforePhase(PagePhaseEvent phaseEvent) {
    }


    public void afterPhase(PagePhaseEvent pagePhaseEvent) {
        if (pagePhaseEvent.getPhaseId() == Lifecycle.PREPARE_RENDER_ID) {
            FacesContext facesCtx = FacesContext.getCurrentInstance();
            ExternalContext extCtx = facesCtx.getExternalContext();
            // Get HttpSession instance
            HttpSession session = (HttpSession)extCtx.getSession(false);
            // Get HttpServletRequest instance
            HttpServletRequest req =
                (HttpServletRequest)extCtx.getRequest();
            if (session != null) {
                int secsTimeout = session.getMaxInactiveInterval();
                if (secsTimeout > 0) {
                    String appURL ="http://www.google.com";
                    secsTimeout += 2;
                    String jsCall =
                        "document.acmeStartClientSessionTimers = function()\n" +
                        "{\n" +
                        "  if(document.acmeSessionTimeoutTimer != null)\n" +
                        "    window.clearTimeout(document.acmeSessionTimeoutTimer);\n" +
                        "\n" +
                        "  document.acmeSessionTimeoutTimer = window.setTimeout(\"document.acmeClientSessionTimeout();\", " +
                        secsTimeout * 1000 + ");\n" +
                        "\n" +
                        "}\n" +
                        "document.acmeStartClientSessionTimers();\n" +
                        "\n" +
                        "document.acmeClientSessionTimeout = function()\n" +
                        "{\n" +
                        "    window.location.href = '" + appURL + "' \n" +
                        "}";

                    ExtendedRenderKitService rks =
                        Service.getRenderKitService(facesCtx,
                                                    ExtendedRenderKitService.class);
                    rks.addScript(facesCtx, jsCall);
                }
            }
        }
    }

    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
}

       
 

Step2 :  Configure above page Phase Listener in adf-settings.xml as shown below
Step3 : Configure session time out interval in web.xml as shown below

 <session-config>
    <session-timeout>2</session-timeout>
  </session-config>

This will automatically redirect to custom URL whenever session expires.

How to Configure or Implement PagePhaseListener in ADF


This blog explains about configuring or implementing Page Phase Listener in an ADF application

Brief info about adf-settings.xml

The adf-settings.xml file holds project- and library-level settings such as ADF Faces help providers. The configuration settings for the adf-settings.xml files are fixed and cannot be changed during and after application deployment. There can be multiple adf-settings.xml files in an application. ADF settings file users are responsible for merging the contents of their configurations.

Step1
Create Java class which extends to PagePhaseListener as shown below. You need to override afterPhase() and beforePhase() methods as shown below.

       

  package com.atd.tirepro.view.filter;


import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import oracle.adf.controller.v2.lifecycle.Lifecycle;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.controller.v2.lifecycle.PagePhaseListener;

import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;


public class TimeOutListener implements PagePhaseListener {
    @SuppressWarnings("compatibility:-1406793285197613021")
    private static final long serialVersionUID = 1L;

    public TimeOutListener() {
        super();
    }

    /**
     * This method determines whether session timed out or not,
     * If session timed out , redirects to corresponding Apps Login page
     * based on configured properties file
     * @param phaseEvent
     */
    public void beforePhase(PagePhaseEvent phaseEvent) {
    }


    public void afterPhase(PagePhaseEvent pagePhaseEvent) {
        if (pagePhaseEvent.getPhaseId() == Lifecycle.PREPARE_RENDER_ID) {
            FacesContext facesCtx = FacesContext.getCurrentInstance();
            ExternalContext extCtx = facesCtx.getExternalContext();
            // Get HttpSession instance
            HttpSession session = (HttpSession)extCtx.getSession(false);
            // Get HttpServletRequest instance
            HttpServletRequest req =
                (HttpServletRequest)extCtx.getRequest();
        }
    }

    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
}

       
 

Step2
Configure adf-settings.xml as shown below, If this file is not available , then create a brand new xml file with exactly same name as 'adf-settings.xml' and place at 'ViewController\adfmsrc\META-INF' folder, If META-INF is not available create new directory.

Configure above PagePhaseListener class in adf-settings.xml as shown below



Step3 : Clean all, Build all and start the application, Keep the debug point in afterPhase() or beforePhase() methods,  before every page gets loaded beforePhase() method will get invoked.

Monday, April 21, 2014

How to handle session time out Programatically in ADF ? How to configure Session Time out ?

This blog explains about how to redirect to specific URL when session time out occurs. By default, default session out time is 45 minutes if nothing specified

This blog also explains about how to configure session time out in weblogic.xml as well as in any ADF application


Below is how we can configure session time out for any ADF Application, This can be done through web.xml

<session-config>
  <session-timeout>10</session-timeout>
</session-config>

You can edit the File weblogic.xml: Edit the session-param TimeoutSecs in the file weblogic.xml. In weblogic.xml, the session timeout is set in seconds.

 <session-descriptor>
       <session-param>
           <param-name>TimeoutSecs</param-name>
          <param-value>3600</param-value>
      </session-param>
 </session-descriptor>

You can also configure sesion time out using weblogic console as well,
Login to Weblogic console -> Deployments -> Click on the application -> Follow below step


Note that the timeout value set in web.xml takes precedence over weblogic.xml. If you don't set any values in web.xml, weblogic.xml takes over. A good approach to handle session timeout is setting this just on web.xml itself since web.xml takes precedence over application server’s deployment descriptors.




- Write below SessionExpiryFilter class, In this class I am verifying the old and new session Id values, if both are different means, session is expired and redirecting the respective URL.

       

  package com.fm.recruitment.view.filter;
  
  import java.io.IOException;
  
  import javax.servlet.Filter;
  import javax.servlet.FilterChain;
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
   
  public class SessionExpiryFilter implements Filter {
      private FilterConfig _filterConfig = null;
   
      public SessionExpiryFilter() {
          super();
      }
   
      public void init(FilterConfig filterConfig) throws ServletException {
          _filterConfig = filterConfig;
      }
   
      public void doFilter(ServletRequest servletRequest,
                           ServletResponse servletResponse,
                           FilterChain filterChain) throws IOException,
                                                           ServletException {
          String requestedSession =
              ((HttpServletRequest)servletRequest).getRequestedSessionId();
          String currentWebSession =
              ((HttpServletRequest)servletRequest).getSession().getId();
          String requestURI =
              ((HttpServletRequest)servletRequest).getRequestURI();
          boolean sessionOk =
              currentWebSession.equalsIgnoreCase(requestedSession);
          System.out.println("currentWebSession == requestedSession? : " + sessionOk);
          if (!sessionOk && requestedSession != null) {
              requestURI="http://www.google.com";
              ((HttpServletResponse)servletResponse).sendRedirect(requestURI);
              System.out.println("redirecting to : " + requestURI);
          } else {
              filterChain.doFilter(servletRequest, servletResponse);
              System.out.println("session is OK");
          }
      }
   
      public void destroy() {
          _filterConfig = null;
      }
  }

       
 

- Below is how we configure Filter through web.xml

 <filter>
 <filter-name>SessionExpiryFilter</filter-name>
   <filter-class>com.fm.recruitment.view.filter.SessionExpiryFilter</filter-class>
 </filter>
<filter-mapping>
  <filter-name>SessionExpiryFilter</filter-name>
   <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

More about Deployment descriptor or web.xml
http://docs.oracle.com/cd/E15523_01/web.1111/e13712/web_xml.htm#i1023849

Thursday, April 10, 2014

How to reset data on a ADF Form?

Below blog explains about resetting a specific portion of data on a ADF form,
For example, User is editing employee form, which has various components such as form, table etc. If you want to reset data in a specific component, follow below



 public void resetFormFieldsListener(ActionEvent actionEvent)
{
    // check if hte action has a component attatched
    UIComponent uiComp = actionEvent.getComponent();
   
    if (uiComp == null)
    {
        // if not we use the button which we bound to this bean
        uiComp=getButtonResetByBean();
        _logger.info("reset fields: buttonID = " + uiComp.getId());
    }
    else
    {
        _logger.info("reset fields: CompID = " + uiComp.getId());
    }
    // pass component inside the UIForm, UIXForm, UIXSubform, UIXRegion, UIXPopup, RichCarousel
    // or RichPanelCollection which holds the components to reset
    ResetUtils.reset(uiComp);
}

Tuesday, April 1, 2014

How to Mark Selected row in as current row in SelectionListener ?

This blog explains about how to make the selected row in <af:table> component  as a current row Progromatically using selection Listener

       
    
 import javax.el.ELContext;
 import javax.el.ExpressionFactory;
 import javax.el.MethodExpression;
 import javax.el.ValueExpression;

 import javax.faces.context.FacesContext;

 import oracle.jbo.Row;

 import org.apache.myfaces.trinidad.event.SelectionEvent;

    /**
     * Programmatic invocation of a method that an EL evaluates to.
     *
     * @param el EL of the method to invoke
     * @param paramTypes Array of Class defining the types of the parameters
     * @param params Array of Object defining the values of the parametrs
     * @return Object that the method returns
     */
    private  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);
    }

    public Object evaluateEL(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);
    } 
    
     /**
     * This method invoke whenever any row selected in  component
     * @param selectionEvent
     */
    public void empSelListener(SelectionEvent selectionEvent) {
        // Below is the code to make the selected row as current row
        invokeEL("#{bindings.EmployeesView1.collectionModel.makeCurrent}", new Class[] { SelectionEvent.class }, new Object[] {
                         selectionEvent });
        Row selectedRow = (Row)evaluateEL("#{bindings.EmployeesView1.currentRow}");
        System.out.println(selectedRow.getAttribute("LastName"));
    }
       
 

- Ensure to override the selectionListener attribute to a backing bean method as shown below
 - Below is the <af:table> component, I have selected '102' row
 - Displays the selected row corresponding last name



How to get ViewObject and RowImpl class in Backing bean using DCIteratorBindings in ADF ?


Below blog explains about how to get View Object and Row Impl class in backing bean using DCIteratorBindings

import oracle.adf.model.binding.DCIteratorBinding;

    /**
     * Find an iterator binding in the current binding container by name.
     *
     * @param name iterator binding name
     * @return iterator binding
     */
    public static DCIteratorBinding findIterator(String name) {
        DCIteratorBinding iter = getBindingContainer().findIteratorBinding(name);
           return iter;
    }


    public static BindingContainer getBindingContainer() {
        return (BindingContainer)JSFUtils.resolveExpression("#{bindings}");
    }
Example how to use

Get the Row Impl class in Backing bean, Ensure 'EmployeeViewIterator' must be available in page definition bindings.

        EmployeeViewRowImpl empRow =
            (EmployeeViewRowImpl )findIterator("EmployeeViewIterator").getCurrentRow();


Below code sample shows how to get View Object instance in backing bean using DIteratorBindings, Ensure 'EmployeeViewIterator' must be available in corresponding page definition bindings
        ViewObject agreementLocationViewObject =
            findIterator("EmployeeViewIterator").getViewObject();