VisiBroker for Java Developer’s Guide : Using object activators

Using object activators
This section describes how to use the VisiBroker object activators.
In this release, as well as the VisiBroker 4.1 release and later, the Portable Object Adaptor (POA) supports the features that were provided by the BOA in the VisiBroker 3.x and 4.0 releases. For backward compatibility reasons, you may still use the object activators as described in this section with your code. For more information on how to use the BOA activators with this release, see “Using the BOA with VisiBroker”.
Deferring object activation
You can defer activation of multiple object implementations using service activation with a single Activator when a server needs to provide implementations for a large number of objects.
Activator interface
You can derive your own interface from the Activator class. This allows you to implement the activate and deactivate methods that the VisiBroker ORB will use for the DBObjectImpl object. You can then delay the instantiation of the DBObjectImpl object until the BOA receives a request for that object. It also allows you to provide clean-up processing when the BOA deactivates the object.
This code sample shows the Activator interface, which provide methods invoked by the BOA to activate and deactivate an VisiBroker ORB object.
package com.inprise.vbroker.extension;
public interface Activator extends org.omg.CORBA.portable.IDLEntity {
public org.omg.CORBA.Object activate(ImplementationDef impl);
public void deactivate(org.omg.CORBA.Object obj, ImplementationDef impl);
}
The following code sample shows you how to create an Activator for the DBObjectImpl interface.
// Server.java
import com.inprise.vbroker.extension.*;
...
class DBActivator implements Activator {
private static int _count;
private com.inprise.vbroker.CORBA.BOA _boa;
public DBActivator(com.inprise.vbroker.CORBA.BOA boa) {
_boa = boa;
}
public org.omg.CORBA.Object activate(
com.inprise.vbroker.extension.ImplementationDef impl) {
System.out.println("Activator called " + ++_count + " times");
byte[] ref_data = ((ActivationImplDef) impl).id();
DBObjectImpl obj = new DBObjectImpl(new String(ref_data));
_boa.obj_is_ready(obj);
return obj;
}
public void deactivate(org.omg.CORBA.Object obj,
com.inprise.vbroker.extension.ImplementationDef impl) {
// nothing to do here...
}
}
...
Using the service activation approach
Service activation can be used when a server needs to provide implementations for a large number of objects (commonly thousands of objects, possibly millions) but only a small number of implementations need to be active at any specific time. The server can supply a single Activator which is notified whenever any of these subsidiary objects are needed. The server can also deactivate these objects when they are not in use.
For example, you might use service activation for a server that loads object implementations whose states are stored in a database. The Activator is responsible for loading all objects of a given type or logical distinction. When VisiBroker ORB requests are made on the references to these objects, the Activator is notified and creates a new implementation whose state is loaded from the database. When the Activator determines that the object should no longer be in memory and, if the object had been modified, it writes the object's state to the database and releases the implementation.
Figure 39
Deferring object activation using service activators
Assuming the objects that will make up the service have already been created, the following steps are required to implement a server that uses service activation:
1
2
3
Implement the Activator which creates the object implementations on demand. In the implementation, you derive an Activator interface from extension::Activator, overriding the activate and deactivate methods.
4
Example of deferred object activation for a service
The following sections describe the odb example for service activation which is located in the following VisiBroker directory:
<install_dir>/examples/vbroker/boa/odb
This directory contains the following files:
When make or nmake (on Windows) is invoked in the odb subdirectory, builds the following client and server programs:
Server, Creator, and Client.
The odb example shows how an arbitrary number of objects can be created by a single service. The service alone is registered with the BOA, instead of each individual object, with the reference data for each object stored as part of the IOR. This facilitates object-oriented database (OODB) integration, since you can store object keys as part of an object reference. When a client calls for an object that has not yet been created, the BOA calls a user-defined Activator. The application can then load the appropriate object from persistent storage.
In this example, an Activator is created that is responsible for activating and deactivating objects for the service named “DBService.” References to objects created by this Activator contain enough information for the VisiBroker ORB to relocate the Activator for the DBService service, and for the Activator to recreate these objects on demand.
The DBService service is responsible for objects that implement the DBObject interface. An interface (contained in odb.idl) is provided to enable manual creation of these objects.
odb.idl interface
The odb.idl interface enables manual creation of objects that implement the DBObject odb interface.
interface DBObject {
string get_name();
};
typedef sequence<DBObject> DBObjectSequence;
interface DB {
DBObject create_object(in string name);
};
The DBObject interface represents an object created by the DB interface, and can be treated as a service object.
DBObjectSequence is a sequence of DBObjects. The server uses this sequence to keep track of currently active objects.
The DB interface creates one or more DBObjects using the create_object operation. The objects created by the DB interface can be grouped together as a service.
Implementing a service activator
Normally, an object is activated when a server instantiates the classes implementing the object, and then calls obj_is_ready followed by impl_is_ready . To defer activation of objects, it is necessary to gain control of the activate method that the BOA invokes during object activation. You obtain this control by deriving a new class from com.inprise.vbroker.extension.Activator and overriding the activate method, using the overridden activate method to instantiate classes specific to the object.
In the odb example, the DBActivator class derives from com.inprise.vbroker.extension.Activator , and overrides the activate and deactivate methods. The DBObject is constructed in the activate method.
The following code sample is an example of overriding activate and deactivate.
// Server.java
class DBActivator implements Activator {
private static int _count;
private com.
inprise.vbroker.CORBA.BOA _boa;
public DBActivator(com.inprise.vbroker.CORBA.BOA boa) {
_boa = boa;
}
public org.omg.CORBA.Object activate(
com.inprise.vbroker.extension.ImplementationDef impl) {
System.out.printIn("Activator called " + ++_count + " times");
byte[] ref_data = ((ActivationImplDef) impl).id();
DBObjectImpl obj = new DBObjectImpl(new String(ref_data));
_boa.obj_is_ready(obj);
return obj;
}
public void deactivate(org.omg.CORBA.Object obj, ImplementationDef impl) {
// nothing to do here...
}
}
When the BOA receives a client request for an object under the responsibility of the Activator, the BOA invokes the activate method on the Activator. When calling this method, the BOA uniquely identifies the activated object implementation by passing the Activator an ImplementationDef parameter, from which the implementation can obtain the ReferenceData , the requested object's unique identifier.
The following code sample gives you an example of implementing a server activator.
public org.omg.CORBA.Object activate(ImplementationDef impl) {
System.out.println("Activator called " + ++_count + " times");
byte[] ref_data = ((ActivationImplDef) impl).id();
DBObjectImpl obj = new DBObjectImpl(new String(ref_data));
_boa.obj_is_ready(obj);
return obj;
}
Instantiating the service activator
The DBActivator service activator is responsible for all objects that belong to the DBService service. All requests for objects of the DBService service are directed through the DBActivator service activator. All objects activated by this service activator have references that inform the VisiBroker ORB that they belong to the DBService service.
The following code sample creates and registers the DBActivator service activator with an impl_is_ready call in the main server program.
public static void main(String[] args) {
org.omg.CORBA.ORB orb = ORB.init(args, null);
com.
inprise.vbroker.CORBA.BOA boa = ((com.inprise.vbroker.orb.ORB )orb).BOA_init();
DB db = new DBImpl("Database Manager");
boa.obj_is_ready(db);
boa.impl_is_ready("DBService", new DBActivator(boa));
}
Note
The call to impl_is ready is a variation on the usual call to impl_is_ready . It takes two arguments:
Using a service activator to activate an object
Whenever an object is constructed, obj_is_ready must be explicitly invoked in activate. There are two calls to obj_is_ready in the server program. One call occurs when the server creates a service object and returns an IOR to the creator program.
public DBObject create_object(String name) {
System.out.println("Creating: " + name);
DBObject dbObject = new DBObjectImpl(name);
_boa().obj_is_ready(dbObject, "DBService", name.getBytes());
return dbObject;
}
The second occurrence of obj_is_ready is in activate, and this needs to be explicitly called.