次の方法で共有


コラボレーション ワークフロー

SharePoint 2010 の機能強化

Paul Andrew

SharePoint 2007 では、コラボレーション アプリケーション対応のワークフローを導入し、多くの企業が、SharePoint ワークフローに手動プロセスを組み込むことでメリットを得ました。ソフトウェアの設計でワークフローを使用する主な理由は、長時間実行するプロセスを管理するためです。コンピューター ハードウェアは、できるだけ速く処理を完了するように設計されていますが、ユーザーがフォームにデータを入力したり、判断を下したり、外部操作の結果を共有したりするまでの待機時間は、CPU の使用率が高くなる数ミリ秒という応答時間よりも長くなります。SharePoint ワークフローは、このような手動プロセスを自動化する理想的な方法です。以前は、長時間実行されるアクティビティを記録および管理するためには、紙や複雑なソフトウェアを使用する必要がありました。

Windows Workflow Foundation は 2005 年に誕生し、当初は Microsoft .NET Framework 3.0 に同梱されていました。今日、SharePoint 2010 では、SharePoint 2007 で人気を博した機能をベースとして、ワークフロー開発者向けに多数の機能強化を施しています。SharePoint ワークフローは、ユーザーが作業を完了するまで待機しなければならないことが往々にしてある、長時間実行されるユーザー ワークフローに使用することをお勧めします。この記事では、SharePoint 2010 の主要な概念と新機能について説明します。まず、ワークフロー開発者向けの SharePoint 2010 の新機能を紹介し、その後、いくつかの新しいユーザー シナリオを紹介します。

ワークフロー モデル デザイン ツールの機能強化

SharePoint 2010 では、ワークフロー モデルの作成や管理のニーズに合わせて選択できるツールの幅が広がりました。ワークフローの開発には、Visual Studio 2010、SharePoint Designer 2010、および Visio 2010 を使用できます。

SharePoint 2010 を使用するには、.NET Framework 3.5 が必要です。.NET Framework の次期バージョン 4.0 は現在開発中ですが、開発のタイミングにより、SharePoint 2010 は .NET Framework 4.0 に依存していません。

Visual Studio 2010 では、SharePoint プロジェクト (特に、ワークフロー プロジェクト) を対象としたツールに関する多くの機能強化が施されています。新しい SharePoint ソリューション (WSP) パッケージを使用すると、SharePoint サーバーにワークフローを簡単に展開できるので、ASPX ワークフローの開始フォームや関連付け フォームを Visual Studio 2010 プロジェクトに追加できます (図 1 参照)。この記事の後半のチュートリアルでは、開始フォームを追加する方法を紹介します。


図 1 Visual Studio 2010 の SharePoint のプロジェクト テンプレート

SharePoint Designer 2010 では、ワークフローをデザインして、SharePoint に直接展開するための新しい視覚的なワークフロー デザイナーが導入されました。このデザイナーは、Visual Studio 2010 でワークフローの本格的な開発に着手する前に試作品を開発するツールとしても使用できます。

SharePoint Designer 2010 に施された機能強化により、SharePoint に組み込まれているワークフローを編集できるようになりました。また、InfoPath がインストールされている場合には InfoPath フォームを使用し、InfoPath がインストールされていない場合はデータ フォーム Web パーツを使用します (SharePoint Designer 2007 では ASPX フォームしか使用できませんでした)。SharePoint Desginer 2010 では InfoPath フォームが利用できるようになったので、後から InfoPath を使用してフォームを簡単に編集して、改良することができます。ワークフローで新しい列を指定すると、指定した列は、ワークフローと関連付けられている一覧のスキーマに自動で追加されます。これは、関連付け列と呼ばれるもので、SharePoint Designer ワークフローで使用できます。ユーザー プロファイル データは、ワークフローのプロパティにバインドできるので、SharePoint ユーザー プロファイルに関する情報を取得することが可能です。たとえば、承認を得る必要がある直接報告者の名前を調べられます。

SharePoint Designer 2010 には、ワークフローにアクティビティを作成しながら、そのアクティビティ内で承認プロセスを管理できるという柔軟性を兼ね備えたタスク プロセス デザイナーが用意されています。これには、エスカレーション プロセス、委任、承認の要件、承認プロセスで対象ドキュメントが変更された場合に発生する処理のセマンティクスを定義することも含まれます。

