チュートリアル:アプリケーションで DataSnap サーバーを使用する

提供: RAD Studio
移動先: 案内検索

データベースおよび LiveBinding のチュートリアル への移動


DataSnap 技術により、インターネット、ローカル ネットワークまたはローカル ホスト内を通信する、クライアントサーバー型アプリケーションを作成できます。

次のサンプルでは、簡単なローカルのクライアントサーバー型アプリケーションを作成するときの DataSnap の使用方法について示します。 クライアント アプリケーションとサーバー アプリケーションの両方とも Delphi で実装されています。 サーバーを作成し、クライアントとサーバー間の接続を DataSnap でアクティブにした後に、サーバーで定義され、実装されているメソッドを、クライアントが呼び出すことができます。

サーバーは Delphi と C++ のいずれでも実装できます。 この例では両方を示します。 クライアントを同じ言語で実装する必要はありません。 DataSnap では、Delphi でサーバーを、C++ でクライアントを実装することも、その逆の組み合わせにすることも可能です。

DataSnap サーバーの主要コンポーネント

主なコンポーネントは以下のとおりです。

TDSServer コンポーネントは、DataSnap サーバー アプリケーションの中心ロジックです。 これには、サーバーを開始および停止する、StartStop メソッドが含まれています。 また、AutoStart プロパティもあります。 デフォルトでは、AutoStart の値は True に設定されており、サーバーは、アプリケーションの起動時に自動的に立ち上がります。 1 つのサーバー アプリケーションにつき、TDSServer コンポーネントが 1 つ必要となります。

TDSServerClass コンポーネントは、サーバー クラスを表します。

DataSnap サーバーはサーバー クラスのインスタンスを自動的に作成し、破棄します。 サーバー クラスのインスタンスは、TDSServerClass コンポーネントのLifeCycle プロパティによって制御されます。 LifeCycle プロパティに指定できる値は次の3つです: ServerSessionInvocation

  • LifeCycleServer に設定すると、DataSnap サーバーは、サーバー アプリケーションに接続するすべてのクライアントが使用する、サーバー クラスのインスタンスを 1 つ作成します。 これは "シングルトン" パターンを表します。 Server ライフ サイクルを使用するときには注意してください。ユーザーのサーバー クラスをスレッドセーフで実装する必要があるからです。 つまり、複数のスレッドから同時にアクセスできるように、サーバー クラスを設計する必要があります。
  • LifeCycle のデフォルト値は、Session です。 つまり、DataSnap サーバーは各接続クライアントに対して、サーバー クラスのインスタンスを 1 つ作成します。
  • LifeCycle プロパティの 3 番目の値は、Invocation です。 この場合、サーバー クラスのインスタンスは、クライアントからメソッド呼び出しが到着するたびに作成され、破棄されます。サーバー クラスの状態はメソッド呼び出しの間では保持されません。

クライアントとサーバー間の通信を実行するためにコンポーネントも必要です。

TDSTCPServerTransport コンポーネントは、複数スレッドでクライアント接続を受信するためにリスンする、マルチスレッドの TCP サーバーを実装します。 このコンポーネントには、イベントがありません。 Port プロパティは、使用する TCP ポートを示します。 デフォルトのポート番号は 211 です。 クライアントとサーバー間の通信に HTTP を使用することもできます。

サーバー アプリケーションの作成

  1. プロジェクトを新規作成します。
    • Delphi の場合、メイン メニューから、[ファイル|新規作成|VCL フォーム アプリケーション - Delphi] を選択します。
    • C++ の場合、メイン メニューから、[ファイル|新規作成|VCL フォーム アプリケーション - C++Builder] を選択します。
    フォームの Caption プロパティを ServerForm に変更します。
  2. 次のコンポーネント(ツール パレットDatasnap Server カテゴリ)をフォームに配置します。
メイン メニュー項目の[ファイル|すべて保存]をクリックします。 ファイルを MyServer、プロジェクトを MyServerProj として保存します。
この時点で、サーバー アプリケーションは次のようになっています。

DS App1.jpg



