Tuesday, 2 September 2008

A method for adopting OraFormsFaces for JDeveloper

Recently I had the luck of trying out Wilfred van der Deijl's excellent OraFormsFaces, a bridging tool that allows Oracle Forms sites to embed Forms within a JDeveloper JSF application and more importantly allows them to communicate with each other through standard Forms globals & parameters, and JSF EL expressions and events. Overall my client was impressed, especially thanks to Wilfred's kind assistance on sorting out some of the tricky parts of their Oracle Forms implementation.

I highly recommend organisations should look to OraFormsFaces to move beyond the analysis paralysis of where to move next after Oracle Forms. On adopting OraFormsFaces you will instead realise that rather redeveloping your entire legacy Oracle Forms system in JDeveloper or whatever technology, an expensive and risky task because you have many man years and dollars wrapped up in your legacy system, instead you can integrate Oracle Forms with JDeveloper, leaving JDeveloper for new subsystems.

As thanks to Wilfred, we'd like to publish documentation, on a method for adopting OraFormsFaces. We hope this will be useful to others out there looking at adopting OraFormsFaces in the near future.

Please note the following documentation is draft, your mileage may vary, and it should be read hand-in-hand with the OraFormsFaces documentation.

A method for adopting OraFormsFaces

The following describes a prescribed approach to adopting OraFormsFaces at your organisation in achieving the following goals:
  • Minimize risk by identifying technical issues early
  • Run OraFormsFaces in both an Oracle Forms Builder and OAS environment
  • Reduce the learning curve for staff by breaking the adoption into manageable sections
  • Identify approaches to integration for your specific legacy Oracle Forms system
The prescribed approach to achieve these goals:

1. Test the basic OraFormsFaces integration between a running JDeveloper JSF page and a compiled Forms Builder fmx.

This step will test you have correctly installed and/or configured:
  • The OraFormsFaces Oracle Forms support files
  • The OraFormsFaces JDeveloper support files and configured JDeveloper appropriately
  • A JDeveloper application workspace with the required web.xml settings
  • That the JDeveloper Embedded OC4J can communicate to the Oracle Forms Standalone OC4J
  • The local Oracle Forms formsweb.cfg file with the new OraFormsFiles entries
  • The local Oracle Forms Standalone OC4J can pick the formsweb.cfg options up
  • Your browser to run with the Sun JVM
To achieve this test, as per the OraFormsFaces guide, setup a standalone development PC with Oracle Forms 10gR1/R2, JDeveloper 10g/11g. Create a test JSF page with an embedded OraFormsFaces forms component, calling a test dummy Oracle Form of your devising.

2. Test passing values from a JDeveloper JSF page to a Form's parameters and global constructs, and the Form returning values to a JSF page.

This step will test the data value passing between JSF and Oracle Forms using OraFormsFaces, including:
  • JSF can pass values to a Form named parameter and named global (proven by Forms being able to receive and display those values in a text area)
  • Forms can pass a value back to JSF bean (proven by JSF showing the bean value in an inputText control)
  • Forms can execute a JSF command control
To achieve this test, extend the first step to get the JSF page to pass globals and parameters to the Oracle Form, and the Oracle Form to pass globals and parameters back to the JSF page. Do the following:

a) In your form create a block and 3 text items: p_some_param, g_some_global, p_some_jsf_value.

b) Also in the form add 2 buttons: update_jsf_page, exit_button.

c) In the when-new-form-instance-trigger add the following code:

IF :parameter.p_some_param IS NULL THEN
  :some_block.p_some_param := 'NULL';
ELSE
  :some_block.p_some_param := :parameter.p_some_param;
END IF;

BEGIN
  IF :global.g_some_global IS NULL THEN
    :some_block.g_some_global := 'NULL';
  ELSE
    :some_block.g_some_global :=
      :global.g_some_global;
  END IF;
EXCEPTION
  WHEN OTHERS THEN
    :some_block.g_some_global := 'DOESN''T EXIST';
