6.3.3 サーバントメソッドのインプリメント
IDLはC++と似た構文を持ち,モジュール,インタフェース,データ構造などの定義に使用できます。インタフェースを含むIDLをコンパイルするとき,サーバントのベースクラスとして動作するクラスが生成されます。例えば,Bank.idlファイルには,AccountManagerインタフェースが記述されます。
- コードサンプル6-7 Bank.idlに記述されるインタフェース
module Bank{ interface Account { float balance(); }; interface AccountManager { Account open (in string name); }; };
コードサンプル6-8にサーバ側のAccountManagerインプリメンテーションを示します。
- コードサンプル6-8 AccountManagerImplコード(C++)
class AccountManagerImpl : public POA_Bank::AccountManager { private: Dictionary _accounts; public: virtual Bank::Account_ptr open(const char* name) { // Lookup the account in the account dictionary. Bank::Account_ptr account = (Bank::Account_ptr) _accounts.get(name); if(account == Bank::Account::_nil()) { // Make up the account's balance, between 0 and // 1000 dollars. float balance = abs(rand()) % 100000 / 100.0; // Create the account implementation, given // the balance. AccountImpl *accountServant = new AccountImpl(balance); try { // Activate it on the default POA which is root // POA for this servant PortableServer::POA_var rootPOA = _default_POA(); CORBA::Object_var obj = rootPOA->servant_to_reference(accountServant); account = Bank::Account::_narrow(obj); } catch(const CORBA::Exception& e) { cerr << "_narrow caught exception: " << e << endl; } // Print out the new account. cout << "Created " << name << "'s account: " << account << endl; // Save the account in the account dictionary. _accounts.put(name, account); } // Return the account. return Bank::Account::_duplicate(account); } };
Javaの場合,コードサンプル6-9に示すように,AccountManagerPOA.javaが作成され,サーバ側のAccountManagerオブジェクトインプリメンテーションのスケルトンコード(インプリメンテーションベースコード)として動作します。
- コードサンプル6-9 AccountManagerImplコード(Java)
import org.omg.PortableServer.*; import java.util.*; public class AccountManagerImpl extends Bank.AccountManagerPOA { public synchronized Bank.Account open(String name){ // Lookup the account in the account dictionary. Bank.Account account = (Bank.Account) _accounts.get(name); // If there was no account in the dictionary, create one. if(account == null){ // Make up the account's balance, // between 0 and 1000 dollars. float balance = Math.abs(_random.nextInt()) % 100000 / 100f; // Create the account implementation, given // the balance. AccountImpl accountServant = new AccountImpl(balance); try { // Activate it on the default POA // which is rootPOA for this servant account = Bank.AccountHelper.narrow(_default_POA(). servant_to_reference(accountServant)); }catch (Exception e){ e.printStackTrace(); } // Print out the new account. System.out.println( "Created " + name + "'s account: " + account); // Save the account in the account dictionary. _accounts.put(name, account); } // Return the account. return account; } private Dictionary _accounts = new Hashtable(); private Random _random = new Random(); }
AccountManagerインプリメンテーションは,サーバコードで作成し活性化しなければなりません。このサンプルでは,AccountManagerは,記録先であるアクティブオブジェクトマップにオブジェクトIDを渡すactivate_object_with_idを使用して活性化されます。アクティブオブジェクトマップは,オブジェクトIDをサーバントにマッピングする単なるテーブルです。この手法はオブジェクトの明示的な活性化と呼ばれ,POAがアクティブなときは常にこのオブジェクトが使用できるようにします。
- コードサンプル6-10 サーバントの作成と活性化(C++)
// Create the servant AccountManagerImpl managerServant; // Decide on the ID for the servant PortableServer::ObjectId_var managerId = PortableServer::string_to_ObjectId("BankManager"); // Activate the servant with the ID on myPOA myPOA->activate_object_with_id(managerId,&managerServant);
- コードサンプル6-11 サーバントの作成と活性化(Java)
// Create the servant AccountManagerImpl managerServant = new AccountManagerImpl(); // Decide on the ID for the servant byte[ ] managerId = "BankManager".getBytes(); // Activate the servant with the ID on myPOA myPOA.activate_object_with_id(managerId, managerServant);