この章では、Coherence for .NETライブラリを使用する簡単なWindows ASP.NET Webアプリケーションを作成する手順について説明します。
Coherence for .NETを使用するWindows ASP.NET Webアプリケーションを開発して構成するには、次の6つの基本的な手順が必要です。
これらの手順の詳細は、次の各項で説明します。
ASP.NET Webアプリケーションを新規に作成する手順は次のとおりです。
Visual Studio 2005で「ファイル」→「新規作成」→「Web サイト」を選択します。
「テンプレート」の「ASP.NET Web サイト」を選択します。
最も使い慣れている開発言語を選択します。
アプリケーションを保存する場所(タイプとフルパス)を選択します。
「OK」ボタンをクリックすると、新しいソリューションと空のASP.NETアプリケーションが生成されます。
.NETアプリケーションでCoherence for .NETライブラリを使用するには、まずCoherence.dllライブラリに対する参照を追加する必要があります。
作成したプロジェクトで「プロジェクト」→「参照の追加」を選択します。または「ソリューション エクスプローラ」の「参照設定」を右クリックして、「参照の追加」を選択します。
表示される「参照の追加」ウィンドウで「参照」タブを選択し、ファイル・システム上のCoherence.dllライブラリを探します。
「OK」をクリックします。
Coherence for .NETライブラリを正しく構成するには、ライブラリで使用される各コンフィギュレーション・ファイルの適切なファイル名を指定したWeb.config XMLファイルを構成する必要があります。例24-2は、有効なWeb.configコンフィギュレーション・ファイルを示しています。
例24-1 Web.configコンフィギュレーション・ファイルのサンプル
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="coherence" type="Tangosol.Util.CoherenceConfigHandler, Coherence"/>
</configSections>
<coherence>
<cache-factory-config>coherence.xml</cache-factory-config>
<cache-config>cache-config.xml</cache-config>
<pof-config>pof-config.xml</pof-config>
</coherence>
...
</configuration>
<configSections>には、Coherence for .NETのコンフィギュレーション・セクションへのアクセスを処理するクラスを指定する必要があります。
Coherence for .NETのコンフィギュレーション・セクションの要素は次のとおりです。
cache-factory-config: CacheFactoryで使用するIConfigurableCacheFactoryおよびLoggerを構成するために、CacheFactoryで使用されるコンフィギュレーション・ディスクリプタのパスを記述します。
cache-config: 前述のキャッシュ・コンフィギュレーション(「クライアントでのCoherence*Extendの構成」を参照)を含むキャッシュ・コンフィギュレーション・ディスクリプタのパスを記述します。このキャッシュ・コンフィギュレーション・ディスクリプタは、DefaultConfigurableCacheFactoryで使用されます。
pof-config: アプリケーションで使用するカスタム型を登録するために、ConfigurablePofContextで使用されるコンフィギュレーション・ディスクリプタのパスを記述します。
例24-2は、coherence.xmlコンフィギュレーション・ファイルのサンプルを示しています。
例24-2 coherence.xmlコンフィギュレーション・ファイルのサンプル
<?xml version="1.0"?>
<coherence xmlns="http://schemas.tangosol.com/coherence">
<logging-config>
<destination>stderr</destination>
<severity-level>5</severity-level>
<message-format>{date} <{level}> (thread={thread}): {text}</message-format>
<character-limit>8192</character-limit>
</logging-config>
</coherence>
例24-3は、cache-config.xmlコンフィギュレーション・ファイルのサンプルを示しています。
例24-3 cache-config.xmlコンフィギュレーション・ファイルのサンプル
<?xml version="1.0"?>
<cache-config xmlns="http://schemas.tangosol.com/cache">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-contact-cache</cache-name>
<scheme-name>extend-direct</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-direct</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>5s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>
例24-4は、pof-config.xmlコンフィギュレーション・ファイルのサンプルを示しています。
例24-4 pof-config.xmlコンフィギュレーション・ファイルのサンプル
<?xml version="1.0"?>
<pof-config xmlns="http://schemas.tangosol.com/pof">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml</include>
<!-- include all application POF user types -->
<user-type>
<type-id>1001</type-id>
<class-name>ContactCache.Web.ContactInfo</class-name>
</user-type>
</user-type-list>
</pof-config>
これらのコンフィギュレーション・ファイルを作成すると、Coherenceクラスタに接続する準備が完了し、Coherence for .NETでサポートされるすべての操作を実行できるようになります。
Default.aspxページの「デザイン」タブに切り替えて、「ツールボックス」ペインから適切なコントロールをドラッグ・アンド・ドロップでページに追加します。Name、Street、City、StateおよびZipの各フィールドには、TextBoxコントロールおよび対応するLabelコントロールが必要です。これを図24-2に示します。
ページにコントロールを配置したら、各コントロールのIDおよびTextプロパティを変更する必要があります。コード内ではラベルを使用しないため、ラベルのIDプロパティ値は生成時のままにして、Textプロパティにのみ適切な値を入力します。IDおよびTextBoxコントロールには、txtName、txtStreetなどの名前を付けます。ボタンを1つ追加し、そのIDをbtnSaveに、TextプロパティをSaveに変更します。これを図24-3に示します。
ボタンを1つ追加し、そのIDをbtnClearに、TextプロパティをClearに変更します。これを図24-4に示します。
labelを追加し、そのIDをlblTotalに変更します。このラベルはキャッシュ・サイズの表示に使用されます。「ツールボックス」ペインの「検証」コントロール・リストからRequiredFieldValidatorを追加して、そのプロパティを設定する必要があります。これを図24-5に示します。
ControlToValidateプロパティがtxtNameコントロールに設定されていることに注意してください。
「ツールボックス」ペインの「データ」コントロール・リストから、GridViewコントロールとObjectDataSource(名前はdsContact)を追加します。これを図24-6に示します。
例24-5は、GridViewコントロール・ソースのコードを示しています。
例24-5 GridViewデータ・コントロールのコード
<asp:GridView ID="gridCache" runat="server" DataSourceID="dsContact" AutoGenerateColumns="False" Font-Names="Verdana">
<Columns>
<asp:TemplateField>
<ItemStyle Font-Size="Small"/>
<ItemTemplate>
<asp:HyperLink Text="[Remove]" ID="HyperLink1" runat="server" NavigateUrl='<%# "?removeKey=" +
DataBinder.Eval(Container.DataItem, "Name").ToString() %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name">
<HeaderStyle BackColor="#DCE7F7"/>
<ItemTemplate>
<asp:HyperLink runat="server" NavigateUrl='<%# "?getKey=" + DataBinder.Eval(Container.DataItem, "Name").ToString() %>'>
<%# DataBinder.Eval(Container.DataItem, "Name") %>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Street" HeaderText="Street">
<HeaderStyle BackColor="#DCE7F7"/>
</asp:BoundField>
<asp:BoundField DataField="City" HeaderText="City">
<HeaderStyle BackColor="#DCE7F7"/>
</asp:BoundField>
<asp:BoundField DataField="State" HeaderText="State">
<HeaderStyle BackColor="#DCE7F7"/>
</asp:BoundField>
<asp:BoundField DataField="Zip" HeaderText="Zip">
<HeaderStyle BackColor="#DCE7F7"/>
</asp:BoundField>
</Columns>
</asp:GridView>
例24-6は、ObjectDataSourceのコードを示しています。
例24-6 ObjectDataSourceのコード
<asp:ObjectDataSource ID="dsContact" runat="server" SelectMethod="GetData"
TypeName="ContactCache.Web.ContactInfoDataSource"
</asp:ObjectDataSource>
ここで、フィルタ列用にDropDownListを1つ、フィルタ基準用にTextBoxを1つドラッグ・アンド・ドロップして「Search」ペインを追加します。これを図24-7に示します。
ASP.NETアプリケーションが終了したときにクラスタのリソースを解放するために、Global.asaxに記述したApplication_Endイベント・ハンドラでCacheFactory.Shutdown()をコールする必要があります。例24-7は、この処理を実行するGlobal.asaxファイルを示しています。ここでは、例外が発生したときにエラー・ページを表示するためのコールも追加しています。
例24-7 エラー・ページへのユーザーのリダイレクト
<%@ Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
try
{
Application["contactCache"] = CacheFactory.GetCache("dist-contact-cache");
}
catch
{
}
}
void Application_End(object sender, EventArgs e)
{
CacheFactory.Log("Application terminated.", CacheFactory.LogLevel.Info);
INamedCache contactCache = Application["contactCache"] as INamedCache;
if (contactCache != null)
{
contactCache.Release();
}
CacheFactory.Shutdown();
}
void Application_Error(object sender, EventArgs e)
{
Server.Transfer("ConnectionError.html");
}
</script>
例24-8は、ContactInfoビジネス・オブジェクトの定義を示しています。
例24-8 ビジネス・オブジェクトの定義ファイルのサンプル
public class ContactInfo : IPortableObject
{
private string name;
private string street;
private string city;
private string state;
private string zip;
public ContactInfo()
{ }
public ContactInfo(string name, string street, string city, string state, string zip)
{
this.name = name;
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
}
public void ReadExternal(IPofReader reader)
{
name = reader.ReadString(0);
street = reader.ReadString(1);
city = reader.ReadString(2);
state = reader.ReadString(3);
zip = reader.ReadString(4);
}
public void WriteExternal(IPofWriter writer)
{
writer.WriteString(0, name);
writer.WriteString(1, street);
writer.WriteString(2, city);
writer.WriteString(3, state);
writer.WriteString(4, zip);
}
}
例24-9は、データをデータ・バインド・コントロールに提供するクラスを示しています。データのICollectionをデータ・バインド・コントロールに返す、publicのGetData()メソッドが必要です。
例24-9 データ・バインド・コントロールへのデータの提供
public class ContactInfoDataSource
{
public ICollection Data
{
set { m_col = value; }
}
public ICollection GetData()
{
return m_col;
}
public ContactInfoDataSource()
{}
public ContactInfoDataSource(ICollection col)
{
ArrayList results = new ArrayList();
if (col is INamedCache)
{
INamedCache cache = col as INamedCache;
foreach (ContactInfo contactInfo in cache.Values)
{
results.Add(contactInfo);
}
}
else if (col is ArrayList)
{
foreach (DictionaryEntry entry in col)
{
results.Add(entry.Value);
}
}
Data = results;
}
private ICollection m_col = null;
}
データをデータ・バインド・コントロールに提供する内部オブジェクトを作成するイベント・ハンドラを追加します。これを例24-10に示します。
例24-10 データをデータ・バインド・コントロールに提供するイベント・ハンドラ
protected void dsContact_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
ContactInfoDataSource cds = new ContactInfoDataSource(Contacts == null ? ContactCache : Contacts);
e.ObjectInstance = cds;
}
例24-11のメソッドは、ページに表示されたGridViewをリフレッシュし、合計ラベルlblTotalをリフレッシュして、キャッシュ内にオブジェクトがある場合にbtnClearおよびすべてのボタンを表示します。
例24-11 グリッド・ビューをリフレッシュするメソッド
private void RefreshDataGridAndRenderPage()
{
gridCache.DataBind();
int totalObjects = (Contacts == null ? ContactCache.Count : Contacts.Count);
lblTotal.Text = "Total objects: " + totalObjects;
if (ContactCache.Count > 0)
{
lblTotal.Visible = btnClear.Visible = true;
lblSearch.Visible = listColumnNames.Visible = lblFor.Visible = txtFilterCriteria.Visible = btnSearch.Visible = true;
}
else
{
lblTotal.Visible = btnClear.Visible = false;
lblSearch.Visible = listColumnNames.Visible = lblFor.Visible = txtFilterCriteria.Visible = btnSearch.Visible = false;
}
btnClearFilter.Visible = (Contacts != null);
}
例24-12のメソッドは、ページ・ロード・イベントを処理します。RequestにgetKey値が存在する場合は、指定キーにマップされた値がキャッシュから取得され、そのプロパティが適切なフィールドに移入されます。RequestにremoveKey値が存在する場合は、指定キーにマップされた値がキャッシュから削除されます。
例24-12 ページ・ロード・イベントを処理するメソッド
protected void Page_Load(object sender, EventArgs e)
{
if (Request["getKey"] != null)
{
FindObjectInCache(Request["getKey"]);
}
else if (Request["removeKey"] != null)
{
CacheFactory.Log("Object with key [" + Request["removeKey"] + "] has been removed from cache.", CacheFactory.LogLevel.Info);
ContactCache.Remove(Request["removeKey"]);
}
RefreshDataGridAndRenderPage();
PopulateFilterColumns();
}
例24-13に示すヘルパー・メソッドは、指定されたキーに従ってContactInfoオブジェクトをキャッシュから取得します。
例24-13 指定キーによるビジネス・オブジェクトのキャッシュからの取得
private void FindObjectInCache(object key)
{
ContactInfo contactInfo = (ContactInfo)ContactCache[key];
if (contactInfo == null)
{
contactInfo = new ContactInfo();
}
txtName.Text = key as String;
txtStreet.Text = contactInfo.Street;
txtCity.Text = contactInfo.City;
txtState.Text = contactInfo.State;
txtZip.Text = contactInfo.Zip;
}
例24-14は、btnSaveボタンのイベント・ハンドラを示しています。
例24-14 「Save」ボタンのイベント・ハンドラ
protected void btnSave_Click(object sender, EventArgs e)
{
String name = txtName.Text;
if (name != null && name != "")
{
ContactInfo contactInfo = new ContactInfo(name,
txtStreet.Text,
txtCity.Text,
txtState.Text,
txtZip.Text);
ContactCache.Insert(name, contactInfo);
CacheFactory.Log("Object with key [" + name + "] has been inserted into cache.", CacheFactory.LogLevel.Info);
RefreshDataGridAndRenderPage();
}
}
例24-15は、btnClearボタンのイベント・ハンドラを示しています。
例24-15 「Clear」ボタンのイベント・ハンドラ
protected void btnClear_Click(object sender, EventArgs e)
{
NameValidator.Enabled = false;
ContactCache.Clear();
RefreshDataGridAndRenderPage();
NameValidator.Enabled = true;
}
例24-16は、btnSearchボタンのイベント・ハンドラを示しています。
例24-16 「Search」ボタンのイベント・ハンドラ
protected void btnSearch_Click(object sender, EventArgs e)
{
NameValidator.Enabled = false;
String filterBy = listColumnNames.Items[listColumnNames.SelectedIndex].Text;
String filterCriteria = txtFilterCriteria.Text.Trim();
if (filterCriteria != "")
{
IValueExtractor extractor = new ReflectionExtractor("get" + filterBy);
IFilter filter = new LikeFilter(extractor, filterCriteria, '\\', true);
ICollection results = ContactCache.GetEntries(filter);
Contacts = results;
dsContact = new ObjectDataSource();
RefreshDataGridAndRenderPage();
}
NameValidator.Enabled = true;
}
例24-17は、btnClearFilterボタンのイベント・ハンドラを示しています。
例24-17 「Clear Filter」ボタンのイベント・ハンドラ
protected void btnClearFilter_Click(object sender, EventArgs e)
{
NameValidator.Enabled = false;
Contacts = null;
dsContact = new ObjectDataSource();
RefreshDataGridAndRenderPage();
NameValidator.Enabled = true;
}
最後に適切なエラー・メッセージを指定して、プロジェクトにConnectionError.htmlページを追加します。