次に示す手順に従って、3 つのコンポーネントを互いにリンクします。
  • TDSServerClass コンポーネントをフォーム上で選択します。 Server プロパティを TDSServer コンポーネントの名前に設定します(この例の場合、DSServer1)。
  • TDSTCPServerTransport コンポーネントをフォーム上で選択します。 Server プロパティを TDSServer コンポーネントの名前に設定します(この例の場合、DSServer1)。
  1. 新しいユニットをプロジェクトに追加します。
    • Delphi の場合、メイン メニューから、[ファイル|新規作成|ユニット - Delphi] を選択します。
    • C++ の場合、メイン メニューから、[ファイル|新規作成|ユニット - C++Builder]を選択します。
    ユニットを Delphi ファイル MyClass.pas、または C++ ファイル MyClass.cpp に保存します。 このユニットには、クライアント アプリケーションで使用するサーバーのクラスの実装が含まれます。 この例では、次のコードは、1 つのメソッド(2 つの浮動小数点数を合計する)を含む MyClass というクラスの実装を表します。
    Delphi
    unit MyClass;
    
    interface
    uses Classes;
    type
      {$METHODINFO ON}
      TMyClass = class(TComponent)
        function Sum(const A, B: Double): Double;
      end;
      {$METHODINFO OFF}
    
    implementation
    { TMyClass }
    function TMyClass.Sum(const A, B: Double): Double;
    begin
      Result := A + B;
    end;
    
    end.
    

    メモ: {$METHODINFO ON} 指令は、Datasnap サーバーが必要とする実行時情報を生成させます。このため、これは必須で、単なるコメントではありません。 詳細は、「METHODINFO 指令(Delphi)」を参照してください。


     


    C++

    MyClass.h に次のコードを記述します。

    #include <DSServer.hpp>
    
    class DECLSPEC_DRTTI TMyClass : public TComponent
    {
    private:
    public:
      double Sum(const double A, const double B);
    };
    #endif
    

    MyClass.cpp に次のコードを記述します。

    double TMyClass::Sum(const double A, const double B)
    {
      return A + B;
    }
    

    メモ: C++ アプリケーション設計時に、DataSnap で RTTI がサポートされるようになりました。 DECLSPEC_DRTTI 宣言では、Delphi の {$METHODINFO ON} 指令と同様に、Datasnap サーバーで必要な実行時情報が生成されます。これは必須です。


    • Delphi では、このユニットの名前 MyClass をサーバー アプリケーションのユニット MyServer.pasuses 句に追加します。
    • C++ では、次の行を MyServer.h に追加します。
    #include "MyClass.h"
    
  2. クライアント アプリケーションから呼び出したいクラスを指定するには、TDSServerClass コンポーネントの OnGetClass イベントを定義します。 MyServer の[デザイン]タブで次のとおり実行します。
    1. TDSServerClass コンポーネントをフォーム上で選択します。
    2. [イベント]タブをオブジェクト インスペクタで選択します。
    3. OnGetClass イベントの値をダブルクリックします。
    4. ちょうど生成された関数で、PersistentClass を設定する、1 行のコードを追加します。
    Delphi
    procedure TForm1.DSServerClass1GetClass(DSServerClass: TDSServerClass;
      var PersistentClass: TPersistentClass);
    begin
      PersistentClass := TMyClass;
    end;
    


    C++

    void __fastcall TForm1::DSServerClass1GetClass(TDSServerClass *DSServerClass, TPersistentClass &PersistentClass)
    
    {
      PersistentClass = __classid(TMyClass);
    }
    
    このイベントを実装しないと、起動直後に、アプリケーションから、次のメッセージとともに TDBXError 例外が発生します。

    OnGetClass event not set or it did not provide a class reference (OnGetClass イベントが設定されていないか、クラス参照がありません)

    OnGetClass イベントには、参照として渡される PersistentClass 引数があります。 イベント ハンドラのコードで、開発者は PersistentClass にサーバー クラスへのクラス参照を割り当てる必要があります(前のサンプルを参照)。
    これが DataSnap アーキテクチャを理解するために必要な重要概念です。 クラス参照PersistentClass に割り当てられます。オブジェクト参照ではありません。

これでサーバー アプリケーションの実装は完了です。

クライアント アプリケーションの作成

  1. クライアント アプリケーションをサーバー アプリケーションと同じプロジェクト グループで作成するには、プロジェクト マネージャのプロジェクト グループ名を右クリックして、コンテキスト メニューから[新規プロジェクトの追加...]を選択するか、メイン メニューから[プロジェクト|新規プロジェクトの追加...]を選択します。[項目の新規作成] ダイアログ ボックスが開きます。
    • Delphi では、[Delphi プロジェクト]カテゴリを選択してから、[VCL フォーム アプリケーション]を選択し、[OK]をクリックします。
    • C++ の場合、[C++Builder プロジェクト]カテゴリを選択してから、[VCL フォーム アプリケーション]を選択し、[OK]をクリックします。
    フォームの Caption および Name プロパティに ClientForm を設定します。 メイン メニュー項目の[ファイル|すべて保存]をクリックします。 ファイルを MyClient、プロジェクトを MyClientProj として保存します。 プロジェクト グループを DSServerExample として保存します。
  2. データを入力し、結果を書き込むコントロール(合計計算用のボタン、ラベル、編集ボックス)をクライアント フォームに次の図のように配置します。 ラベル A の隣にある TEditName プロパティを EditA に、BTEditNameEditB に変更します。 Result TEditName を、EditResult に設定します。 すべての TEdit コントロールの Text プロパティを、空に変更します。 TButtonCaptionCalculate に設定します。
  3. TSQLConnection コンポーネントを、ツール パレット dbExpress カテゴリから追加します。 TSQLConnection の次のプロパティを設定します。
    • Driver: Datasnap(クライアント側からみると、このプロバイダはデータベースへの接続と同様であるが、実際には、DataSnap サーバーへの接続)
    • LoginPrompt: False(オプション、クライアントがサーバーに接続するたびにユーザー名とパスワード用のダイアログが表示されない)
