This document covers the following topics:
If a client makes a request to create an object of a certain class, it is DCOM's task
to start a server process that provides the class and to direct the request to this
process. For Natural classes, the responsible server process is a NaturalX server. DCOM
recognizes different options that control when a new server process is started or when
an object is created in a server process that is already running. For further
information, see the section Registration. While registering a Natural class with
the REGISTER command, you can control which
activation options DCOM shall use for this class. NaturalX combines the different
options supported by DCOM in the form of the following three activation policies:
ExternalMultiple
If a Natural class is registered with the activation policy
"ExternalMultiple", and a client requests an object of
that class, DCOM tries first to create the requested object in the current process.
Remember that the client itself might at the same time be a NaturalX server and
might provide the class itself. If the current process is not a server for the
class, DCOM starts a new NaturalX server process and creates the object in that
process. If a second object of the same class is created later, this object is also
created in that server process. This means that the same server process can contain
several objects of the class.
ExternalSingle
If a Natural class is registered with the activation policy
"ExternalSingle", DCOM starts a new NaturalX server
process each time an object of this class is created. One server process can contain
only one object of the class.
InternalMultiple
If a Natural class is registered with the activation policy
"InternalMultiple", DCOM always creates objects of this
class in the current process. The same server process can contain several objects of
the class.
The default activation policy is "ExternalMultiple". This
default is defined with the Natural parameter ACTPOLICY and can be changed with the Configuration Utility.
The activation policy of a class can be set in three different ways, in the following order of precedence:
Explicity as part of the REGISTER command.
In the DEFINE CLASS
statement.
With the profile parameter ACTPOLICY.
Non-trivial DCOM applications will mostly deal with "persistent" objects, i.e. objects stored in databases. For such applications, some considerations concerning database access, transaction handling and user isolation must be made. Consider the following scenario: clients A and B both create an object of a class that is provided by a certain NaturalX server process. Assume that the NaturalX server uses a database to load and store its objects. If both clients were served by the same server process, they would appear to the database as one single user. This would have the consequence that a transaction started by a method call from Client A can be committed or backed out by a method call from Client B. Such interferences are obviously to be avoided.
There are two approaches to avoid this interference: either the clients do not use persistent objects, or each of them is served by its own NaturalX server process. Both approaches have their advantages in different situations; for a class or application that does not access databases or other shared resources, it is useful to serve several clients with a single server process. For classes that access databases or other shared resources, it is necessary to isolate different clients in different server processes. Hence both approaches should be possible. Activation policies give an administrator the means to control the activation behavior for each class at registration time.
This example illustrates how the various activation policies can be used. Let us
consider parts of an imaginary travel agency application. The application contains the
business classes Trip, Skipper and
RoutePlanner. The Trip class
represents a sailing trip to be planned; the Skipper class
represents the skippers available to lead the trips.
RoutePlanner is a class that determines an optimal route for
a trip. Assume that the Trip and Skipper
classes use a database to read and store their objects. The
RoutePlanner class just performs some calculations on a given
Trip object and does not use a database.
Since some of the business classes use transactional access to a database, and a
transaction might span several method calls, each active client needs to be served
with its own NaturalX server process. This can be done by defining an additional class
SagTours, which represents an application session. This class
can be used, for example, to keep general information about the session status, but
the main task will be to create business objects on behalf of a client.
* Represents a SagTours application session.
*
define class SagTours
local using tour-ids
id clsid-sagtours
*
interface Create /* Used to create application objects. */
id iid-sagtours-create
*
method newTrip /* Creates a new Trip object. */
is trip-n
parameter
1 trip handle of object by value result
end-method
method newSkipper /* Creates a new Skipper object. */
is skip-n
parameter
1 skipper handle of object by value result
end-method
*
end-interface
*
end-class
end
This class will be registered as "ExternalSingle". This
means that each creation of a SagTours object starts a
NaturalX server process for the client that requested the object. A client will
create a SagTours object only once and will use its methods
later to create the business objects it needs. In order to create a
Trip object, the client will call the method
newTrip, which is implemented as follows.
* This method creates a new Trip object. * define data parameter 1 trip handle of object by value result end-define * create object trip of class "Trip" * end
The Trip class itself will be registered as
"InternalMultiple". This ensures that the
Trip objects created by the method
newTrip are created in the NaturalX server process just
started for this client.
Now let us look at the class RoutePlanner.
* Plans optimal routes for sailing trips.
*
define class RoutePlanner
local using tour-ids
id clsid-planner
*
interface routing
id iid-planner-routing
*
method plan /* Plans a sailing trip. */
is plan-n
parameter
1 trip handle of object by value
end-method
*
end-interface
*
end-class
end
* This method plans a sailing trip. * define data parameter 1 trip handle of object by value end-define * * Perform some operations on the given Trip object. * end
This class can be registered as "ExternalMultiple". In
this case, all RoutePlanner objects created by different
clients would be created in the same NaturalX server process. This does not do any
harm if the methods of this class do not access databases, or if each database
transaction is fully contained in a method (i.e. if each method subprogram ends with
either a BACKOUT
TRANSACTION statement or an END TRANSACTION statement).
Now let us look at a sample client program.
define data local sagTours handle of object trip handle of object planner handle of object end-define * * Start the application session. create object sagTours of "SagTours" * * Create a Trip object. send "newTrip" to sagTours return trip * Create a RoutePlanner object. create object planner of "RoutePlanner" * Plan the trip. send "plan" to planner with trip * end
The client first creates a SagTours object. This starts a
new NaturalX server process exclusively for this client. The client then uses the
SagTours object to create a Trip
object in the context of this application session. Note that the client creates the
RoutePlanner object directly. This is possible because the
class is registered as "ExternalMultiple", but it is not
necessary: the SagTours class could also provide a method for
the creation of RoutePlanner objects. Afterwards it lets the
business objects do their jobs. The objects are automatically released at program
end. The deletion of the SagTours object causes the NaturalX
server to shut down.
Note
This example shows only the NaturalX techniques needed to illustrate the usage
of activation policies. A real-world application would require a lot more. The
classes would use object data areas and they would surely have globally unique IDs
assigned. Also parameter data areas would be used instead of inline parameter
declarations.