Using the VisiBroker Server Manager

This document provides the following information:

The VisiBroker Server Manager allows client applications to monitor and manage object servers, view and set properties at runtime for those servers, and view and invoke methods on server manager objects. The Server Manager uses elements known as containers which represent each major ORB component. A container can contain properties, operations, and even other containers.

Note: Do not confuse the Server Manager container with J2EE containers. The Server Manager container is simply a logical grouping of ORB components and selected runtime properties.

Getting Started with the Server Manager

This section details:

Enabling the server manager on a server

A VisiBroker server is not enabled to be managed by default. The command which starts the server must set the following property to manage the server:

vbroker.orb.enableServerManager=true

The property can be specified either through the command-line or through the server's properties file.

Obtaining a Server Manager reference

The first step in interacting with a Server Manager is to obtain a reference to a server's Server Manager. This reference points to the top level container. A client can obtain the reference using two ways:

  1. A server runner can choose to name the Server Manager using the property option vbroker.serverManager.name. For example, the command:

    prompt> Server -Dvbroker.serverManager.name=BigBadBoss

    registers the Server Manager name "BigBadBoss" to the Smart Agent namespace. From this point onward, the client can bind to that name and start invoking operations on the reference. This property can be set in the properties file as well. This method of locating a Server Manager can be used when the client does not have object references to any other objects implemented by the server, for example:

    Java:

    import com.inprise.vbroker.ServerManager.*;
    
    
    
    // returns reference to Server Manager "BigBadBoss" top container.
    
    Container topContainer = ContainerHelper.bind(orb,"BigBadBoss");
    
    

    C++:

    ServerManager::Container_var cont = ServerManager::Container::_bind("BigBadBoss");
  2. If the client has an object reference to some other object implemented by the server, then the client can perform _resolve_reference("ServerManager") on that object to obtain the ServerManager for the ORB corresponding to the object. The following code fragment obtains the server manager's top-level container from the Bank::AccountManager object.

    Java:

    import com.inprise.vbroker.ServerManager.*;
    
    
    
    // assume "manager" contains the reference to AccountManager 
    
    // object. No need to narrow since AccountManager is a
    
    // com.inprise.vbroker.CORBA.Object, however a narrow is still
    
    // required to convert returned Server Manager reference to
    
    // Container.
    
    Container topContainer = ContainerHelper.narrow(
    
    manager._resolve_reference("ServerManager"));
    
    

    C++:

    Bank::AccountManager_var manager = Bank::AccountManager::_bind("/bank_agent_poa", managerId);
    
    ServerManager::Container_var cont;
    
    CORBA::Object_var objCont = manager->_resolve_reference("ServerManager");

    The client code needs to include the servermgr_c.hh to use the Server Manager interfaces.

Working with Containers

Once a Client application has obtained the reference to the top level container, it can:

The top-level container does not support any properties or operations but just contains the ORB container. The ORB container in turn contains few ORB properties, a shutdown method, and other containers like RootPOA, Agent, OAD, and so forth.

See The Container Interface section for information on how to interact with containers. The examples section, below, shows Java and C++ interactions as well.

The Storage Interface

ServerManager provides an abstract notion of Storage that can be implemented in any fashion. Individual Containers may choose to store their properties in the different ways. Some Containers may choose to store their properties in a database, while others may choose to store them in files or in some other method. The Storage interface is defined in Server Manager IDL.

Every container uses the same methods to get and set storage, along with the ability to optionally set storage on all child containers of the parent. Similarly, each container uses the same methods to read and write its properties from the storage.

For information on the Storage Interface and its methods, see The Storage Interface section.

The Container Interface

Container class for Java

public interface Container extends

	com.inprise.vbroker.CORBA.Object

	com.inprise.vbroker.ServerManager.ContainerOperations

	org.omg.CORBA.portable.IDLEntity

When using this class in your code, you must include the following include statements:

import com.borland.vbroker.ServerManager.*; 

import com.borland.vbroker.ServerManager.ContainerPackage.*;

Container Methods for Java

A container can hold properties, operations, and other containers. Each major ORB component is represented as a container.

This section explains the Java methods that can be executed on the container interface. There are four categories:

Methods related to property manipulation and queries