ワークフロー モデルは、Visio 2010 で作成し、SharePoint 2010 でさらに編集を進めることができます。Visio 2010 では、ビジネス プロセス モデリング表記がサポートされています。また、図面や検証結果を分解するサブプロセスとコンテナーがサポートされており、図面を分析することで、図面が適切に構築されているかどうかを確認できます。

SharePoint 2010 の新しいワークフロー モデル

サイト ワークフロー

サイト ワークフローにより、ワークフロー開発者は、ワークフローの実行対象となるリスト アイテムやドキュメント アイテムから解放されます。これは、ワークフローに実装されているプロセスが、リスト アイテムやドキュメントの結果として開始されない場合に便利です。これはよくあるシナリオで、開発者は、ワークフローを追加するためだけにダミーのリストとアイテムを作成していました。Visual Studio 2010 で、このワークフローを作成するのに必要なことは、ワークフロー プロジェクトのアイテムを作成する際に [Site Workflow] (サイト ワークフロー) を選択するだけです (図 2 参照)。


図 2 サイト ワークフローまたはリスト ワークフローを選択するページ

SharePoint では、[Site Actions] (サイトの操作) メニューの [Site Workflows] (サイト ワークフロー) を選択すると、アクティブなサイト ワークフローを確認できます。ここでは、開始できる新しいワークフロー、実行中のサイト ワークフロー、および完了したワークフローが表示されます。サイト ワークフローには開始をトリガするリスト アイテムやドキュメントがないので、SharePoint のユーザー インターフェイスまたは SharePoint API を使用して手動で開始する必要があります。

再利用可能な宣言型ワークフロー

SharePoint Designer 2010 では、再利用可能な宣言型ワークフローを作成できます。SharePoint 2007 では、SharePoint Designer で作成したワークフロー モデルと関連付けられるリストは 1 つだけでした。再利用可能な宣言型ワークフローは、特定のリストに依存せず、任意のリストと関連付けることができます。ワークフローのデザインは、再利用して、複数のリストと関連付けられます。"Save as Template" (テンプレートとして保存) コマンドを使用すると、再利用可能な宣言型ワークフローを含む WSP ファイルを作成できます。このファイルは、別の SharePoint サーバーまたは Visual Studio 2010 に移植できます。また、ワークフローは特定のリスト構造に接続されていないので、SharePoint Designer では、リストのフィールドにアクセスする必要なく、データにアクセスできます。

実行時とホスト時の機能強化

高い権限を持つワークフロー

SharePoint 2007 では、ワークフローはログオン ユーザーの ID で実行していました。SharePoint 2010 では、高い権限を持つワークフローを使用すると、ワークフローの実行に使用するアカウントを指定して、必要なアクセス許可を付与できます (図 3 参照)。SharePoint Designer 2010 でワークフローを作成する際には、個々のステップを追加できるので、ログオン ユーザーではなくワークフローを作成したユーザーのアカウントでワークフローを実行することが可能です。


図 3 高い権限を使用した偽装手順を含む SharePoint Designer ワークフロー

SPTimer の場所

SharePoint では、最後の操作に基づいて、ワークフローのインスタンスを 2 つの場所のいずれかで実行します。ワークフローで行われた最後の操作がユーザーの入力待ちである場合、ワークフローは、ユーザーが入力を行った Web フロント エンドで引き続き実行されます。ワークフローが遅延タイマーまたは受信したイベントにより引き続き実行されている場合、ワークフローは SPTimer サービス内で実行されます。SharePoint サーバー管理に導入された新しいオプションを使用すると、SPTimer サービスを実行する優先サーバーを設定できます。これには、SharePoint サーバー管理で、[Application Management] (アプリケーション構成の管理) の [Manage Content Databases] (コンテンツ データベースの管理) メニューをクリックします。次に、コンテンツ データベースをクリックし、[Preferred Server for Timer Jobs] (タイマー ジョブの優先サーバー) の設定がある位置まで下方向にスクロールします (図 4 参照)。SPTimer サービスを実行するのが望ましくないサーバーでは、SPTimer サービスを手動で停止することもできます。


図 4 ワークフロー タイマー ジョブの優先サーバーの設定

