Calling User Methods from Packages

JADE enables you to provide an interface when creating a package to allow the user of the package to register a callback method to be invoked when a specific event occurs. (See also "Package Callback Examples", in the following subsection.)

When the package calls the method, it enables the schema in which the package is imported to perform the required functionality; for example, in an appointment book package in which you want to associate an alarm with an appointment.

When the starting time is reached, the alarm in the appointment book package calls the importing package callback method, which can send an e-mail message, bring up an alert form, or perform some other such action to alert the user of the impending appointment.

The package user must supply and the package writer must save the information required to perform the callback. A callback is registered by the package user supplying the target:

The package would normally export a method to allow the package user to supply this information.

Within a package, use the Object class invokeMethod method on the saved object to invoke the method and return the result. This method has as parameters the saved context and the saved method, and any parameters that are required.

invokeMethod(targetContext: ApplicationContext;
             targetMethod:  Method;
             paramList:     ParamListType): Any;

As part of the call, the invokeMethod call switches context to the saved context. This switch will typically be from the context of the package to the context of the user of the package.

As the application context used by invokeMethod is transient, it can switch to a context only within the same process. The mechanism is not designed to call a method running in another process in the node or in another node.

In addition, as the context is transient, any connection between a context and a method to be invoked must be set up again if an application is stopped and then restarted. If you want to save events to be called persistently so that methods would still be called if the application stops and restarts (for example, in a scheduler application), you would have to re-supply a context when the application restarts and events are loaded. The target method and object could be persistent but the context is not.

The targetMethod parameter must be a valid method, which is executed when the invokeMethod method is called. Use the paramList parameter to specify a variable list of parameters of any type that are passed to the method or condition specified in the targetMethod parameter when it is executed.

For details about the ParamListType pseudo type, see "ParamListType" under "Pseudo Types", in Chapter 1. See also "Passing Variable Parameters to Methods" under "JADE Language Syntax", in Chapter 1.

If the number or type of the actual parameters passed to a method by a parameter list does not correspond exactly to the formal parameter list declaration, an exception or an unpredictable result may occur, as the compiler is unable to perform any type checking on the values that are passed to a parameter list. However, the Method::isCallCompatibleWith method, described earlier in this section, enables you to validate the number and type of parameters.

When an exception handler is invoked from a package method, the package context is switched to the context that was in effect when the exception handler was armed. When the exception handler finishes, the package context is adjusted back, if required.

Although the callback mechanism is designed with packages in mind, you can also use it to allow a method to be invoked from within the same context. If the context in the invokeMethod call is null, the current context (that is, appContext) is used. This therefore enables you to invoke a specific saved method (for example, myClass::myMethod) rather than calling the Object::sendMsg method, which allows you to provide only the name of the method to which the message is sent.

Within a package, the package writer may want to check that the method supplied by the user of the package is appropriate. The Method::isCallCompatibleWith method checks that the target method supplied by the package user cannot only be invoked on the specified target object but that it has a signature that is compatible with that expected by the package.

The isCallCompatibleWith method has the following signature.

isCallCompatibleWith(targetObject:  Object;
                     exampleMethod: Method): Boolean;

When a process begins, transient instances of the ApplicationContext class are created (along with other environmental objects such as app and global) for the main application in which the package is imported and for each package application.

The ApplicationContext class provides the read-only properties listed in the following table.

Property Contains a reference to the …
initialApp Application instance of the context
initialPackage JadePackage instance of the context
initialProcess Process instance of the context; that is, the current process
initialSchema Schema instance of the context

To support the calling of user methods from packages, you can use the appContext system variable operand to denote the current context; that is, a transient instance of the ApplicationContext class. This instance encapsulates the current execution context and contains all of the information required for a method to switch back to the current context when a method is called. (Such a switch is the same as that which occurs when the context is switched on the call of an imported method.)

JADE automatically creates a unique appContext object for each JADE application that is running and for each package that is imported (recursively) by the schema from which that application is running.

The appContext system variable enables a package to switch context back to the context of the application that imported the package, by calling the Object class invokeMethod method.