Externalizing a reference to an object for which object wrappers have been installed, using the VisiBroker ORB Object's 
object_to_string method, will not propagate those wrappers to the recipient of the stringified reference if the recipient is a different process.
 
      
      VisiBroker offers two kinds of object wrappers: typed and 
untyped. You can mix the use of both of these object wrappers within a single application. For information on typed wrappers, see 
“Typed object wrappers”. For information on untyped wrappers, see 
“Untyped object wrappers”. The following table summarizes the important distinctions between these two kinds of object wrappers.
 
      
      
      Whenever you plan to use typed or untyped object wrappers, you must ensure that you use the -obj_wrapper option with the 
idl2cpp compiler when you generate the code for your applications. This will result in the generation of an Object wrapper base class for each of your interfaces.
 
      
      
      
      
      
      
      
      
      
      The following figure shows how an untyped object wrapper's pre_method is invoked before the client stub method and how the 
post_method is invoked afterward. It also shows the calling sequence on the server-side with respect to the object implementation.
 
      
      
      
      
      When a client invokes a method on a bound object, each untyped object wrapper pre_method will receive control before the client's stub routine is invoked. When a server receives an operation request, each untyped object wrapper 
pre_method will be invoked before the object implementation receives control. In both cases, the first 
pre_method to receive control will be the one belonging to the object wrapper that was 
registered first.
 
      
      When a server's object implementation completes its processing, each post_method will be invoked before the reply is sent to the client. When a client receives a reply to an operation request, each 
post_method will be invoked before control is returned to the client. In both cases, the first 
post_method to receive control will be the one belonging to the object wrapper that was 
registered last.
 
      
      
      
      
      
      
      
      
      
      
      The TimeWrap.h file, part of the 
ObjectWrappers sample applications, illustrates how to define an untyped object wrapper factory that is derived from the 
VISObjectWrapper::UntypedObjectWrapperFactory.
 
      Your factory's create method will be invoked to create an untyped object wrapper whenever a client binds to an object or a server invokes a method on an object implementation. The 
create method receives the target object, which allows you to design your factory to not create an untyped object wrapper for those object types you wish to ignore. It also receives an enum specifying whether the object wrapper created is for the server side object implementation or the client side object.
 
      The following code sample shows the TimingObjectWrapperFactory, which is used to create an untyped object wrapper that displays timing information for method calls. Notice the addition of the 
key parameter to the 
TimingObjectWrapperFactory constructor. This parameter is also used by the service initializer to identify the wrapper.
 
      class TimingObjectWrapperFactory
  : public VISObjectWrapper::UntypedObjectWrapperFactory
{
   public:      
TimingObjectWrapperFactory(VISObjectWrapper::Location loc,
            const char* key)
         : VISObjectWrapper::UntypedObjectWrapperFactory(loc),
            _key(key) {}
      // ObjectWrapperFactory operations
      VISObjectWrapper::UntypedObjectWrapper_ptr 
create(
               CORBA::Object_ptr target,
               VISObjectWrapper::Location loc) {
         if (_owrap == NULL) {
               _owrap = 
new TimingObjectWrapper(_key);
         }         
return VISObjectWrapper::UntypedObjectWrapper::_duplicate(_owrap);
      }
   private:
      CORBA::String_var _key;
      VISObjectWrapper::UntypedObjectWrapper_var _owrap;
};
 
      
      The following code sample shows the implementation of the TimingObjectWrapper, also defined in the 
TimeWrap.h file. Your untyped wrapper must be derived from the 
VISObjectWrapper::UntypedObjectWrapper class, and you may provide an implementation for both the 
pre_method or 
post_method methods in your untyped object wrapper.
 
      Once your factory has been installed, either automatically by the factory's constructor or manually by invoking the VISObjectWrapper::ChainUntypedObjectWrapper::add method. An untyped object wrapper object will be created automatically whenever your client binds to an object or when your server invokes a method on an object implementation.
 
      The pre_method shown in the following code sample invokes the 
TimerBegin method, defined in 
TimeWrap.C, which uses the 
Closure object to save the current time. Similarly, the 
post_method invokes the 
TimerDelta method to determine how much time has elapsed since the 
pre_method was called and print the elapsed time.
 
      
      
      Both the pre_method and 