ワークフロー メッセージングの機能強化

SharePoint 2010 では、リスト ベースのワークフロー向けに 4 つの新しいワークフロー イベント レシーバーを追加しました。利用できるワークフロー イベント レシーバーの種類は、開始中、開始済み、延期、および完了です (図 5 参照)。これらは SharePoint の他のイベント レシーバーと類似しており、イベントへの応答としてサーバーでコードを実行します。開発作業を簡略化するため、Visual Studio 2010 には、このようなイベントを簡単に使用できるようにするイベント レシーバー向けのプロジェクトの種類が用意されています。新しいイベントは、特定のリストに適用され、そのリストに関連付けられているワークフロー インスタンスでイベントが発生するたびに呼び出されます。つまり、これらのイベント レシーバーは、サイト ワークフローで呼び出すことができません。また、イベント レシーバーではリストが必要になります。


図 5 Visual Studio 2010 で構築できるイベント レシーバー

SharePoint 2007 では、ワークフローにユーザーを簡単に組み込めるようになりましたが、外部システムとのメッセージの送受信は困難でした。推奨されていたアプローチは、Web サービスを使用して外部システムにメッセージを送信する際にはタスク アイテムを使用し、外部システムでタスクを更新して結果を返すようにすることでした。

SharePoint 2010 では、プラグ可能なワークフロー サービスのサポートを追加しました。このサービスは、Windows Workflow Foundation (WF) 開発者には馴染みのあるもので、メソッドとイベントを含むインターフェイスを作成することで定義します。このインターフェイスは、CallExternalMethod および HandleExternalEvent という 1 組のアクティビティに接続されています。.NET Framework の WF に同梱されている WCA.exe という名前のツールでは、このインターフェイスに基づいて送受信する厳密に型指定されたアクティビティを生成します。このツールで生成したアクティビティは、SharePoint ワークフローでも使用できます。インターフェイスをプロパティで設定する必要はなく、ツール ボックスからワークフローのデザイン サーフェイスに直接ドラッグできます。

SharePoint ワークフローと統合するサービスのコードは、ワークフローからアクセスできるように GAC に読み込まれます。これは、SPWorkflowService 基本クラスから派生し、web.config ファイルで参照される必要があります。

これらの新しいアクティビティを使用すると、SharePoint ワークフローから外部システムに非同期にメッセージを直接送信できます。この記事後半の 2 つ目のチュートリアルでは、これらのアクティビティを作成および使用する方法を紹介します。

チュートリアル: Visual Studio 2010 で単純なワークフローを構築する

SharePoint ワークフローで重要なのは、ユーザーとの対話です。ですから、最も単純な処理は、ユーザーにタスクを割り当てて、そのユーザーの応答を待つことになります。このチュートリアルの手順では Visual Studio 2010 で導入された新しい SharePoint ツールを使用すると、どれほど簡単にタスクを割り当てられるかを紹介します。

手順 1 - 新しい SharePoint シーケンシャル ワークフロー プロジェクトを作成する

新しい SharePoint ワークフロー プロジェクトは簡単に作成できます。図 1 のとおり、新しいプロジェクト テンプレートを選択するボックスの一覧からシーケンシャル ワークフローを選択します。この手順は、ステート マシンのワークフローを作成する場合も同様です。

新しいワークフロー プロジェクト ウィザードは 4 つのページで構成されています。1 ページ目は、すべての SharePoint ツール プロジェクト テンプレートに共通のものですが、ソリューションを展開およびデバッグするのに使用するローカル SharePoint サイトの URL を指定します (図 6 参照)。


図 6 新しいワークフロー プロジェクト ウィザードの 1 ページ目

2 ページ目では、ワークフローの名前を指定して、ワークフローをリストと関連付けるのか、サイトとして定義するのかを選択します。このページについては、図 2 を参照してください。

3 ページ目では、Visual Studio で自動的にワークフローを関連付けるのか、展開後に手動で関連付けを行うのかを選択します。このチェック ボックスがオンになっていると (これが既定の設定です)、関連付けるリストの一覧 (リスト ベースのワークフローを選択している場合)、使用するワークフローの履歴リスト、および使用するタスク リストを選択できます (図 7 参照)。通常、履歴リストとタスク リストを変更する必要はありません。


