Remote Method Invocation 00k1126 Hiroko Suzuki
RMI概要 Remote Method Invocation →遠隔メソッド呼び出し 異なるJVM上に存在するオブジェクトのMethodを呼び出す機能を実現するための仕組みである
RMI概要Ⅱ 通信の部分のコードを意識せずにサーバ・クライアントの機能を実現できる JDK1.1以降で標準ライブラリとして提供されている(JDK1.3.0使用) Methodを呼び出す際の引数・戻り値として、オブジェクトを受け渡すことが出来る
RMIの仕組み ServerとClientはinterfaceで結合される ServerはClientに対してオブジェクトの参照(どのMethodが参照可能か)を提供し、Clientはその参照を用いてServerのMethodを呼び出す 上記の機能を成り立たせるためにRegistryを使用する
RMIRegistry 名前付けされたRemote Objectの登録・検索を行うネームサーバである RMIのオブジェクトは一意のURLと名前で登録され、サービスの呼び出しはこのRegistryへの問い合わせによって開始される RMIのプログラムの実行時にはRMIRegistryがバックグラウンドで起動している必要がある
RMI Application 作成手順 Server側 1. Remote Object のInterfaceを作成 2. Remote Object の実装(1.のInterfaceをImplementする) Client側 3. Remote Objectを使うClientを実装
RMI Application 実行手順 ソースコードのコンパイル リモートオブジェクトのコンパイル これによって新しいバイトコードが2つ生成される(StubとSkel)
簡単な例での実装
Example(basic) – Server 側 1. Remote ObjectのInterfaceの定義 Remote Interface はRemoteのサブクラスである Remote Method の定義を記述し、また、RemoteMethodはRemoteExceptionをthrowしなければならない import java.rmi.*; interface HelloWorld extends Remote { String sayHelloWorld( String name ) throws RemoteException; }
Example(basic) – Server 側 2. Remote Objectの作成 ・UnicastRemoteObjectを継承し、RemoteInterfaceを実装する HelloWorldObj.java public class HelloWorldObj extends UnicastRemoteObject implements HelloWorld
Example(basic) – Server 側 ・ Superclass であるUnicastRemoteObjectのコンストラクタがRemoteExceptionを送出するので、コンストラクタを作成し、RemoteExceptionをthrowするようにする // コンストラクタ public HelloWorldObj() throws RemoteException { }
Example(basic) – Server 側 ・RMIを利用可能にするためにセキュリティマネジャの設定 ・RMIRegistryへの登録 HelloWorldObj.java // セキュリティマネージャーの設定 System.setSecurityManager ( new RMISecurityManager() ); // サーバー側のリモートオブジェクトを生成 HelloWorldObj obj = new HelloWorldObj(); // リモートオブジェクトに新しい名前を関連付ける Naming.rebind( "MyObject", obj );
Example(basic) – Client 側 ・ Clientのプログラムを作成し、その中でRemote Objectの名前を引数にしてNaming.lookup Methodを呼ぶ Web Server に入れてアクセスさせる場合はlocalhost の部分にIPaddress もしくはaddressを記述する // リモートオブジェクトの参照(スタブ)を取得します obj = ( HelloWorld )Naming.lookup ( "rmi://localhost/MyObject" );
Example(basic) – Compile 全体のソースコードをCompile C:\> javac *.java Remote Object の Compile C:\ rmic HelloWorldObj この結果、 HelloWorldObj_Skel.class(スケルトン)と HelloWorldObj_Stub.class(スタブ)がディレクトリ内に生成される。実際に異なるJVMで通信を行うのはこの二つのクラスである。
Example(basic) – Security Policy grant { permission java.security.AllPermission; };
Example(basic) – 実行 NameServerの起動 C:\RmiRegistry > rmiregistry 正常に起動された場合はカーソルが点滅した状態になる RMIServer の起動 実行時に-Dオプションでプロパティの設定をする C:\RMI>java -Djava.security.policy=java.policy -Djava.rmi.server.codebase= file:///C:/RMI/ HelloWorldObj
Example(basic) – エラー例 java.rmi.ConnectException: Connection refused to host: xxx.xxx.x.xx(IPAddress) RMIRegistry が起動していない java.rmi.AlreadyBoundException: Server Serverという名前のRMIServerがRMIRegistry にもうすでに登録されている java.security.AccessControlException: access denied (java.net.SocketPermission xxx.xxx.x.xxx:xxxx connect,resolve) セキュリティポリシーの設定のエラー
Example(basic) – 実行 Client プログラムを実行する C:\RMI> java –Djava.security.policy=policy HelloWorldClient name Hello name!! と表示されたら成功
Example(basic) – エラー例 java.rmi.ConnectException: Connection refused to host: xxx.xxx.x.xx(IPAddress) Naming.lookup( “rmi://” + addr + “/Server”); addressの記述ミス 名前の記述ミス RMIServerが起動していない
Schedule Management System
Schedule Management System Host上の全ユーザの個人もしくはグループのスケジュールを管理するシステム スケジュールの形態 2003/4/30 開始時刻 終了時刻 内容 メモ 13:30 14:30 Meeting @lab 18:30 19:50 Lesson w4021
Schedule Management System 見た目
Schedule Management System Server Userの管理 Scheduleの管理 Client Scheduleの取得・編集
Schedule Management System ScheduleのAppointment Object : Appointment.class public int start; //start time public int end; //end time public String description; public String memo; //memo public Appointment( int sh, int sm, int eh, int em, String descrip, String me ) { start = sh * 60 + sm; end = eh * 60 + em; description = descrip; memo = me; }
Schedule Management System ServerはClientのScheduleをHashTableで管理する “2003/4/30”という日付の文字列をKeyとし、 その日のアポイントメントの配列(Appointmentを要素とするVector)を値とするHashTable そのHashTableを値とし、UserNameをKeyとしたHashTableでGroupのScheduleを管理する
Schedule Management System Clientは個人のScheduleを選択し今日の日付のScheduleを得る( Server側のgetDailyApp() Methodを呼ぶ ) ScheduleImpl.java public synchronized Vector getDailyApp( String usr, int year, int month, int day ) throws RemoteException { table = new Hashtable(); Object users=user.get(usr); if( users != null ){ table = ( Hashtable )users; String key = getKey( year,month, day ); Object obj = table.get( key ); if( obj == null ) return null; else return ( Vector )obj; }else return null; }
Schedule Management System Scheduleを編集し、Updateする場合はServer側のupdateDailyApp Methodを呼ぶ。ServerはsendData Methodで同じScheduleを参照しているClientにCallbackで変更を知らせる( sendData() ) ScheduleImpl.java public synchronized void updateDailyApp( String usr, int ye, int mo, int da, Vector v ) throws RemoteException { Object users=user.get( usr ); if( users != null ) table = ( Hashtable )users; String key = getKey( ye, mo, da ); table.put( key, v ); user.put( usr, table ); sendData( usr, key, v ); }
Schedule Management System ServerからClientのメソッドを呼び出す ScheduleImpl.java WhatDaysSch() と outUpdate( Vector v ) メソッドはClient側のメソッドである( RemoteExceptionをthrowしている必要がある ) private void sendData( String usr, String key, Vector v ){ try{ InterfaceClient cl; String str; int rsize = remote_obj.size(); for( int i=0; i<rsize; i++ ){ str = ( String )member.get( i ); if( str.equals( usr )){ cl = ( InterfaceClient )remote_obj.get( i ); if( key.equals( cl.WhatDaysSch() ) ){ cl.outUpdate( v ); }}} }catch( Exception e ){ e.printStackTrace(); }}
Conflictを避けるには Conflictを避けるには 1. TimeTable上のクリックした時間だけedit不可にする →1 Day Schedule の編集の柔軟性を高める 2. Edit WindowでそのAppointmentの優先度を選択出来るようにする 重要度で置き換えられたAppointment はどうするか? 1. 近い時間に移動する 2. 削除されたAppointmentを保管しておくVectorを作る 指定した時間後にそのデータを破棄する 3. その場で再編集