public String[] list_all_properties();

Returns the names of all the properties in the contianer as a StringSequence.

public com.inprise.vbroker.ServerManager.ContainerPackage.Property[] 

      get_all_properties();

Returns the PropertySequence containing the names, values, and read-write status of all the properties in the container.

public com.inprise.vbroker.ServerManager.ContainerPackage.Property 

      get_property(String name) throws com.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid

Returns the value of the property name passed as an input parameter.

public void set_property(String name, org.omg.CORBA.Any 

      value) throws com.inprise.vbroker.ServerManager. ContainerPackage.NameInvalid,

      com.inprise.vbroker.ServerManager. ContainerPackage.ValueInvalid,

      com.inprise.vbroker.ServerManager. ContainerPackage.ValueNotSettable

Sets the value of the property name to the requested value.

public void persist_properties(boolean recurse) throws 

      com.inprise.vbroker.ServerManager.StorageException;

Causes the container to actually store its preoprties to the associated storage. If no storage is associated with the container, a StorageException will be raised. When it is invoked with the parameter recurse=true, the properties of the children containers are also stored into the storage. It is up to the container to decide if it has to store all the properties or only the changed properties.

public void restore_properties(boolean recurse) throws

      com.inprise.vbroker.ServerManager.StorageException;

Instructs the container to obtain its properties from the storage. A container knows exactly what properties is manages and it attempts to read those properties from the storage. The containers shipped with the ORB do not support restoring from the storage. You must create containers that support this feature yourself.

Methods related to operations

public String[] list_all_operations();

Returns the names of all the operations suppored in the container.

public com.inprise.vbroker.ServerManager.ContainerPackage.Operation[] 

      get_all_operations();

Returns all the operations along with the parameters and the type code of the parameters so that the operation can be invoked with the appropriate parameters.

public com.inprise.vbroker.ServerManager.ContainerPackage.Operation 

      get_operation(String name) throws com.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid;

Returns the parameter information of the operation specified by name which can be used to invoke the operation.

public org.omg.CORBA.Any do_operation(

      com.inprise.vbroker.ServerManager.ContainerPackage.Operation op) throws

      com.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid,

      com.inprise.vbroker.ServerManager.ContainerPackage.ValueInvalid,

      com.inprise.vbroker.ServerManager.ContainerPackage.OperationFailed;

Invokes the method in the operation and returns the result.

Methods related to children containers

public String[] list_all_containers();

Returns the names of all the children containers of the current container.

public com.inprise.vbroker.ServerManager.ContainerPackage.NamedContainer[] 

      get_all_containers();

Returns all the children containers.

public com.inprise.vbroker.ServerManager.ContainerPackage.NamedContainer

      get_container(String name) throws

      com.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid;

Returns the child container identified by the name parameter. If there is not any child container with this name, a NameInvalid exception is raised.

public void add_container(

      com.inprise.vbroker.ServerManager.ContainerPackage.NamedContainer container)

      throws com.inprise.vbroker.ServerManager.ContainerPackage.NameAlreadyPresent,

      com.inprise.vbroker.ServerManager.ContainerPackage.ValueInvalid;

Adds the container as a child container of this container.

public void set_container(String name, com.inprise.vbroker.ServerManager.Container value) throws

      com.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid,

      com.inprise.vbroker.ServerManager.ContainerPackage.ValueInvalid,

      com.inprise.vbroker.ServerManager.ContainerPackage.ValueNotSettable;

Modifies the child container identified by the name parameter to one in the value parameter.

Methods related to storage

void set_storage(in com.inprise.vbroker.ServerManager.Storage s, in boolean recurse);

Sets the storage of this container. If recurse=true, it also sets the storage for all its children as well.

com.inprise.vbroker.ServerManager.Storage get_storage();

Returns the current storage of the container.

Container Methods for C++

A container can hold properties, operations, and other containers. Each major ORB component is represented as a container. The top-level container corresponds to the ORB itself and includes a few ORB properties, the shutdown method, and a few other commonly used containers like RootPOA and Agent.

This section explains the C++ methods that can be executed on the container interface. There are four categories:

Methods related to property manipulation and queries

CORBA::StringSequence list_all_properties();