図 7 新しいワークフロー プロジェクト ウィザードの 3 ページ目

4 ページ目では、ワークフローの開始方法を選択します (図 8 参照)。すべてのチェック ボックスをオフにすると、ワークフローを開始するのが困難になるため、お勧めしません。サイト ワークフローを選択している場合は、ワークフローを手動で開始するオプションしか選択できません。リスト ワークフローを選択している場合は、ドキュメントの作成時にワークフローのインスタンスを開始するか、ドキュメントの変更時にワークフローのインスタンスを開始するオプションも選択できます。


図 8 新しいワークフロー プロジェクト ウィザードの 4 ページ目

新しい空のワークフロー モデルは、Visual Studio 2010 のデザイン サーフェイスでは図 9 のような状態になります。WorkflowActivated アクティビティは、HandleExternalEvent アクティビティから派生し、SharePoint からワークフロー インスタンスに初期化データを提供します。HandleExternalEvent アクティビティについては、後で詳しく説明します。


図 9 既定の WorkflowActivated アクティビティの空のワークフロー

手順 2 - ワークフローに開始フォームを追加する

開始フォームは、ワークフローを開始するときにユーザーに対して表示できます。このフォームを使用すると、ワークフローを開始する前にパラメーター情報を収集できます。開始フォームは、Visual Studio 2010 のソリューション エクスプローラーでワークフロー アイテムを右クリックし、[Add] (追加) をポイントして、[New Item] (新しいアイテム) をクリックして追加できます (図 10 参照)。Workflow Initiation Form (ワークフロー開始フォーム) テンプレートを選択すると、ワークフローに新しいフォームが自動的に関連付けられます。これは HTML 形式で編集できる ASPX フォームです (図 11 参照)。


図 10 ワークフロー開始フォームを追加する

ASPX ファイルのコードでは、GetInitiationData という名前のメソッドを編集する必要があります。このメソッドでは文字列しか返されません。複数の値がある場合は、値を返す前に XML フラグメントにシリアル化することをお勧めします。ワークフロー インスタンスが実行された後であれば、この文字列は、workflowProperties.InitiationData を参照するだけで簡単に取得できます。GetInitiationData メソッドで複数の値がシリアル化されている場合は、値を XML フラグメントから逆シリアル化する必要があります。


図 11 既定の ASPX 形式のワークフロー開始フォーム

開始フォームの場合は、テキスト フィールドが 1 つ追加され、このフィールドの値が GetInitiationData メソッドで返されます。次のコードを、1 つ目の asp:Content タグ内に追加します。

<asp:TextBox ID="MyID" runat="server" /> <br />

GetInitiationData メソッドは既に存在しているので、必要なのは MyID.Text プロパティを返すコードを追加するだけです。次に更新した GetInitiationData メソッドのコードを示します。

private string GetInitiationData()
{
  // TODO: Return a string that contains the initiation data that will be passed to the workflow. Typically , this is in XML format.
  return MyID.Text;
}

手順 3 – ワークフローにログ アクティビティを追加する

LogToHistoryList アクティビティは、とても簡単に使用できます。作成された各ワークフロー インスタンスには、SharePoint ユーザー インターフェイスで確認できる履歴リストがあります。このアクティビティでは、1 つの文字列パラメーターを受け取り、履歴リストにアイテムを 1 つ追加します。また、このアクティビティは、ワークフロー インスタンスの状態を運用環境のユーザーに通知するものとしても使用できます。必要なのは、ツールボックスから LogToHistoryList アクティビティをワークフロー デザイン サーフェイスにドラッグして、Description プロパティを設定するだけです (図 12 参照)。


図 12 Visual Studio のツールボックスに配置されている SharePoint ワークフローのアクティビティ

ワークフローのプロパティは、"依存プロパティ" と言います。このようなプロパティは、実行時に別のアクティビティの依存するプロパティ (フィールド、プロパティ、メソッドなど) にバインドされています。このプロセスをワイヤアップと言い、このプロセスにより、コンパイル時にお互いに関する詳細な型情報を持っていないにもかかわらず、ワークフローでアクティビティが連動するようになります。Visual Studio のプロパティ ウィンドウに表示されている各プロパティは、ワークフロー クラスのクラス フィールドまたはクラス プロパティに接続されています。最も簡単に作成できるのはフィールドです。ワークフローのプロパティをワイヤアップするときに表示されるダイアログ ボックスを使用すると、新しいフィールドやプロパティを作成したり、既存のフィールドやプロパティにワイヤアップしたりすることができます。


