Wednesday 21 September 2011

OraFormsFaces using a reusable Task Flow to load Forms in a common way

I've implemented a common/reusable Task Flow to load Oracle Forms in a generic way in order to function as part of an ADF Web Application in an integrated fashion.

Below is the source-xml of the Task Flow I've implemented (oraFormsFaces-tfd.xml):
<?xml version="1.0" encoding="windows-1252" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
  <task-flow-definition id="oraFormsFaces-tfd">
    <default-activity>loadForm</default-activity>
    <input-parameter-definition id="__2">
      <name>formName</name>
      <value>#{pageFlowScope.formName}</value>
      <class>java.lang.String</class>
      <required/>
    </input-parameter-definition>
    <input-parameter-definition id="__3">
      <name>ipAddress</name>
      <value>#{pageFlowScope.ipAddress}</value>
      <class>java.lang.String</class>
      <required/>
    </input-parameter-definition>
    <input-parameter-definition id="__4">
      <name>formDescription</name>
      <value>#{pageFlowScope.formDescription}</value>
      <class>java.lang.String</class>
      <required/>
    </input-parameter-definition>
    <managed-bean id="__1">
      <managed-bean-name>oraFormsFacesBean</managed-bean-name>
      <managed-bean-class>com.myflow.common.view.oraformsfaces.OraFormsFacesBean</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    <view id="loadForm">
      <page>/oraformsfaces/loadForm.jspx</page>
    </view>
  </task-flow-definition>
</adfc-config>


You'll notice the following from the above listing:
  1. I've defined three (3) input parameters to my Task Flow for it was required by the specific use case. An interesting thing to mention is that I had to set these input parameters dynamically. This is actually done in a very simple way by calling the above Task Flow with an URL as follow: "/faces/adf.task-flow?adf.tfId=oraFormsFaces-tfd&adf.tfDoc=/WEB-INF/oraformsfaces/oraFormsFaces-tfd.xml", and then simply appending the input parameters as request parameters to the URL as such: "?formName=MYORAFM&ipAddress=10.4.5.6.7&formDescription=My Oracle Form".
  2. I've implemented a backing bean (OraFormsFacesBean) within the Task Flow to facilitate the representation of user friendly information to the user AND to expose the values to be passed to OraFormsFaces and Forms as available attributes retrievable from the backing bean. As you'll see later these attributes are referenced from the loadForm.jspx page.
  3. The page, /oraformsfaces/loadForm.jspx, facilitates the load of the actual OraFormsFaces Form component. Please see the source of this page in the listing below:
loadForm.jspx
<?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"
          xmlns:off="http://commit-consulting.com/OraFormsFaces/tags">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document title="SPIF" id="loadFormDoc" maximized="true">
      <af:pageTemplate id="p_tmpl" viewId="/templates/defaultFormTemplate.jspx">
        <f:facet name="mainContent">
          <af:panelGroupLayout id="pgl2" styleClass="AFStretchWidth">
            <off:form formModuleName="#{pageFlowScope.formName}" id="oraFormsFacesForm" clipApplet="true"
                      autoClipTop="menu" loadingImage="preset5" autoSize="true" uniqueAppletKey="piet">
              <off:formParameter id="userID" value="#{oraFormsFacesBean.username}"/>
              <off:formParameter id="companyCode" value="#{oraFormsFacesBean.companyCode}"/>
              <off:formParameter id="clientIP" value="#{pageFlowScope.ipAddress}"/>
              <off:formParameter id="companyCode" globalName="companyCode" value="#{oraFormsFacesBean.companyCodeCode}"/>
              <off:formParameter id="userid" globalName="userid" value="#{oraFormsFacesBean.username}"/>
            </off:form>
          </af:panelGroupLayout>
        </f:facet>
        <f:attribute name="formBean" value="#{oraFormsFacesBean}"/>
        <f:attribute name="displayLinksFacet" value="false"/>
      </af:pageTemplate>
    </af:document>
  </f:view>
</jsp:root>



Please note how I've used the OraFormsFacesBean as backing bean to provide the values:
  • formName
  • username (send through as 'userID')
  • companyCode (also send through as 'companyCode')
  • ipAddress (send through as 'clientIP')
Also important to note, is that there are two (2) Global Forms Parameters (going directly through to Oracle Forms) and three (3) OraFormsFaces Parameters of which I only passed through the latter in order for it to get used by the off_lib.pll (PLS/SQL library) provided as part of the OraFormsFaces installation.

For completeness sake, I'll explain what I did in the off_lib.pll PL/SQL library. First observe the script sniplet below:
    elsif eventName = 'initapplet' then
          -- add code here that is execute when the applet is first started
          -- in a browser session. This is not re-executed when the applet is
          -- reused on subsequent pages.
          --null;
          v_params := offParams.getParameters;
          v_userID := offParams. getParamValue(v_params, 'userID');
          v_companyCode := offParams. getParamValue(v_params, 'companyCode');
          v_clientIP := offParams. getParamValue(v_params, 'clientIP');
          APPSYS.AUTH.prepare_session(v_userID,v_companyCode,v_clientIP);

You'll notice that I've added a few statements in the 'initapplet'-clause of the "eventName-if-statement" as found in the handleGlobalEvent(eventName in varchar2) procedure in off_lib.pll. These statements simply extract the parameters which were sent through and then send them through to an implemented Stored Procedure that will do the necessary preparation work for the Oracle Forms to function in an integrated fashion. For example, this procedure will set the session identifier on the database session to the value of 'userID' for auditing purposes.

I hope someone finds this as useful as I did!
 

No comments:

Post a Comment