There is enhanced support for managing modules in Jdapi. An abstract type,
oracle.forms.jdapi.JdapiModule
, which the concrete types (FormModule,
MenuModule, PlsqlModule, ObjectLibrary
) extend, can be used to load and
refer generically to different module types. Each module type also has its own
open()
and save()
methods.
All loaded and newly created modules are saved in the session module list.
An iterator of the current set can be obtained by calling Jdapi.getModules()
.
Also, each module is uniquely identified by its path on the file system; that
is, where it was opened from or last saved to, obtained by calling JdapiModule.getAbsolutePath()
,
so attempting to reopen an open module a second time will simply return the
open module.
The following example demonstrates how to load a module using Jdapi.
import oracle.forms.jdapi.*; /** * Example to illustrate how modules are loaded using Jdapi * * We load a list of modules passed from the command line * (e.g. *.fmb). These modules are saved to the module list on loading, * from where they can be subsequently accessed. The example goes on to * search the module list for a given name and deletes any modules with * that name. Note they are NOT deleted from the file system. */
public class ModuleListExample { public static void main(String[] args) {// load all modules passed on the command line
for (int i = 0; i < args.length ; i++) {// the first time openModule is called will initialize the API
JdapiModule mod = JdapiModule.openModule(args[i]); }// get the module list from the session...
JdapiIterator mods = Jdapi.getModules();// ... and iterate round them
while(mods.hasNext()) { JdapiModule mod = (JdapiModule)mods.next();// getStringProperty(JdapiTypes.NAME_PTID) is equivalent to getName()
String moduleName = mod.getName(); System.out.println("Module Name: " + moduleName);// Get rid of Form Modules with this name
,// but not other module types
if ( mod instanceof FormModule && moduleName.equals("some_name"))
{ mod.destroy(); } }// finally, clean up
Jdapi.shutdown(); } }
Comments: Even though the JdapiModule
variable
mod
goes out of scope outside the initial for
... loop,
when a module is loaded a reference to that module is automatically saved on
the session module list so that it can be retrieved later. These references
are stored in a Vector object, and they are in addition to the object cache's
references.
Because JdapiModule
indirectly implements JdapiObject
you can call getName()
without casting to the real module type,
instead of using the generic getStringProperty()
method. getName()
is the only non-generic property accessor method included (for convenience)
in the JdapiObject
interface.
Objects referenced by generic types can be tested for their real type in the
normal Java way using the instanceof
operator. Alternatively, you
can call the getTypeId()
or queryType()
methods of
any Forms object; both return an integer which can be compared with Object Type
ID values (JdapiTypes.<*>_OTID
). For example:
if (mod.getTypeID() == JdapiTypes.FORM_MODULE_OTID) ...
Note that calling destroy()
on Forms Modules (or any other Forms
objects) is necessary to free the underlying native object. If the reference
to the object instance were simply set to null, you would lose the only immediate
reference to the underlying native object's allocated memory and the result
would be a memory leak. The object cache retains a reference to the object in
question, preventing garbage collection and preserving the native memory address.
However, it would be necessary to find and navigate to that given object again
in order to invoke destroy()
.
However, calling the destroy()
method on a given
object is guaranteed to automatically clean up all objects owned by that object,
so you do NOT need to explicitly iterate through a module hierarchy destroying
all its owned objects before destroying the module. Since a Forms object can
not be instantiated independently of an owning module, calling Jdapi.destroyAllModules()
is guaranteed to clean up the entire Jdapi session. This approach has been
chosen because Java finalizers are not guaranteed to be invoked prior to garbage
collection.
Calling Jdapi.shutdown()
alone will also free
all natively-allocated resources, which works by calling Jdapi.destroyAllModules()
.