post_method receive the parameters shown in the following table.
 
      
        
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  | post_method only parameter used to inform the user of any exceptions that might have occurred during the previous steps of the method invocation. | 
      
      
      
      
      The following code sample shows a portion of the sample file UntypedClient.C which shows the creation, with automatic registration, of two untyped object wrapper factories for a client. The factories are created after the VisiBroker ORB has been initialized, but before the client binds to any objects.
 
      int main(int argc, char* const* argv) {
   try {
         // Initialize the ORB.
         CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
         // Install untyped object wrappers         
TimingObjectWrapperFactory timingfact(VISObjectWrapper::Client,
                   "timeclient");
         TraceObjectWrapperFactory tracingfact(VISObjectWrapper::Client,
                  "traceclient");
         // Now locate an account manager.
   . . .]
 
      The following code sample illustrates the sample file UntypedServer.C, which shows the creation and registration of untyped object wrapper factories for a server. The factories are created after the VisiBroker ORB is initialized, but before any object implementations are created.
 
      
      
      The VISObjectWrapper::ChainUntypedObjectWrapperFactory class 
remove method can be used to remove an untyped object wrapper factory from a client or server application. You must specify a location when removing a factory. This means that if you have added a factory with a location of 
VISObjectWrapper::Both, you can selectively remove it from the 
Client location, the 
Server location, or 
Both.
 
      
      
      
      
      
      
      
      
      
      
      On the client side, the first object wrapper registered is client_wrapper_1, so its methods will be the first to receive control. After performing its processing, the 
client_wrapper_1 method may pass control to the next object's method in the chain or it may return control to the client.
 
      On the server side, the first object wrapper registered is server_wrapper_1, so its methods will be the first to receive control. After performing its processing, the 
server_wrapper_1 method may pass control to the next object's method in the chain or it may return control to the servant.
 
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      You derive typed object wrappers from the <interface_name>ObjectWrapper class that is generated by the 
idl2cpp compiler.
 
      
      Notice that this class is derived from the AccountObjectWrapper interface and provides a simple caching implementation of the 
balance method, which provides these processing steps:
 
      
        
          
            | 
                1	
               | Check the _inited flag to see if this method has been invoked before. | 
        
       
      
        
          
            | 
                2	
               | If this is the first invocation, the balance method on the next object in the chain is invoked and the result is saved to _balance , the _inited  flag is set to true , and the value is returned. | 
        
       
      
      class CachingAccountObjectWrapper : public Bank::
AccountObjectWrapper {
   public:
      CachingAccountObjectWrapper() : _inited((CORBA::Boolean)0) {}
      CORBA::Float 
balance() {
         cout << "+ CachingAccountObjectWrapper: Before Calling Balance" << endl; 
if (! _inited) {
            _balance = Bank::AccountObjectWrapper::balance();
            _inited = 1;
         } else {
            cout << "+ CachingAccountObjectWrapper: Returning Cached Value" <<
         endl;
         }
         cout << "+ CachingAccountObjectWrapper: After Calling Balance" << endl;
         return _balance;
      }
   . . .
};
 
      
      A typed object wrapper is registered on the client-side by invoking the <interface_name>::add method that is generated for the class by the 
idl2cpp compiler. Client-side object wrappers must be registered after the 
ORB_init method has been called, but before any objects are bound. The following code sample shows a portion of the 
TypedClient.java file that creates and registers a typed object wrapper.
 
      . . .
int main(int argc, char* const* argv) {
   try {
      // Initialize the ORB.
 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
      // Install Typed Object Wrappers for Account. 
Bank::AccountObjectWrapper::add(orb,
            CachingAccountObjectWrapper::factory,
             VISObjectWrapper::Client);
      // Get the Manager ID.
      PortableServer::ObjectId_var managerId =
            PortableServer::string_to_ObjectId("BankManager");
      // Locate an Account Manager.
      Bank::AccountManager_var manager =
            Bank::AccountManager::_bind("/bank_ow_poa", managerId);
. . .
 
      The VisiBroker ORB keeps track of any object wrappers that have been registered for it on the client side. When a client invokes the _bind method to bind to an object of that type, the necessary object wrappers will be created. If a client binds to more than one instance of a particular class of object, each instance will have its own set of wrappers.
 
      
      As with a client application, a typed object wrapper is registered on the server side by invoking the <interface_name>::add method. Server side, typed object wrappers must be registered after the 
ORB_init method has been called, but before an object implementation services a request. The following code sample shows a portion of the 
TypedServer.C file that installs a typed object wrapper.
 
      
      
      
      The <interface_name>ObjectWrapper::remove method that is generated for a class by the 
idl2cpp compiler allows you to remove a typed object wrapper from a client or server application. You must specify a location when removing a factory. This means that if you have added a factory with a location of 
VISObjectWrapper::Both, you can selectively remove it from the 
Client location, the 
Server location, or 
Both.
 
      
      
      
      If you choose to use both typed and untyped object wrappers in your application, all pre_method methods defined for the untyped wrappers will be invoked prior to any typed object wrapper methods defined for an object. Upon return, all typed object wrapper methods defined for the object will be invoked prior to any 
post_method methods defined for the untyped wrappers.
 
      The sample applications Client.C and 
Server.C make use of a sophisticated design that allows you to use command-line properties to specify which, if any, typed and untyped object wrappers are to be used.
 
      
      
      
      
      The typed wrappers are created in the BankInit::update initializer, defined in 
objectWrappers/BankWrap.C. This initializer will be invoked when the 
ORB_init method is invoked and will handle the installation of various typed object wrappers, based on the command-line properties you specify.
 
      The following code sample shows how the initializer uses a set of PropStruct objects to track the command-line options that have been specified and then add or remove 
AccountObjectWrapper objects for the appropriate locations.
 
      . . .
static const CORBA::ULong kNumTypedAccountProps = 2;
static PropStruct TypedAccountProps[kNumTypedAccountProps] =
{ { "
BANKaccountCacheClnt", CachingAccountObjectWrapper::factory,
      VISObjectWrapper::Client },
   { "
BANKaccountCacheSrvr", CachingAccountObjectWrapper::factory,
      VISObjectWrapper::Server }
};
static const CORBA::ULong kNumTypedAccountManagerProps = 4;
static PropStruct 
TypedAccountManagerProps[kNumTypedAccountManagerProps] =
{ { "
BANKmanagerCacheClnt", CachingAccountManagerObjectWrapper::factory,
      VISObjectWrapper::Client },
{ "
BANKmanagerSecurityClnt", SecureAccountManagerObjectWrapper::factory,
      VISObjectWrapper::Client },
{ "
BANKmanagerCacheSrvr", CachingAccountManagerObjectWrapper::factory,
      VISObjectWrapper::Server },
{ "
BANKmanagerSecuritySrvr", SecureAccountManagerObjectWrapper::factory,
      VISObjectWrapper::Server },
};
void 
BankInit::update(int& argc, char* const* argv) {
   if (argc > 0) {
      init(argc, argv, "-BANK");
      CORBA::ULong i;
      for (i=0; i < kNumTypedAccountProps; i++) {
         CORBA::String_var arg(getArgValue(
TypedAccountProps[i].propname));
         if (arg && strlen(arg) > 0) {
            if (atoi((char*) arg)) {               
Bank::AccountObjectWrapper::add(_orb,
                      TypedAccountProps[i].fact,
                 TypedAccountProps[i].loc);
            } else {               
Bank::AccountObjectWrapper::remove(_orb,
                      TypedAccountProps[i]Fact,
                     TypedAccountProps[i].loc);
            }
         }
      }
      for (i=0; i < kNumTypedAccountManagerProps; i++) {
            CORBA::String_var arg(
               getArgValue(
TypedAccountManagerProps[i].propname));
            if (arg && strlen(arg) > 0) {
                  if (atoi((char*) arg)) {                        
Bank::AccountManagerObjectWrapper::add(_orb,
                              TypedAccountManagerProps[i]Fact,
                              TypedAccountManagerProps[i].loc);
                  }    else {                        
Bank::AccountManagerObjectWrapper::remove(_orb,
                             TypedAccountManagerProps[i]Fact,
                            TypedAccountManagerProps[i].loc);
                  }
            }
      }
   }
}
 
      
      
      
      
      The untyped wrappers are created and registered in the TraceWrapInit::update and
TimingWrapInit::update methods, defined in 
BankWrappers/TraceWrap.C and 
TimeWrap.C. These initializers will be invoked when the 
ORB_init method is invoked and will handle the installation of various untyped object wrappers.
 
      The following code sample shows a portion of the TraceWrap.C file, which will install the appropriate untyped object wrapper factories, based on the command-line properties you specify.
 
      TraceWrapInit::update(int& argc, char* const* argv) {
   if (argc > 0) {
      init(argc, argv, "-TRACEWRAP");      
VISObjectWrapper::Location loc;
      const char* propname;
      LIST(VISObjectWrapper::UntypedObjectWrapperFactory_ptr) *list;
      for (CORBA::ULong i=0; i < 3; i++) {
         switch (i) {
            case 0:               
loc = VISObjectWrapper::Client;
               propname = "TRACEWRAPclient";
               list = &_clientfacts;
               break;
            case 1:               
loc = VISObjectWrapper::Server;
               propname = "TRACEWRAPserver";
               list = &_serverfacts;
               break;
            case 2:               
loc = VISObjectWrapper::Both;
               propname = "TRACEWRAPboth";
               list = &_bothfacts;
               break;
         }         
CORBA::String_var getArgValue(property_value(propname));
         if (arg && strlen(arg) > 0) {            
int numNew = atoi((char*) arg);
            char key_buf[256];
            for (CORBA::ULong j=0; j < numNew; j++) {
               sprintf(key_buf, "%s-%d", propname, list->size());               
list->add(new TraceObjectWrapperFactory(loc,
                     (const char*) key_buf));
            }
         }
      }
   }
}