図 13 作成したフィールドにバインドされている依存プロパティ

図 13 は、既定の名前で新しいフィールドを追加した状態です。次のコードは、アクティビティでプロパティをワークフローの開始データに設定するために MethodInvoking イベント ハンドラーに追加したものです。

public String logToHistoryListActivity1_HistoryDescription1 = default(System.String);

private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e)
{
  logToHistoryListActivity1_HistoryDescription1 = workflowProperties.InitiationData;
}

HistoryDescription プロパティには、アクティビティを接続する役割がないので、このプロパティの値はコードで直接設定できます。ですが、依存プロパティについて学習するのには、ちょうどよいシンプルなアクティビティです。

手順 4 – CreateTask アクティビティを追加する

この手順は、SharePoint タスク アイテムと呼ばれる手動プロセスのワークフローへの組み込みに関するメインの部分です。タスクを作成し、タスクをユーザーに割り当てて、そのユーザーが、そのタスクに変更を加えるまで待機します。CreateTask アクティビティは、ワークフロー デザイン サーフェイスにドラッグして、必要なプロパティを構成する必要があります。図 14 に、CreateTask アクティビティをデザイン サーフェイスにドラッグした直後の CreateTask プロパティ ウィンドウの状態を示します。


図 14 CreateTask アクティビティのプロパティ ウィンドウ

ここでは、まず、タスクの関連付けトークンが必要です。関連付けトークンは、ワークフローでのメッセージの関連付けに使用します。関連付けトークンでは、一意な ID が提供されるので、SharePoint で、特定のワークフロー インスタンスのタスク オブジェクトとワークフロー ランタイム間でのマッピングが可能になります。このマッピングは、SharePoint でワークフロー インスタンスに関するメッセージを受信したときに、適切なワークフロー インスタンス内の該当タスクを特定できるようにすることを目的としています。CorrelationToken プロパティは必ず構成する必要があります。また、ツールでは特に制御されていませんが、タスクには WorkflowToken プロパティを使用することをお勧めします。関連付けトークンの新しい名前として「TaskToken」と入力し、Enter キーを押します。プラス (+) 記号を展開し、OwnerActivityName の右側にあるドロップダウン ボックスの一覧からワークフローを選択します。

TaskId プロパティを構成する必要があります。このプロパティを構成すると、そのタスク ID 用の新しい GUID が指定されます。この設定は、TaskId プロパティを選択し、[…] をクリックして、プロパティ エディタを起動して行います。[Bind to a New Member] (新しいメンバーへのバインド) タブをクリックし、[Create Field] (フィールドの作成) をクリックして、[OK] をクリックします。TaskProperties プロパティについても、同じように構成する必要があります。それには、プロパティを選択し、[…] をクリックして、新しいフィールドを追加します。次に、ワークフロー デザイン サーフェイスで新しく作成した CreateTask アクティビティをダブルクリックして、createTask1_MethodInvoking ハンドラー コードを表示し、コードでプロパティの値を設定します。

新しいタスクには、タイトルを付ける必要があります (余談ですが、私は、タスクの説明に開始フォームから取得したデータを使用しています)。すべてのプロパティを設定すると、コードは、次のようになります。

public Guid createTask1_TaskId1 = default(System.Guid);
public SPWorkflowTaskProperties createTask1_TaskProperties1 = new
  Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

private void createTask1_MethodInvoking(object sender, EventArgs e)
{
  createTask1_TaskId1 = Guid.NewGuid();
  createTask1_TaskProperties1.Title = "Hello";
  createTask1_TaskProperties1.Description = workflowProperties.InitiationData;
}

手順 5 – OnTaskChanged アクティビティと CompleteTask アクティビティを追加する

While アクティビティを使用すると、タスクに必要な変更が加えられるまで待機できます。While アクティビティには、OnTaskChanged など、別のアクティビティが含める必要があります。Listen アクティビティは、一度に複数のイベントをリッスンするのに使用できます。これは、Listen の分岐内に実際のイベント レシーバー アクティビティを設定した Listen アクティビティを追加することで行います。また、OnTaskDeleted アクティビティを使用して、単にタスクが削除されるまで待機することも可能です。