END;

DECLARE
  v_some_jsf_value VARCHAR2(100);

  tableParams offParams.typeParams;

BEGIN
  tableParams := offParams.getParameters;

  v_some_jsf_value :=
    offParams.getParamValue(
      tableParams, 'someJsfValue');

  IF v_some_jsf_value IS NULL THEN
    :some_block.p_some_jsf_value := 'NULL';
  ELSE
    :some_block.p_some_jsf_value := v_some_jsf_value;
  END IF;
END;


d) On the update_jsf_page button add the following when-button-pressed trigger code:

offParams.setParamValue('someJsfValue',
  :some_block.p_some_jsf_value);
offInterface.execJSFCommand('someCommand');


e) On the exit_button add the following when-button-pressed trigger code:

exit_form;

f) Finally in the Oracle Form create a Form level parameter p_some_param, a String 30 characters in length.

In your JSF page add the following code:

<af:form>
  <off:form clipApplet="false"
            formModuleName="ORAFORMSFACESDEMO"
            height="480" width="640"
            showDevControls="true">
    <off:formParameter
      formParameterName="p_some_param"
      value="A param value"/>
    <off:formParameter
      globalName="g_some_global"
      value="A global value" />
    <off:formParameter id="someJsfValue"
      value="#{someBean.someJsfValue}"
      valueChangeListener="#{someBean.someValueChangeEvent}"/>
    <off:formCommand id="someCommand"
      action="#{someBean.someAction}"/>
  </off:form>
  <af:outputText value="#{someBean.someJsfValue}"/>
  <af:commandButton text="Submit"/>
<</af:form>


g) Add a backing bean to the ViewController (name: someBean, class: view.SomeBean, scope: request) with the following code:

package view;

import javax.faces.event.ValueChangeEvent;

public class SomeBean {
  public SomeBean() { }

  String someJsfValue = "A JSF Value";

  public void setSomeJsfValue(String someJsfValue) {
    this.someJsfValue = someJsfValue;
  }

  public String getSomeJsfValue() {
    return someJsfValue;
  }

  public String someAction() {
    return null;
  }

  public void someValueChangeEvent(ValueChangeEvent event) {
    int fish =1;
  }
}


On running the JSF page, you should see the Forms app embedded with the 3 values populated from the JSF OraFormsFaces parameters (ie. A param value, A global value. You should be able to update the value in the form, press the Update JSF Page button and see the value reflected in the JSF page outputText control, and vice versa.

It would also be good practice for developers to improve their understanding of the interaction of OraFormsFaces with JSF at this point to place breakpoints on each of the bean methods above, run your JDeveloper in debug, and watch the interaction of the above methods.

3. Extend the last step by trying to clip off the Forms menu and borders such that only the data contents of the form page show.

4. Test passing values from a JDeveloper JSF page to an actual Oracle Form from your legacy system, which requires both named parameters and global variables:

This step will help you:
  • Understand how to identify parameters and globals in your Oracle Forms that OraFormsFaces will need to pass, as well identifying the actual parameters and globals and what values to pass.
  • Run your first real embedded Oracle Form to see if it will work within OraFormsFaces.
  • As extension of the last point, this will help you identify any problematic code that may need to be rewritten.
To achieve this test:

a) Identify the legacy system Oracle Form.

b) Embed the OraFormsFaces code into the Oracle Form as per the OraFormsFaces developers' guide.

c) Create a JSF OraFormsFaces page that passes in the relevant parameters and globals.

5. Test passing values from an actual legacy system Oracle Form to your JSF application.

This will step will help you:
  • Understand how you will need to generically modify existing code to pass values back to JSF.
  • Identify how different Forms programmers have traditionally passed values around your legacy system (though no exhaustively).
To achieve this test:

a) Identify the legacy system Oracle Form.

b) Embed the OraFormsFaces code into the Oracle Form as per the OraFormsFaces developers' guide.

c) Modify the existing Form to return values to the JSF page.