クライアント フォームは次のようになります:

DSAppClientForm.png



  1. クライアントサーバー型アプリケーションを作成するときの一番重要な手順は、サーバーで実装されるすべての機能のプロトタイプを含むインターフェイスを作成することです。 次のとおり実行します。
    • プロジェクト マネージャで、サーバー プロジェクト MyServerProj の名前をダブルクリックして、サーバー プロジェクトを選択します。
    • [実行|デバッガを使わずに実行]をメイン メニューから選択し、サーバーを実行します。 表示される[ServerForm]ダイアログを最小化できます。
    • サーバー実行中に、プロジェクト マネージャで、名前 MyClientProj をダブルクリックして、クライアント プロジェクトを選択します。
    • [デザイン]タブで、TSQLConnection コンポーネントの Connected プロパティを、True に設定します。
    • クライアント フォームの TSQLConnection コンポーネントを右クリックし、そのコンテキスト メニューから、[DataSnap クライアント クラスの生成]をクリックします。 新しいユニットがユーザーのクライアント プロジェクトに追加されます。サーバーで実装されたクラスに関する情報と、これらのクラスに含まれるすべてのメソッドが含まれます。
      • Delphi では、新規ユニットを MyDSClient.pas として保存し、このユニット名 MyDSClientMyClient.pas のユニットのリストに追加します。
      • C++ の場合は、新規ユニットを MyDSClient.cpp として保存します。 #include "MyDSClient.h" 行を MyClient.cpp の先頭に追加します。
  2. クライアント アプリケーションで必要なメソッドを呼び出します。 この例では、OnClick イベントを TButton コンポーネントに対して実装し、自動生成された DataSnap クライアント ユニットの Sum メソッドを呼び出します。 ここで、生成クラスは TMyClassClient であり、ボタンのイベント ハンドラは TClientForm.CalculateClick(Delphi)またはTClientForm::Button1Click(C++)です。 Delphi
    procedure TClientForm.CalculateClick(Sender: TObject);
    var
      Temp: TMyClassClient;
      A, B: Double;
    begin
      Temp := TMyClassClient.Create(SQLConnection1.DBXConnection);
    try
      A := StrToFloat(EditA.Text);
      B := StrToFloat(EditB.Text);
      EditResult.Text := FloatToStr(Temp.Sum(A, B));
    finally
      Temp.Free;
    end;
    


    C++

    void __fastcall TClientForm::Button1Click(TObject *Sender)
    {
      TMyClassClient *Temp;
      double A, B;
    
      Temp = new TMyClassClient(SQLConnection1->DBXConnection);
      try
      {
        A = StrToFloat(EditA->Text);
        B = StrToFloat(EditB->Text);
        EditResult->Text = FloatToStr(Temp->Sum(A, B));
      }
      __finally
      {
        delete Temp;
      }
    }
    
  3. 最後に、クライアント アプリケーションをビルドし実行します。 クライアント フォームが表示されます。 AB の各フィールドに 10 進数を入力し、[Calculate] ボタンをクリックします。合計が Result フィールドに表示されます。 次のエラー メッセージが表示された場合は、
    Connection cannot be nil. Make sure the connection has been opened.(接続に nil を指定できません。接続が開いていることを確認してください。) TSQLConnection コンポーネントの Connected プロパティが、True に設定されていない可能性があります。

DSAppClientRunning.png



メモ: サーバー アプリケーションを終了する前に、すべての SQL 接続を必ず閉じてください。 この例では、クライアントの TSQLConnection コンポーネントの Connected プロパティを、False に設定します。 DataSnap では中断している接続に関する警告が表示されません。したがって、サーバーが閉じられているように見える場合でも、サーバーへの接続がなくなるまで、サーバーは終了しません。 すべてのクライアント アプリケーションを閉じても、この問題の解決になりません。 Delphi IDE からサーバーへの接続を自動的に開き、公開されたクラスとメソッドを参照できるからです。

関連項目