イベントの応答待ちをエスカレーションしたり、タイムアウトしたりしなければならないことは往々にしてあります。これは、Listen アクティビティを使用してタスクの変更に関するメッセージをリッスンし、Delay アクティビティを使用してタイマー メッセージをリッスンすることで行います。一方のアクティビティで受信した最初のメッセージによりワークフローが再開し、もう一方のアクティビティでは待機を中止します。タイムアウトが発生すると、Delay アクティビティではメッセージを送信します。

上記の方法には多数のオプションがありますが、一番簡単なのは OnTaskChanged アクティビティを使用することです。このアクティビティでは、タスク アイテムへの変更を待機して、変更が発生するとワークフローを再開します。OnTaskChanged アクティビティを構成するには、CorrelationToken プロパティと TaskId プロパティを CreateTask アクティビティで構成したときと同じフィールドにワイヤアップする必要があります。

最後に、CompleteTask アクティビティを追加して、このアクティビティにも CorrelationToken プロパティと TaskId プロパティを設定します。図 15 のとおり、メッセージを待機するアクティビティは緑色、メッセージを送信するアクティビティは赤色で表示されます。これは、すべての SharePoint ワークフローに共通です。


図 15 完成したシンプルなタスク ワークフロー モデル

手順 6 – ワークフローを展開してテストする

ワークフローは、ほぼ完成したので、F5 キーを押して、展開の準備をします。F5 キーを押すと、ワークフローがコンパイルされて WSP にパッケージ化され、WSP が SharePoint に展開され、SharePoint の機能が有効になり、Visual Studio 2010 のデバッガーが SharePoint にアタッチされ、Internet Explorer で SharePoint サイトが表示されます。

SharePoint サイトが表示されたら、[Site Actions] (サイトの操作) メニューの [Site Workflows] (サイト ワークフロー) をクリックします。すべてのサイト ワークフローが表示されるので、作成したワークフローをクリックして、ワークフローを開始します。ワークフローを選択すると、ワークフローの開始フォームが表示されます (図 16 参照)。


図 16 ワークフローの開始フォーム

この基本的なワークフロー モデルは改良の余地があります。たとえば、コンテンツ タイプを使用して、ユーザーに割り当てるタスクを定義したり、電子メールを使用して、タスクが割り当てられたユーザーに通知したり、InfoPath フォームを使用して、ユーザーがデータを電子メールまたはオンラインで入力できるようにする複雑なフォームを作成したりすることができます。

チュートリアル: プラグ可能なワークフロー サービスを構築する

SharePoint 2010 では、SharePoint にプラグ可能なワークフロー サービスを追加する機能が新たに導入されました。Windows Workflow Foundation では以前から可能なことでしたが、SharePoint では、SharePoint でホストされているワークフロー ランタイムはロックダウンされていたので、プラグ可能なワークフロー サービスを追加することができませんでした。プラグ可能なワークフロー サービスは、ワークフロー インスタンスの外部でメッセージの送受信を行うようにデザインされています。ですが、プラグ可能なワークフロー サービスは、長時間実行される計算など、長時間実行されるシステム操作で役立ちます。

これは、ワークフロー ランタイムが長時間実行される作業をメッセージの汎化として管理する際に使用するメカニズムです。これは単にアクティビティ内で実行される短時間で完了する作業を実行し、長時間実行される操作が完了するまで (ユーザーがタスクを完了したことを通知するメッセージを受信するまで) ワークフローを中断します。ユーザーからの応答を待機している間、ワークフロー インスタンスは退避されるので、サーバーの CPU リソースや RAM リソースは消費しません (退避とは、ワークフロー インスタンスが、後で、リハイドレードされて、処理を続行できるような形でデータベース レコードに書き込まれた状態のことを言います)。

長時間実行される作業は、ワークフローで同じように処理されます。まず、ワークフローでは、長時間実行される作業を開始します (メッセージを送信します)。次に、長時間実行される作業が完了するまで (応答を受信するまで) ワークフローを中断します。関連付けトークンを使用して、応答を受信したときに適切なワークフロー インスタンスが再開されるようにしています。