6. Once you are happy with the previous sections all done within Forms Builder, developers should attempt to move to an OAS environment testing their previous successes to ensure that the OAS is configured correctly to run OraFormsFaces.

7. If your legacy Forms applications uses embedded JavaBeans, for each Form embed it in a JSF OraFormsFaces page and test the form both in the Forms Builder and OAS environment, specifically exercising the JavaBean code. This will help identify any issues with the JavaBean called within the OraFormsFaces engine.

8. As an extension of the previous test, potentially the entire legacy Forms systems can be embedded and called from the one JSF OraFormsFaces page both in Forms Builder and the OAS environment. For testing purposes every legacy Form could be embedded with the OraFormsFaces code, then the main menu called form the JSF page, and regression testing undertaken to identify any issues.

9. By now you should have 3 documents you can produce:

a) Detailing how to setup your local Forms Builder environments to run with OraFormsFaces such that new developers and/or network admins know how to configure the development environment correctly.

b) Detailing how to configure your OAS to run with OraFormsFaces as per the developers' guide and any other configurations you need to do to suit your environment.

c) Detailing issues of where your current Forms application will need to be rewritten to work correctly within OraFormsFaces.

10. Finally at this point you're in a position how you wish to use OraFormsFaces for future development. There maybe a new subsystem you wish to implement within JDeveloper that needs to integrate with your existing legacy Forms system. There maybe a part of your existing system that you wish to redevelop in JDeveloper to make it easier for your users to use, but must still fit into your existing legacy Forms system. Considering any part of this last step is immature until you've gone through the previous steps to judge how well your system will integrate with OraFormsFaces.

6 comments:

Nicola said...

Hi,

congratulation to the author
of the article; it is more detailed than the official guide of Oracle Forms Faces;

I have only one question:
I have followed all the steps to see the Forms app embedded;
I can see the form, but at the beginning, parameters are null;
only if I press the button in the form or the button in the jsf page, I can see the value of parameters in the respective fields;
so, it seems that the first time that WHEN-NEW-FORM-INSTANCE is invoked, it can see the formParameters p_some_param and g_some_global;
is this the expected behaviour?
Thank you

Nicola Mancini

Chris Muir said...

Hi Nicola

Thanks for your kind comments, I do appreciate them :-)

I'm afraid I'm working on different projects at the moment with the usual project deadlines, and don't have time to revisit this post for sometime (plans are to revisit OraFormsFaces around October+), with my apologies.

If you discover a fix or work out what's meant to happen it would be appreciated if you could post your findings here.

Thanks & regards,

CM.

Nicola said...

Hi Chris,
thanks for your replay;

I'll make other tests;

I profit by this comment,
to correct a typing error
of my previous comment:
almost at the end I wrote

"so, it seems that the first time that WHEN-NEW-FORM-INSTANCE is invoked, it can see the formParameters p_some_param and g_some_global;"

instead, the correct sentence is

"so, it seems that the first time that WHEN-NEW-FORM-INSTANCE is invoked, it can't see the formParameters p_some_param and g_some_global;"

thank you

Nicola Mancini

Nicola said...

I noticed that:

in order to see the parameter
in WHEN-NEW-FORM-INSTANCE
even the first time,

off:form
and
off:formParameters
must be included in a
afh:body tag;

without this tag,
the first time, WHEN-NEW-FORM-INSTANCE can't see the parameter,
even if it exists in html source
with the correct value,
and only if WHEN-NEW-FORM-INSTANCE is fired a second time,
it can see the parameter!

Nicola Mancini

freakentwig said...

Hi Chris,

Have you ever implemented a custom Java class as Forms Credential provider in order to facilitate the setup of a database session when using OraFormsFaces? I need to do this now, but don't like the fact that you have to provide the password of the user.

I will appreciate any info or help from you in this regard.

Many thanks,
Hannes vd Merwe.

Chris Muir said...

Sorry, I can't say I have.

CM.