Smart Proxies

Smart Proxies (or Smart Stubs) are basically user-defined proxy classes.

By default, the IDL compiler generates proxy classes for IDL interfaces. The proxy is an exact image of the target object on whom the invocations are to be made by the client, i.e. it has the same methods as the targeting interface. A proxy packadges the request which gets marshalled and sent to the target object.


Table of Contents


Examples

The user may wish to manually change the proxy code for the following reasons:


Design Issues

Design Needs and discussion points

A ProxyFactory (either default or user-defined) is needed which will create the stubs (either default or smart). This factory should be able to create different kinds of proxies.

The unchecked_narrow method needs to return the appropriate stub.

Collocated stubs need to be handled too. This means that smart proxies need to be generated for collocated object references too.

An existing function for creating stubs has to replaced by a class which will handle all cases viz. default stubs, smart stubs (proxies), collcated stubs.

Design Overview

At a glance:

Classses to be generated by TAO_IDL in addition to the Default Stub:

Classes to be defined by the user:


Detailed Example

//------------------------ Generated by TAO_IDL------------------------

class TAO_Proxy_Factory_Adapter
{
 // DESCRIPTION:
 // Behaves like a singleton and contains the
 // factory object which is used to create the
 // default/smart Proxys.
public:

 friend class ACE_Singleton;

 // Register the factory with the Adaptor.
 register_proxy (TAO_Default_Proxy_Factory *df)
 {
   Perform Double-Checked Locking Optimisation...

   // If there is a factory already existing, replace it.
   this->unregister_proxy_factory ();
   this->proxy_factory_ = df;
   this->delete_proxy_factory_ = 0;
 }

 // Remove the factory.
 unregister_proxy_factory (void)
 {
   Perform Locking to ensure exclusive access.
    if (this->delete_proxy_factory_ == 0 && this->proxy_factory_ != 0)
    {
      // Its necessary to set  to 1 to make sure that it
      // doesnt get into an infinite loop in  as it is 
      // invoked in the destructor of the class too.
      this->delete_proxy_factory_ = 1;
      delete this->proxy_factory_;
      this->proxy_factory_ = 0;
    }
 }

 // Delegation of the Proxy creation to the factory
 interface_ptr create_proxy (void)
 {
   Verify that an  is available else make one.

   return this->factory_->create_proxy ();
 }

protected:
 
 TAO_Test_Default_Proxy_Factory *proxy_factory_;
 int delete_proxy_factory_;
 ACE_Recursive_Thread_Mutex lock_;

};

// This class will also be generated by TAO_IDL.
class TAO_Default_Proxy_Factory
{
 // DESCRIPTION:
 // This class is the parent for the different Proxy factories. The
 // Proxy could either be collocated or remote and hence here only
 // the Proxy pointer is returned which will be created on invocation of
 // .

public:
 TAO_Default_Proxy_Factory (int register_proxy_factory);
 {
   // Unless told dont register. By default registration is done.
   // This comes in handy while creating the TAO_Proxy_Factory_Adapter
   // instance since we want either the user to set the factory. Only
   // if that doesnt happen will the TAO_Default_Proxy_Factory be set
   // to the factory delegated by the Adapter and that is done using
   // the Lazy Evaluation Principle when the first call to 
   // is done.

   if (register_proxy_factory)
    {
      TAO_PROXY_FACTORY_ADAPTER::instance ()->register_proxy_factory (this);
    }
 }

 ~TAO_Default_Proxy_Factory (void)
 {
 }

 // By default the proxy is simply returned.
 interface_ptr create_proxy (interface_ptr proxy)
 {
   return proxy;
 }

};

// This class will be generated by the TAO_IDL.
class TAO_Smart_Proxy_Base : public virtual DefaultProxyInterface
{
 // DESCRIPTION:
 // This class is the class from which the user will inherit
 // and simply override the methods he requires. This extra
 // level of indirection is necessary to be able to provide
 // the smartProxy interface for even collocated Proxies.
public:

 // The delegation to which underlying proxy is decided here.
 TAO_Smart_Proxy_Base (interface_ptr proxy)
  : base_proxy_ (proxy)

 // Interface operations...
 int method ()
  {
    this->proxy_->method ();
  }
 ...
 // @@ How are exceptions handled?
 // This not an issue really because the actual method call is simply
 // to the application level which is catch it as the exception is
 // propogated upwards from the proxy level. 

protected:
 // This var member denotes the kind of proxy used:
 // collacated-thru_poa, collocated-direct, or remote.
 // This is decided by the collocated strategy used along
 // with the smart Proxies. Note: the collocated Proxies
 // themselves are smart proxies. The proxy pointer passed
 // thru the constructor will be assigned to . The
 // pointer will actually point to the smart proxy in case
 // of smart proxies or else to the default proxy.
  DefaultProxyInterface_var base_proxy_;

};

// ----------------- User Implemenatation Begins here----------------

// Note: This has to be implemented by the user
class SmartFactory : public TAO_Default_Proxy_Factory
{
 // DESCRIPTION:
 // An object of this class has to be defined by the user
 // which will cause it to be registered with the
 // ProxyFactoryAdaptor.
public:

 Smartinterface_ptr create_proxy (interface_ptr proxy)
 {
   return (!CORBA::is_nil (proxy) ? new SmartProxy (proxy) : proxy);
  }
};

// This class will be implemented by the user.
class VerySmartProxy : public TAO_Smart_Proxy_Base
{
 // DESCRIPTION:
 // This is the smart Proxy will is defined by the user
 // to suit his needs.
 int method ()
 {
   print "Yahoo, I am so smart"
   this->proxy_->method ();
 }

}

// --------------------Related Stub Changes------------------


// Generated by TAO_IDL. Note the changes wherein the
// TAO_Proxy_Factory_Adapter is used.

interface_ptr _unchecked_narrow (CORBA::Object obj,
                                 CORBA::Environment &)
{
   if (CORBA::is_nil (obj))
        return test::_nil ();
      TAO_Proxy* Proxy = obj->_stubobj ();
      stub->_incr_refcnt ();
      interface_ptr *default_proxy = interface::_nil ();

      if (obj->_is_collocated () && _TAO_collocation_interface_Stub_Factory_function_pointer != 0)
        {
          default_proxy =
            _TAO_collocation_interface_Stub_Factory_function_pointer (obj);
        }

      if (CORBA::is_nil (default_proxy))
        ACE_NEW_RETURN (default_proxy, interface (stub), test::_nil ());

      return TAO_PROXY_FACTORY_ADAPTER::instance ()->create_proxy (default_proxy);
    }
}

Implementation Issues


Acknowledgements

Nanbor Wang and Dr.Schmidt for their help in designing and discussing this feature.


References

CORBA Distributed Objects using Orbix - Sean Baker

Visigenic Documentation


Last Update

Date: 21thSept99

By: Kirthika Parameswaran