たとえば、長時間実行される作業の一般的な 2 つの例を見てみましょう。1 つは、チャネルで応答を受信するまで、呼び出し元がブロックされる同期型の Web サービス要求です。これは、ワークフロー アクティビティ内で実行するのには適していません。ワークフロー サービスは、Web サービスの呼び出しが完了するのを待機してから、応答と併せてメッセージをワークフロー インスタンスに送信する必要があります。もう 1 つは、実行する必要がある CPU 使用率の高い作業項目です。というのも、このような作業項目はワークフロー アクティビティ外で実行する場合よりも実行にかかる時間が 1 秒長くなるからです。この場合も、ワークフロー サービスを使用して、ワークフロー サービスにスレッドを作成して、CPU 使用率の高い作業項目を実行できます。新しいスレッドでは、作業項目の実行が完了するとメッセージを送信します。

このどちらの例でも、同じパターンを実装しています。次のチュートリアルでは、SharePoint シーケンシャル ワークフローを作成して、100,000,000 より小さい値の中に素数がいくつあるのかを特定するために素数を因数分解するプラグ可能なワークフロー サービスを呼び出す方法を紹介します。この作業は、アクティビティのメイン ラインで実行するには時間がかかりすぎます。

手順 1 –プラグ可能なワークフロー サービスを作成する

Visual Studio 2010 でプラグ可能なワークフロー サービスを作成するには、サービスをプロジェクトのインターフェイスおよびクラスとして実装する必要があります。図 17 に、プロジェクトの MyService.cs という名前の新しいクラス ファイルに追加できるプラグ可能なワークフロー サービスの例を示します。コードでは、IMyService でインターフェイスを定義していますが、インターフェイスの実装は MyService クラスで行い、MessageOut メソッドで、個別のスレッドで匿名メソッドへの委任を行うことで大半のロジックを実行しています。個別のスレッドでは、RaiseEvent の呼び出しにより、待機している HandleExternalMessage アクティビティにメッセージが送信されます。

図 17 プラグ可能なワークフロー サービス

// Interface declaration
[ExternalDataExchange]
public interface IMyService
{
  event EventHandler<MyEventArgs> MessageIn;
  void MessageOut(string msg);
}

// Arguments for event handler
[Serializable]
public class MyEventArgs : ExternalDataEventArgs
{
  public MyEventArgs(Guid id) : base(id) { }
  public string sAnswer;
}

// Class for state
class FactoringState
{
  public SPWeb web;
public Guid instanceId;
  public FactoringState(Guid instanceId, SPWeb web)
  {
    this.instanceId = instanceId;
    this.web = web;
  }
}

