この章は、トランザクションの実行に必要な次の各項で構成されています。
.NETクライアントは、トランザクション・フレームワークAPIを利用することによって、トランザクション内でキャッシュ操作を実行します。トランザクションAPIは、.NETでネイティブではサポートされていないため、入力プロセッサ内で使用する必要があります。入力プロセッサはJavaでクラスタ上に実装され、入力プロセッサのスタブ・クラスはC#でクライアント上に実装されます。いずれのクラスでも、POFを使用して、JavaとC#の間でシリアライズを行います。
例22-1 は、トランザクションAPIを使用してトランザクション内で単純なupdate操作を実行する入力プロセッサを示しています。実行時には、Coherenceプロキシ・サーバーのクラスパス上にクラスを配置する必要があります。
例22-1 Extendクライアント・トランザクション用の入力プロセッサ
package coherence.tests;
import com.tangosol.coherence.transaction.Connection;
import com.tangosol.coherence.transaction.ConnectionFactory;
import com.tangosol.coherence.transaction.DefaultConnectionFactory;
import com.tangosol.coherence.transaction.OptimisticNamedCache;
import
com.tangosol.coherence.transaction.exception.PredicateFailedException;
import com.tangosol.coherence.transaction.exception.RollbackException;
import
com.tangosol.coherence.transaction.exception.UnableToAcquireLockException;
import com.tangosol.util.Filter;
import com.tangosol.util.InvocableMap;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.EqualsFilter;
import com.tangosol.util.processor.AbstractProcessor;
public class MyTxProcessor extends AbstractProcessor implements PortableObject
{
public Object process(InvocableMap.Entry entry)
{
// obtain a connection and transaction cache
ConnectionFactory connFactory = new DefaultConnectionFactory();
Connection conn = connFactory.createConnection("TransactionalCache");
OptimisticNamedCache cache = conn.getNamedCache("MyTxCache");
conn.setAutoCommit(false);
// get a value for an existing entry
String sValue = (String) cache.get("existingEntry");
// create predicate filter
Filter predicate = new EqualsFilter(IdentityExtractor.INSTANCE, sValue);
try
{
// update the previously obtained value
cache.update("existingEntry", "newValue", predicate);
}
catch (PredicateFailedException e)
{
// value was updated after it was read
conn.rollback();
return false;
}
catch (UnableToAcquireLockException e)
{
// row is being updated by another tranaction
conn.rollback();
return false;
}
try
{
conn.commit();
}
catch (RollbackException e)
{
// transaction was rolled back
return false;
}
return true;
}
public void readExternal(PofReader in)
throws IOException
{
}
public void writeExternal(PofWriter out)
throws IOException
{
}
}
入力プロセッサのスタブ・クラスを使用すると、クライアントはクラスタ上でトランザクション入力プロセッサを利用できます。スタブ・クラスはC#で実装され、POFを使用してシリアライズを行います。POFを使用することにより、C#とJavaの間で入力プロセッサをシリアライズできます。入力プロセッサのスタブ・クラスにはトランザクション・ロジックは必要ありません。これはトランザクション入力プロセッサのスケルトンです。.NETでPOFを使用する際の詳細は、「統合オブジェクトの構築(.NET)」を参照してください。
例22-2 は、例22-1 で作成したトランザクション入力プロセッサの入力プロセッサ・スタブ・クラスを示しています。
例22-2 トランザクション入力プロセッサの.NETスタブ・クラス
using Tangosol.IO.Pof;
using Tangosol.Net.Cache;
using Tangosol.Util.Processor;
namespace Coherence.Tests{
public class MyTxProcessor : AbstractProcessor, IPortableObject
{
public MyTxProcessor()
{
}
public override object Process(IInvocableCacheEntry entry)
{
return null;
}
public void ReadExternal(IPofReader reader)
{
}
public void WriteExternal(IPofWriter writer)
{
}
}
}
カスタム・ユーザー・タイプは、Javaトランザクション入力プロセッサに関してはクラスタ側のPOF構成ファイルで、クライアント・スタブに関してはクライアント側のPOF構成ファイルで登録する必要があります。両方の登録で、同じタイプIDを使用する必要があります。次の例は、例22-1 で作成したMyTxProcessorクラスと、例22-2 で作成したクライアント・スタブ・クラスのそれぞれの登録方法を示しています。
クラスタ側のPOF構成:
<?xml version="1.0"?>
<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config
coherence-pof-config.xsd">
<user-type-list>
<include>coherence-pof-config.xml</include>
<include>txn-pof-config.xml</include>
<user-type>
<type-id>1599</type-id>
<class-name>coherence.tests.MyTxProcessor</class-name>
</user-type>
</user-type-list>
</pof-config>
クライアント側のPOF構成:
<?xml version="1.0"?>
<pof-config xmlns="http://schemas.tangosol.com/pof"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/pof
assembly://Coherence/Tangosol.Config/pof-config.xsd">
<user-type-list>
<include>coherence-pof-config.xml</include>
<user-type>
<type-id>1599</type-id>
<class-name>Coherence.Tests.MyTxProcessor</class-name>
</user-type>
</user-type-list>
</pof-config>
トランザクションを実行するには、クラスタ側のキャッシュ構成ファイルでトランザクション・キャッシュを定義する必要があります。トランザクション・キャッシュは、トランザクション・フレームワークでトランザクション保証を行うために使用します。トランザクション・キャッシュの詳細は、『Oracle Coherenceでのアプリケーションの開発』のトランザクション・キャッシュの定義に関する項を参照してください。
次の例では、MyTxCacheという名前のトランザクション・キャッシュを作成します。これは、例22-1 で入力プロセッサによって使用されていたキャッシュ名です。この構成には、リモート・クライアントから入力プロセッサを実行する際に必要なプロキシ・スキームと分散キャッシュ・スキームも含まれています。プロキシは、ポート7077のlocalhostでクライアントのTCP/IP接続を受け入れるように構成します。Coherence*Extend使用時にクラスタ側のキャッシュを構成する方法の詳細は、「拡張プロキシの構成」を参照してください。
<?xml version='1.0'?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>MyTxCache</cache-name>
<scheme-name>example-transactional</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>example-distributed</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<transactional-scheme>
<scheme-name>example-transactional</scheme-name>
<service-name>TransactionalCache</service-name>
<thread-count-min>2</thread-count-min>
<thread-count-max>10</thread-count-max>
<high-units>15M</high-units>
<task-timeout>0</task-timeout>
<autostart>true</autostart>
</transactional-scheme>
<distributed-scheme>
<scheme-name>example-distributed</scheme-name>
<service-name>DistributedCache</service-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>
クラスタのプロキシに接続してトランザクション入力プロセッサを実行するには、リモート・クライアントにリモート・キャッシュが必要です。リモート・キャッシュは、クライアント側のキャッシュ構成ファイルで定義します。クライアント側のキャッシュを構成する方法の詳細は、「拡張プロキシの構成」を参照してください。
次の例では、リモート・キャッシュをポート7077のlocalhostに配置されているプロキシに接続するように構成します。また、リモート・キャッシュの名前(dist-example)はトランザクション入力プロセッサの開始時に使用されるクラスタ側のキャッシュの名前と一致している必要があります。
<?xml version='1.0'?>
<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>extend</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>7077</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>
クライアントで入力プロセッサのスタブ・クラスを起動する方法は、入力プロセッサを起動する方法と同じです。ただし、実行時に、クラスタ側の入力プロセッサがクラスタ上で起動されます。起動がJavaクラスに委任されたことは、クライアント側では認識されません。次の例は、入力プロセッサのスタブ・クラスを使用して、結果的に例22-1 で作成したトランザクション入力プロセッサを起動するクライアントを示しています。
INamedCache cache = CacheFactory.GetCache("dist-example");
object result = cache.Invoke( "AnyKey", new MyTxProcessor());
Console.Out.WriteLine("Result of extend transaction execution: " + result );