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
| Module | File | Role in the application |
|---|---|---|
| PL/SQL library | cw_lib.pll | Messages, the signed-in user and roles, error messages, navigation |
| Object library | cw_objects.olb | Alerts and visual attributes that every form subclasses |
| Template form | cw_template.fmb | The starting point of every form: window, library, menu, standard objects |
| Menu | cw_app.mmb | The menu of every form, with a Clinic menu that opens the modules |
| Sign-in form | cw_login.fmb | The first form: who is using the application |
| Home form | cw_main.fmb | The day's figures, a report, buttons to the modules |
| Patients | cw_patients.fmb | Finding a patient, then opening the patient's appointments or invoices |
| Appointments | cw_appointments.fmb | A patient's appointments, with booking checks |
| Billing | cw_billing.fmb | Invoices, their lines, and payments |
| Report | cw_appt_schedule.rdf | The 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:
| Variable | Holds |
|---|---|
| CW_SEC.USERNAME, CW_SEC.FULL_NAME, CW_SEC.APP_ROLE | The signed-in user and role |
| CW_CTX.PATIENT_ID | The 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.
