Registering Servants

A servant is an local object that is registered in the broker to be invoked by remote clients. In other words, a servant is an object publicly available through the network. To create servants, it is necessary to have an initialized broker. See section Initializing Brokers.

Creation

Servants are created by method newservant(object [, key, type]) of a broker. It returns an objet that represents the new registered servant. Parameter object is the local object that will receive the invocations destined to the servant being created. This object only have to implement the methods when they are actually invoked by a remote client. Therefore, a servant's invocations are very late bound.

Every servant has an unique name in a broker. This name is called the key, which can be provided as the second parameter of operation newservant. If no key is provided, an automatic one is generated based on the memory position where the object is allocated. All automatically generated keys starts with a special prefix that can be defined by field keyprefix in the configs table passed to function oil.init. The default prefix is "_". If two servants are created with the same key, an error is raised. A single object can be used as the implementation of multiple servants. But, in such case, the key of each additional servant must be provided. The code below is a complete implementation of a OiL server using the LuDO RMI protocol.

require "oil"

oil.main(function()
  -- create an object to be exported via OiL
  local hello = {}
  function hello:sayto(name)
    print(string.format("Hello, %s!", name))
  end
  
  -- initialize a LuDO ORB
  local broker = oil.init{flavor="ludo"}
  
  -- registers a servant and save a textual
  -- reference for it in a file 'hello.ref'.
  oil.writeto("hello.ref",
    broker:tostring(
      broker:newservant(hello)))
  
  -- starts processing remote invocations
  broker:run()
end)

Some RMI protocols supported by OiL rely on typing information to perform invocations correctly, e.g. CORBA. When one of these protocols is the one used by the broker, it is necessary to inform the type of each servant being created. In such cases, the type shall be defined by the optional parameter type of method newservant. The possible values for this parameter depends on the RMI protocol being used. The code below is a implementation of the server above using a CORBA ORB.

require "oil"

oil.main(function()
  -- create an object to be exported via OiL
  local hello = {}
  function hello:sayto(name)
    print(string.format("Hello, %s!", name))
  end
  
  -- get the default, which is a CORBA ORB
  local broker = oil.init()
  
  -- load an IDL definition
  broker:loadidl[[
    interface Hello {
      void sayto(in string name);
    };
  ]]
  
  -- registers a servant with interface 'Hello'
  -- and save a textual reference for it in a
  -- file 'hello.ref'.
  oil.writeto("hello.ref",
    broker:tostring(
      broker:newservant(hello, nil, "Hello")))
  
  -- starts processing remote invocations
  broker:run()
end)

Behavior

The servant object behaves like its implementation object. This means, that any method call performed on the servant results in the same call on its implementation object. Furthermore, every field provided by the implementation object is also provided by the servant. However, the servant provides additional fields that are described below.

_key
The string value that identifies the servant in its broker.
_deactivate()
Method that unregister the servant from its broker.

References

Prior to invoke a method on a remote servant, the client process must get a reference to the servant. The easiest way to get a reference to a servant is to provide the servant as the return value of a method of another servant that the client already has a reference, as described in the example below.

local Factory
function Factory:create()
  local hello = { say = function() print("Hello") end }
  return broker:newservant(hello)
end

On the other hand, this approach is not feasible to get the first reference to a remote servant. The alternative approach is to use a textual reference, which is a string value contained the information necessary to generate a reference to a servant. Textual references are created by method tostring(servant) of brokers. Such references can be stored in files (see auxiliary operation oil.writeto) or passed as command-line parameters to applications.

Deactivation

Lua relies on automatic memory management by means of garbage collection. However, it is very difficult to build a reliable garbage collection mechanism over a distributed environment. OiL does not impose that its underlying RMI protocol provide this kind of support. Instead, OiL provides means for the application to manage explicitly the release of memory used by servants by means of deactivation.

A servant is deactivated by method deactivate(servant) of its broker. After this call, the servant is removed from its broker and all resources associated to it are released. In particular, after a servant is deactivated its key becomes free, so another object can be used to create a servant with this key.

Copyright (C) 2004-2008 Tecgraf, PUC-Rio

This project is currently being maintained by Tecgraf at PUC-Rio.