// Interface implementation
class MyService : Microsoft.SharePoint.Workflow.SPWorkflowExternalDataExchangeService,
                  IMyService
{
  public event EventHandler<MyEventArgs> MessageIn;
  public void MessageOut(string msg)
  {
    ThreadPool.QueueUserWorkItem(delegate(object state)
      {
        FactoringState factState = state as FactoringState;
        DateTime start = DateTime.Now;
        int topNumber = 100000000;
        BitArray numbers = new System.Collections.BitArray(topNumber, true);

        for (int i = 2; i < topNumber; i++)
        { if (numbers[i]) { for (int j = i * 2; j < topNumber; j += i)
          numbers[j] = false; } }
        int primes = 0; for (int i = 2; i < topNumber; i++)
        { if (numbers[i]) primes++; }

        string sAnswer = "Found " + primes + " in " +
          Math.Round(DateTime.Now.Subtract(start).TotalSeconds, 0) + " seconds";

        // Send event back through CallEventHandler
        RaiseEvent(factState.web, factState.instanceId, typeof(IMyService),
                   "MessageIn", new object[] { sAnswer });
      }, new FactoringState(WorkflowEnvironment.WorkflowInstanceId,
                            this.CurrentWorkflow.ParentWeb));
    }

    // Plumbing that routes the event handler
    public override void CallEventHandler(Type eventType, string eventName,
      object[] eventData, SPWorkflow workflow, string identity,
      System.Workflow.Runtime.IPendingWork workHandler, object workItem)
    {
      var msg = new MyEventArgs(workflow.InstanceId);
      msg.sAnswer = eventData[0].ToString();
      msg.WorkHandler = workHandler;
      msg.WorkItem = workItem;
      msg.Identity = identity;
      // If more than one event - you'd need to switch based on parameters
      this.MessageIn(null, msg);
    }
    public override void CreateSubscription(MessageEventSubscription subscription)
    { throw new NotImplementedException(); }
    public override void DeleteSubscription(Guid subscriptionId)
    { throw new NotImplementedException(); }

手順 2 – web.config ファイルを更新する

プラグ可能なワークフロー サービスを構築したら、SharePoint で実行するワークフロー ランタイムに登録する必要があります。この処理は、ワークフロー サービスの web.config セクションを編集することで行います。web.config ファイルは、SPWebApplication.WebConfigModifications.Add を呼び出す機能レシーバーを使用して編集する必要があります。次に、追加する必要がある構成エントリを示します。

<WorkflowServices><WorkflowService Assembly="WorkflowProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YOURPUBLICKEY" Class="WorkflowProject1.MyService">
</WorkflowService></WorkflowServices>

アセンブリ名と公開キー情報は、GACUTIL.EXE /l コマンドを使用して入手できます。

手順 3 – ワークフロー モデルを作成する

残りの作業は簡単です。ワークフローに Call External Method アクティビティと Handle External Event アクティビティを追加して、このサービスをポイントするように、これらのアクティビティを構成します (図 18 参照)。Call External Method アクティビティでは、サービスの MessageOut メッセージを呼び出し、Handle External Event アクティビティでは MessageIn イベントが発生するのを待機します。これには、この 2 つのアクティビティで InterfaceType プロパティと EventName プロパティを設定する作業が必要です。


図 18 完成したプラグ可能なワークフロー サービスを使用するワークフロー


図 19 完成した素数を計算するプラグ可能なワークフロー サービス

手順 4 – ワークフローを実行する

このワークフローを実行すると、プラグ可能なワークフロー サービスで個別のスレッドが起動され、素数の計算を実行します。10 ~ 15 秒間実行すると、ワークフローの履歴項目が表示されます (図 19 参照)。0 ~ 100,000,000 には、5,761,455 個の素数があることが示されています。

ご覧のとおり、プラグ可能なワークフロー サービスを使用するには少しコードを記述する必要があり、接続するシステムが増えるごとに記述するコードの量も増えます。外部サービスとの通信に必要なコードの量を削減する方法は 2 つあります。1 つは、BizTalk Server に接続して、他のシステムとの接続に適切な BizTalk アダプターを使用することです。もう 1 つの方法は、SahrePoint 2010 のビジネス接続性サービスを使用することです。これらのサービスを使用すると、外部リストを使用して別のシステムのデータを公開できるようになります。

簡単で成功率が高い

Visual Studio 2010、SharePoint Designer 2010、および Visio 2010 で導入された新しいツールにより、開発者は、より簡単に SharePoint 2010 ワークフローの開発に着手して、開発作業を無事に完了することができます。SharePoint 2010 ワークフロー ホストの新機能により、SharePoint では、ソフトウェアが抱えるさまざまなワークフローの問題を堅牢かつ適切に解決できるようになりました。

ワークフローは、Visual Studio 2010 に同梱されている標準的な SharePoint WSP ファイル パッケージ化ツールを使用して、簡単に構築して、SharePoint に展開できます。多くの企業で一般的に使用されている標準的な SharePoint サイトに展開できるので、ワークフローをより簡単に導入できます。SharePoint ワークフローにより、タスクや電子メールを使用してユーザーと対話する実行時間の長いプロセスが構築しやすくなります。また、プラグ可能なワークフロー サービス、ビジネス接続性サービス、および BizTalk Server により、他のシステムとの通信も簡略化されます。

この記事で紹介した 2 つのチュートリアルのコードは、私のブログ (blogs.msdn.com/pandrew、英語) からダウンロードして、ご覧いただけます。

Paul Andrew は、SharePoint のシニア テクニカル プロダクト マネージャーです。彼は、SharePoint に関する開発者向けの情報を発信しています。2005 年には、筆頭著者として『Presenting Windows Workflow Foundation』(SAMS) を執筆しました。Paul は、ニュージーランドのマッセイ大学でコンピューター システム エンジニアリングの分野で工学士号を取得しています。