How to Structure a Multi-Form Oracle Forms Application

Organize an Oracle Forms 14.1.2 application into a library, template, menu, and forms that share the signed-in user and open each other one way.

A single form is easy to build. An application of many forms needs more: every form should know who signed in, open the others the same way, look alike, and respect the user's role. That comes from how the modules are organized, not from any one form.

This guide shows how to structure a multi-form application in Oracle Forms 14.1.2: the modules it is made of, how a shared library carries the signed-in user and the current record from form to form, and one procedure that every form and the menu use to open the others.

Sample Application for This Guide

The examples use a complete sample application of ten modules, all in the Oracle Forms code repository on GitHub. Each module is linked in the table below. Download them into one directory, open them in Forms Builder, and connect as CAREWELL to follow along.

The forms run against the CareWell Clinic sample schema, which you install first.

The Modules of the Application

ModuleFileRole in the application
PL/SQL librarycw_lib.pllMessages, the signed-in user and roles, error messages, navigation
Object librarycw_objects.olbAlerts and visual attributes that every form subclasses
Template formcw_template.fmbThe starting point of every form: window, library, menu, standard objects
Menucw_app.mmbThe menu of every form, with a Clinic menu that opens the modules
Sign-in formcw_login.fmbThe first form: who is using the application
Home formcw_main.fmbThe day's figures, a report, buttons to the modules
Patientscw_patients.fmbFinding a patient, then opening the patient's appointments or invoices
Appointmentscw_appointments.fmbA patient's appointments, with booking checks
Billingcw_billing.fmbInvoices, their lines, and payments
Reportcw_appt_schedule.rdfThe appointment schedule as a PDF

The flow is simple. The sign-in form replaces itself with the home form, and the home form opens the others, which can open each other. The first two are built in how to build a sign-in form in Oracle Forms and how to build a dashboard form in Oracle Forms. Every form except the sign-in form is created from the template, so each has the library attached, the menu, the standard alerts, and the same startup trigger.

The template and object library are explained in how to reuse objects with object libraries in Oracle Forms, and the library in how to create a PL/SQL library in Oracle Forms.

Share One Copy of the Library

After signing in, every form must know who the user is, and a form opened from another must know which patient the user was looking at. Both are package variables of the library:

VariableHolds
CW_SEC.USERNAME, CW_SEC.FULL_NAME, CW_SEC.APP_ROLEThe signed-in user and role
CW_CTX.PATIENT_IDThe patient chosen most recently

By default, each form gets its own copy of a library's package variables. Forms opened with SHARE_LIBRARY_DATA share one copy, so a value set in one form is seen by all. The application opens every form that way. The difference is shown in how to pass values between forms in Oracle Forms.

One Navigation Package

To make sure no form forgets SHARE_LIBRARY_DATA, all opening goes through one package of the library, CW_NAV.

Example (library CW_LIB, package CW_NAV specification):

package cw_nav is
  -- the start of every CareWell form: the signed-in user, or the form's P_USER when it runs alone
  procedure start_form(p_user varchar2);
  -- opens a module, or brings it to the front, for a patient (null: the current one)
  procedure open_module(p_form varchar2, p_patient_id number default null);
end cw_nav;

Example (library CW_LIB, package CW_NAV body):

package body cw_nav is
  procedure start_form(p_user varchar2) is
  begin
    if cw_sec.username is null then            -- not signed in: a form run on its own, for testing
      cw_sec.login(p_user);
    end if;
    cw_sec.apply_menu;
    set_window_property(forms_mdi_window, TITLE,
                        'CareWell Clinic - ' || cw_sec.full_name || ' (' || initcap(cw_sec.app_role) || ')');
  end start_form;

  procedure open_module(p_form varchar2, p_patient_id number default null) is
  begin
    if p_patient_id is not null then
      cw_ctx.patient_id := p_patient_id;       -- shared: every form sees the same package data
    end if;
    if id_null(find_form(upper(p_form))) then
      open_form(p_form, activate, no_session, share_library_data);
    else
      go_form(upper(p_form));                  -- open already: its WHEN-FORM-NAVIGATE catches up
    end if;
  end open_module;
end cw_nav;

START_FORM: the First Line of Every Form

Every form's WHEN-NEW-FORM-INSTANCE starts with START_FORM. When the user has signed in, CW_SEC.USERNAME is already set, and the form only applies the role to the menu and puts the user and role in the window title.

A form started on its own, from Forms Builder to test it, has no signed-in user. It then signs in the user named by its parameter P_USER, which the template gives every form. Each form can therefore be tested alone, as whichever user P_USER names.

Example (WHEN-NEW-FORM-INSTANCE trigger of the home form):

cw_nav.start_form(:parameter.p_user);
refresh_home;

OPEN_MODULE: Open a Form or Bring It Back

OPEN_MODULE records the patient, if one is given, and opens the form with SHARE_LIBRARY_DATA. If the form is already open, it goes to it with GO_FORM instead of opening a second copy. The open form then catches up with the new patient in its WHEN-FORM-NAVIGATE trigger, as shown in how to refresh an open form with WHEN-FORM-NAVIGATE.

Buttons call it, and so does the menu. Menu code can call a library that the menu module attaches, as the menu attaches cw_lib.

Example (menu item Clinic, Patients):

cw_nav.open_module('cw_patients');

Roles in the Menu and on the Forms

The library's CW_SEC.APPLY_MENU disables menu items that the user's role may not use, such as Invoices for everyone but the ADMIN and BILLING roles. Forms disable their own buttons with the same function, CW_SEC.HAS_ROLE, so the menu and the buttons always agree. Role-based menus are covered in how to secure menus with roles in Oracle Forms.

Compile Order

The structure also decides the compile order: the library first, then the menu, then the forms. The object library is not compiled, because its objects are copied into the forms. A script that does this is shown in how to automate Oracle Forms builds from the command line.

Conclusion

A multi-form Oracle Forms application is a PL/SQL library, an object library, a template form, a menu, and forms created from the template. Open every form with SHARE_LIBRARY_DATA so the signed-in user and the current record travel with the user, and route all opening through one procedure that also brings an open form back with GO_FORM. Start every form with the same procedure, and let roles disable both menu items and buttons through one function.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE and software veteran with 25+ years of experience, passionate about AI and IT innovation.

guest

0 Comments
Oldest
Newest Most Voted
00