Returns the names of all the properties in the contianer as a StringSequence.

PropertySequence get_all_properties();

Returns the PropertySequence containing the names, values, and read-write status of all the properties in the container.

Property get_property(in string name raises(NameInvalid);

Returns the value of the property name passed as an input parameter.

void add_property(in string name, in any value) raises(NameInvalid, ValueInvalid, ValueNotSettable);

Sets the value of the property name to the requested value.

void persist_properties(in boolean recurse) raises(StorageException);

Causes the container to actually store its properties to the associated storage. If no storage is associated with the container, a StorageException will be raised. When it is invoked with the parameter recurse=true, the properties of the children containers are also stored into the storage. It is up to the container to decide if it has to store all the properties or only the changed properties.

void restore_properties(in boolean recurse) raises(StorageException);

Instructs the container to obtain its properties from the storage. A container knows exactly what properties is manages and it attempts to read those properties from the storage. The containers shipped with the ORB do not support restoring from the storage. You must create containers that support this feature yourself.

Methods related to operations

::CORBA::StringSeqence list_all_operations();

Returns the names of all the operations suppored in the container.

OperationSequence get_all_operations();

Returns all the operations along with the parameters and the type code of the parameters so that the operation can be invoked with the appropriate parameters.

Operation get_operation(in string name) raises(NameInvalid);

Returns the parameter information of the operation specified by name which can be used to invoke the operation.

any do_operation(in Operation op) raises(NameInvalid, ValueInvalid, OperationFailed);

Invokes the method in the operation and returns the result.

Methods related to children containers

::CORBA::StringSequence list_all_containers();

Returns the names of all the children containers of the current container.

NamedContainerSequence get_all_containers();

Returns all the children containers.

NamedContainer get_container(in string name) raises(NameInvalid);

Returns the child container identified by the name parameter. If there is not any child container with this name, a NameInvalid exception is raised.

void add_container(in NamedContainer container) raises(NameAlreadyPresent, ValueInvalid);

Adds the container as a child container of this container.

void set_container(in string name, in Container value)  raises(NameInvalid, ValueInvalid, ValueNotSettable);

Modifies the child container identified by the name parameter to one in the value parameter.

Methods related to storage

void set_storage(in Storage s, in boolean recurse);

Sets the storage of this container. If recurse=true, it also sets the storage for all its children as well.

Storage get_storage();

Returns the current storage of the container.

The Storage Interface

The Server Manager provides an abstract notion of storage that can be implemented in any fashion. Individual containers may choose to store their properties in databases, flat files, or some other means. The storage implementation included with the VisiBroker ORB uses a flat-file-based approach.

Storage Interface Class and Methods for Java

Storage Class

public interface Storage extends

	com.inprise.vbroker.CORBA.Object

	com.inprise.vbroker.ServerManager.StorageOperations,

	org.omg.CORBA.portable.IDLEntity

The following include statements must appear in your code when using the Storage interface:

import com.borland.vbroker.ServerManager.*; 

import com.borland.vbroker.ServerManager.ContainerPackage.*;

Storage Interface Methods

public void open() throws

      com.inprise.vbroker.ServerManager.StorageException;

Opens the storage and makes it ready for reading and writing the properties. For the database-based implementation, logging into the database is performed in this method.

public void close() throws

      com.inprise.vbroker.ServerManager.StorageException;

Closes the storage. This method also updates the storage with any properties that have been changed since the last Container::persist_properties call. In database implementations, this method closes the database connection.

public com.inprise.vbroker.ServerManager.ContainerPackage.Property[]

      read_properties() throws

      com.inprise.vbroker.ServerManager.StorageException;

Reads all the properties from the storage.

public com.inprise.vbroker.ServerManager.ContainerPackage.Property read_property(String 

        propertyName) throwscom.inprise.vbroker.ServerManager.ContainerPackage.NameInvalid, 

        com.inprise.vbroker.ServerManager.StorageException;

Returns the property value for propertyName read from the storage.

public void write_properties(com.inprise.vbroker.ServerManager.ContainerPackage. 

      Property[] props) throws com.inprise.vbroker.ServerManager.StorageException; 

Saves the property sequence into the storage.

public void write_property(com.inprise.vbroker.ServerManager.ContainerPackage.Property 

      prop) throws com.inprise.vbroker.ServerManager.StorageException;

Saves the single property into the storage.

Storage Interface Methods for C++

void open() raises (StorageException);

Opens the storage and makes it ready for reading and writing the properties. For the database-based implementation, logging into the database is performed in this method.

void close() raises (StorageException);

Closes the storage. This method also updates the storage with any properties that have been changed since the last Container::persist_properties call. In database implementations, this method closes the database connection.

Container::PropertySequence read_properties() raises(StorageException);

Reads all the properties from the storage.

Container::Property read_property(in string propertyName) raises(StorageException, Container::NameInvalid);

Returns the property value for propertyName read from the storage.

void write_properties(in Container::PropertySequence p) raises(StorageException);

Saves the property sequence into the storage.

void write_property(in Container::Property p) raises(StorageException);

Saves the single property into the storage.

Limiting access to the Server Manager

A client that obtains the server manager can control the entire ORB and hence security is paramount. There are three properties that can limit a user's access to the Server Manager functionality:

Property Default Value Description
vbroker.orb.enableServerManager false Setting this property to True enables the Server Manager.
vbroker.serverManager.enableOperations true Controls the permission to invoke operations in the containers. If set to false, the client will not be able to invoke do_operation on any container.
vbroker.serverManager.enableSetProperty true Controls the setting of properties from the client. If set to false, clients cannot modify any of the container properties.

Server Manager IDL

Server Manager IDL is as shown below:


module ServerManager { 

interface Storage; 



exception StorageException { 

    string reason; 

}; 



interface Container 

{ 

    enum RWStatus { 

        READWRITE_ALL, 

        READONLY_IN_SESSION, 

        READONLY_ALL 

    }; 



    struct Property { 

        string name; 

        any value; 

        RWStatus rw_status; 

    }; 

    typedef sequence<Property> PropertySequence; 



    struct NamedContainer { 

        string name; 

        Container value; 

        boolean is_replaceable; 

    }; 

    typedef sequence<NamedContainer> NamedContainerSequence; 



    struct Parameter { 

        string name; 

        any value; 

    }; 

    typedef sequence<Parameter> ParameterSequence; 



    struct Operation { 

        string name; 

        ParameterSequence params; 

        ::CORBA::TypeCode result; 

    }; 

    typedef sequence<Operation> OperationSequence; 



    struct VersionInfo { 

        unsigned long major; 

        unsigned long minor; 

    }; 



    exception NameInvalid{}; 

    exception NameAlreadyPresent{}; 

    exception ValueInvalid{}; 

    exception ValueNotSettable{}; 

    exception OperationFailed{ 

        string real_exception_reason; 

    }; 



    ::CORBA::StringSequence list_all_properties(); 

    PropertySequence get_all_properties(); 

    Property get_property(in string name) raises (NameInvalid); 

    void add_property(in Property prop) 

    raises(NameAlreadyPresent, NameInvalid, ValueInvalid); 

    void set_property(in string name, in any value) 

    raises(NameInvalid, ValueInvalid, ValueNotSettable); 



    ::CORBA::StringSequence get_value_chain(in string propertyName) raises (NameInvalid); 

    void persist_properties(in boolean recurse) raises (StorageException); 

    void restore_properties(in boolean recurse) raises (StorageException); 



    ::CORBA::StringSequence list_all_operations(); 

    OperationSequence get_all_operations(); 

    Operation get_operation(in string name) 

    raises (NameInvalid); 

    any do_operation(in Operation op) 

    raises(NameInvalid, ValueInvalid, OperationFailed); 



    ::CORBA::StringSequence list_all_containers(); 

    NamedContainerSequence get_all_containers(); 

    NamedContainer get_container(in string name) 

    raises (NameInvalid); 

    void add_container(in NamedContainer container) 

    raises(NameAlreadyPresent, ValueInvalid); 

    void set_container(in string name, in Container value) 

    raises(NameInvalid, ValueInvalid, ValueNotSettable); 

  



    void set_storage(in Storage s, in boolean recurse); 

    Storage get_storage(); 



    readonly attribute VersionInfo version; 

}; 



interface Storage 

{ 

    void open() raises (StorageException); 

    void close() raises (StorageException); 

    Container::PropertySequence read_properties() raises 

    (StorageException); 

    Container::Property read_property(in string propertyName) 

    raises (StorageException, Container::NameInvalid); 

    void write_properties(in Container::PropertySequence p) raises 

    (StorageException); 

    void write_property(in Container::Property p) raises (StorageException); 

}; 



}; 

Examples

The following examples demonstrate how to:

  1. Obtain a reference to the top-level container.
  2. Get all containers and their properties recursively.
  3. Getting, setting, and saving properties on different containers.
  4. Invoke the shutdown() method on the ORB container.

This example uses the bank_agent server. This server should be started by passing the property storage file. Initially the property file contains the properties to enable the server manager and set its name. The file is used by the server manager to update the properties if the user changes them. The properties to enable the server manager and set its name can be passed as command-line options, but the property file is required if any of the properties are to be modified and saved during the session.

Initially, the property file contains the following:


# server properties

vbroker.orb.enableServerManager=true

vbroker.serverManager.name=BigBadBoss

The Server is started from the command-line:


prompt> Server -ORBpropStorage prop.txt

Obtaining the reference to the top-level container

This example will use the second, or "bind" method above, since the Server Manager has been started with a name.

Java:

Container topContainer = ContainerHelper.bind(orb,"BigBadBoss");

C++:


ServerManager::Container_var cont = ServerManager::Container::_bind("BigBadBoss");

Getting all the containers and their properties

The following example shows how get_all_properties, get_all_operations, and get_all_containers can be used to query all the properties and operations of all the containers below the current container recursively.

Java:

public void displayContainer(NamedContainer cont, boolean top) {



    // Get All Containers

    NamedContainer[] nc = cont.value.get_all_containers();



    // Get All Properties for the current container

    Property[] props=cont.value.get_all_properties();



    // Get All Operations for the current container

    Operation[] ops=cont.value.get_all_operations();



    ....

    // Now print all properties and operations and recurse

    // through all containers



 }

C++:


void SrvrmgrUtil::displayContainer(char * name, ServerManager::Container_ptr cont) {

  try {

        ServerManager::Container::PropertySequence * props = cont->get_all_properties();

        for (int i =0; i < props->length() ; i++) {

                printProperty((*props)[i]);

        }

        ServerManager::Container::OperationSequence * ops = cont->get_all_operations();

        for (int j = 0; j < ops->length(); j++)

                printOperation((*ops)[j]);

        }

        catch (ServerManager::Container::NameInvalid& ne) {

        cerr << ne <<endl; 

        } catch (ServerManager::Container::ValueInvalid & ve) {

                cerr << ve <<endl;

        } // Pass the remaining exceptions to the main function

        ServerManager::Container::NamedContainerSequence* nc = cont->get_all_containers();

        for (int j =0 ; j < nc->length(); j++) {

                displayContainer((*nc)[j].name, (*nc)[j].value);

        }

}

Getting and Setting properties and saving them into the file.

The following code fragment shows how to query a property of a container. If the container is not the top-level container, it needs to be reached first by traversing through all its parents from the top container. The get and set methods can be called only on the container which owns the property. Note that properties with RW_STATUS values of READONLY_ALL are not settable.

Java:

public void getSetProperties(NamedContainer topCont) throws Exception {



      // Obtain the ORB container from top level container.

      Container orbCont=topCont.value.get_container("ORB").value;



      // Obtain the "iiop_tp" SCM container. This container is

      // contained as follows:

      // topCont->ORB->ServerEngines->iiop_tp->iiop_tp (the first 

      // iiop_tp is the ServerEngine name)'



      Container iiopCont=orbCont.get_container(

                           "ServerEngines").value.get_container(

                           "iiop_tp").value.get_container(

                           "iiop_tp").value;



      // Obtain the "bank_agent_poa" container. This container is 

      // contained as follows:

      // topCont->ORB->RootPOA->Children->bank_agent_poa

      Container poaCont=orbCont.get_container(

                           "RootPOA").value.get_container(

                           "Children").value.get_container(

                           "bank_agent_poa").value;



      // get the process Id property from ORB container

      Property procIdProp=orbCont.get_property("vbroker.orb.procId");

 

      // get the listener port property from iiop_tp container

      Property portProp=iiopCont.get_property(

                       "vbroker.se.iiop_tp.scm.iiop_tp.listener.port");



      // get the upTime property from bank_agent_poa container

      Property upTimeProp=poaCont.get_property("upTime");



      ....



      // let the user modify listener port value

	org.omg.CORBA.Any portAny=orb.create_any();

	   portAny.insert_long(newPort);

	   iiopCont.set_property(

"vbroker.se.iiop_tp.scm.iiop_tp.listener.port",portAny);



	  ....



	 // save the updated property to file



iiopCont.persist_properties(true);

}



C++:


// querying for properties

ServerManager::Container::NamedContainer_var orbCont = cont->get_container("ORB");

ServerManager::Container::NamedContainer_var sesCont = 

                orbCont->value->get_container("ServerEngines");

ServerManager::Container::NamedContainer_var seCont = 

                sesCont->value->get_container("iiop_tp");

ServerManager::Container::NamedContainer_var scmCont = 

                seCont->value->get_container("iiop_tp");

SrvrmgrUtil::displayProperty("vbroker.se.iiop_tp.scm.iiop_tp.dispatcher.inUseThreads",

                scmCont->value);



CORBA::Any_var a = new CORBA::Any;

a <<= (CORBA::ULong) 34001UL;

scmCont->value->set_property("vbroker.se.iiop_tp.scm.iiop_tp.listener.port", a);

scmCont->value->persist_properties(true);

Invoking an operation in a Container

The ORB container supports the operation shutdown. The operation can be obtained by calling get_operation on the container.

Java:

public void invokeShutdown(NamedContainer topCont) throws Exception {



    Container orbCont=topCont.value.get_container("ORB").value;



    System.out.println("Executing ShutDown ...");



    // Prepare parameter (boolean wait_for_completion)

    org.omg.CORBA.Any any=orb.create_any();

    any.insert_boolean(false);

    Parameter[] params=new Parameter[1];



    // Prepare result (void)

    params[0]=new Parameter("waitForCompletion",any);

    org.omg.CORBA.TypeCode result=orb.get_primitive_tc(

                      org.omg.CORBA.TCKind.tk_void);



    // Prepare operation

    Operation op=new Operation("shutdown",params, result);



    // Invoke operation

    orbCont.do_operation(op);

}

C++:


void SrvrmgrUtil::invokeShutdown(ServerManager::Container_ptr orbCont)

{

        ServerManager::Container::Operation_var shutOp = orbCont->get_operation("shutdown");

        shutOp->params[0].value <<= CORBA::Any::from_boolean(0UL);

        orbCont->do_operation(shutOp.in());

}

The operation returned by the get_operation call has the default parameters. If the default values of the parameters are not the intended ones, these values should be modified before calling the do_operation method.

Custom Containers

It is possible for a user application to define containers and add them to the Server Manager. The container manages two properties and defines one operation. It also uses its own storage for storing the properties. The two properties are:

Property Description
manager.lockAllAccounts This property has a read-write status of READWRITE_ALL, so it can be modified and takes effect while the server is running. The purpose of this property is to make AccountManager unavailable for client applications. The initial value of this property is read by the server on startup and saved to the same file when server shuts down/restarts.
manager.numAccounts This property has a read-write status of READONLY_ALL, so it can only be read. The purpose of this property is to provide the number of Accounts in the AccountManager. The value of this property is not written to the storage.

The operation is:

OperationDescription
shutdown Shuts down the server without starting it again. Before shutdown, the manager.lockAllAccounts property is written (persisted) to the property file.

A complete example can be seen in CustomContainer directory within the ServerManager examples directory. For brevity, the example is not discussed here, however, the main steps in writing custom containers is follows:

  1. Implement the Container interface defined in Serve Manager IDL.
  2. Instantiate the servant that implements the Container interface and activate it on a POA.
  3. Obtain the reference to Server Manager top level container. Add the custom container to the Container hierarchy.

The server then can be started with the Server Manager enabled and a client can interact with the custom container.

If you want your application to implement its own storage, it has to implement the Storage interface defined in Server Manager IDL. The basic steps are same as implementing custom containers