この章の内容は次のとおりです。
親トピック: キャッシュの使用
次の例では、RunNamespaceHandler
ネームスペース・ハンドラ・クラスに関連付けられたrun
ネームスペースを宣言して、キャッシュ構成ファイルを拡張します。実行時に、このハンドラ・クラスは<run:runnable>
要素とその属性を処理し、必要に応じてクラスタ・メンバー上でロジックを実行します。
<?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" xmlns:run="class://com.examples.RunNamespaceHandler"> <run:runnable classname="MyRunnable" every="10m"/> ... </cache-config>
通常は、キャッシュ構成ファイルを拡張して、アプリケーションがカスタムの初期化、バックグラウンド・タスクを実行したり、クラスタ内のキャッシュのモニタリングおよび保守を実行できるようにします。たとえば、アプリケーションで次のことを実行できます。
ドメイン固有のキャッシュ・エントリ索引の構築
キャッシュされている情報の事前ロード
クラスタへの構成のロード
クラスタに対するバックグラウンド・タスクの実行またはスケジュール
外部システムとの統合
キャッシュ構成ファイルを拡張すると、共通で統合的な構成の場所がアプリケーションに提供されます。また、アプリケーション・ロジックは、可用性およびスケーラビリティに優れた環境であるクラスタに埋め込まれて管理され、必要な場合は、障害が発生したアプリケーション・ロジックの自動リカバリを提供することもできます。
親トピック: キャッシュ構成ファイルの拡張
xmlns
の宣言が存在することを確認するチェックが実行されます。キャッシュ構成ファイル内でエラーが発生した場合、Coherenceのメンバーは起動に失敗します。 次の例では、接頭辞ex
を使用したネームスペースを宣言しています。
<?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"
xmlns:ex="URI">
...
ネームスペースのURI値は、class://FullyQualifiedClassName
の形式である必要があります。正しくない形式が指定された場合は、障害が発生し、Coherenceのメンバーは起動に失敗します。宣言で指定されたハンドラ・クラスは、NamespaceHandler
インタフェースを実装するクラスである必要があります。ネームスペース・ハンドラの作成を参照してください。
ハンドラ・クラスは、関連付けられたXML要素および属性がキャッシュ構成ファイル内に出現したときに処理できる必要があります。さらに具体的に言うと、キャッシュ構成のXML DOMの処理中にネームスペース内に出現したすべてのXML要素および属性は、関連付けられたハンドラ・インスタンスに渡されて処理されます。次の例では、MyNamespaceHandler
を使用して、ex
のネームスペース接頭辞を使用するすべての要素を処理します。
<?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" xmlns:ex="class://MyNamespaceHandler"> <ex:myelement/> ...
XMLネームスペースの宣言のガイドライン
XMLネームスペースを宣言する際は、次のガイドラインを使用します。
URIクラスはNamespaceHandler
インタフェースを実装する必要があります。そうしない場合、キャッシュ構成ファイルの処理は失敗します。
XML要素および属性で、宣言されていないネームスペース接頭辞を使用しないでください。そうしない場合、キャッシュ構成ファイルの処理は失敗します。
Coherenceの要素および属性に使用されるデフォルト・ハンドラはオーバーライドできません。そうした場合、キャッシュ構成ファイルの処理は失敗します。デフォルトのネームスペースはCoherence用に予約されています。
親トピック: キャッシュ構成ファイルの拡張
NamespaceHandler
インタフェースを実装する必要があります。通常、ネームスペース・ハンドラは、複雑なネームスペースの処理を簡略化できる便利なメソッドを提供する基本のAbstractNamespaceHandler
実装クラスを拡張します。この項で説明するこれらのAPIはいずれもcom.tangosol.config.xml
パッケージに含まれています。この項には次のトピックが含まれます:
ネームスペース・ハンドラは、XMLネームスペース内で使用される要素および属性を処理します。ネームスペース・ハンドラは、NamespaceHandler
インタフェースを直接実装できます。このインタフェースは、DocumentPreprocessor
、ElementProcessor
およびAttributeProcessor
の各インタフェースに依存します。XMLの処理は、ProcessingContext
インタフェースで定義された処理コンテキスト内で実行されます。
ネームスペースに出現する要素および属性は、プロセッサ実装で処理する必要があります。要素および属性のプロセッサは、処理、解析および型変換のロジックを担当します。ドキュメント・プロセッサは、必要であれば処理する前に要素を変化させるために使用します。
例18-1に、基本的なNamespaceHandler
の実装を示します。GreetingNamespaceHandler
実装は、内部クラスとして含まれるElementProcessor
実装(MessageProcessor)
を使用して、<message>
要素を処理します。たとえば、次のXMLがあると想定します。
<?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" xmlns:ex="class://com.examples.GreetingNamespaceHandler"> <ex:message>hello</ex:message> ...
例18-1 NamespaceHandlerインタフェースを使用したハンドラの実装
import com.tangosol.config.ConfigurationException; import com.tangosol.config.xml.AttributeProcessor; import com.tangosol.config.xml.DocumentPreprocessor; import com.tangosol.config.xml.ElementProcessor; import com.tangosol.config.xml.NamespaceHandler; import com.tangosol.config.xml.ProcessingContext; import com.tangosol.run.xml.XmlAttribute; import com.tangosol.run.xml.XmlElement; import java.net.URI; public class GreetingNamespaceHandler implements NamespaceHandler { public AttributeProcessor getAttributeProcessor(XmlAttribute xmlAttribute) { return null; } public DocumentPreprocessor getDocumentPreprocessor() { return null; } public ElementProcessor getElementProcessor(XmlElement xmlElement) { if (xmlElement.getName().equals("ex:message")) { MessageProcessor mp = new MessageProcessor(); return mp; } else { throw new RuntimeException("Unknown element type " + xmlElement.getQualifiedName()); } } public void onEndNamespace(ProcessingContext processingContext, XmlElement xmlElement, String string, URI uRI) { } public void onStartNamespace(ProcessingContext processingContext, XmlElement xmlElement, String string, URI uRI) { } public class MessageProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { System.out.println("Greeting is: " + xmlElement.getString()); return null; } } }
前述のクラスは、<ex:message>
要素の内容を処理します。ただし、異なるタイプの要素が出現してもそれらは区別されません。デフォルトのXMLネームスペース内に出現したすべての要素は、同じprocess
メソッドに渡されます。各タイプのXML要素を処理するには、process
メソッド内に条件文が必要です。単純なXMLコンテンツの場合はこのテクニックで十分ですが、複雑なXMLコンテンツでは多くの条件文が必要となって、非常にわかりにくくなることがあります。より宣言的な方法は、AbstractNamespaceHandler
クラスで提供されます。
ネームスペース・ハンドラのコールバック・メソッド
NamespaceHandler
インタフェースには、onStartNamespace
およびonEndNamespace
のコールバック・メソッドが用意されています。これらのメソッドを使用すると、キャッシュ構成ファイル内で最初および最後に出現したネームスペースに対して追加の処理を実行できます。
親トピック: ネームスペース・ハンドラの作成
AbstractNamespaceHandler
クラスでは、便利で拡張可能なNamespaceHandler
、ElementProcessor
およびAttributeProcessor
の各インタフェースのベース実装と、特定の名前が付いた要素および属性のためのプロセッサを登録するメカニズムが提供されます。このクラスは要素および属性の処理を容易化し、多くの場合、要素および属性のプロセッサのインタフェースを直接実装する必要性をなくすことができます。
この項では、次の項目について説明します。
AbstractNamespaceHandler
クラスには、要素および属性のプロセッサを宣言で登録するメソッドが用意されています。このメソッドにより、要素の名前および型をチェックする必要がなくなります。明示的な登録と暗黙的な登録の2つの登録メカニズムがあります。
明示的なプロセッサ登録
明示的なプロセッサ登録を使用するには、サブクラス・コンストラクタ内でregisterProcessor
メソッドをコールし、要素と属性の両方のプロセッサを手動で登録します。例18-2では、例18-1を再実装し、registerProcessor
メソッドを使用してMessageProcessor
要素のプロセッサを登録します。
例18-2 明示的な登録を使用したAbstractNamespaceHandlerの実装
import com.tangosol.config.ConfigurationException; import com.tangosol.config.xml.AbstractNamespaceHandler; import com.tangosol.config.xml.ElementProcessor; import com.tangosol.config.xml.ProcessingContext; import com.tangosol.run.xml.XmlElement; public class GreetingNamespaceHandler extends AbstractNamespaceHandler { public GreetingNamespaceHandler() { registerProcessor("message", new MessageProcessor()); } public class MessageProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { System.out.println("Greeting is: " + xmlElement.getString()); return null; } } }
暗黙的なプロセッサ登録
暗黙的なプロセッサ登録を使用するには、プロセッサ・クラスに@XmlSimpleName
注釈を付けます。これらのプロセッサは、関連付けられたネームスペース内で使用するように自動的に登録されます。@XmlSimpleName
注釈は、XML DOMの処理中に出現したXMLコンテンツの処理にどのプロセッサ実装が適切であるかを判断するために使用されます。定義済のプロセッサが存在しないXML要素または属性が出現した場合は、onUnknownElement
またはonUnknownAttribute
のメソッドがそれぞれコールされます。これらのメソッドにより、可能な場合は修正処置を実行できます。処理中に不明なXMLコンテンツが見つかった場合、デフォルトでは、ConfigurationException
例外が発生します。
例18-3では、例18-1を再実装し、@XmlSimpleName
注釈を使用してMessageProcessor
要素のプロセッサを登録します。
例18-3 暗黙的な登録を使用したAbstractNamespaceHandlerの実装
import com.tangosol.config.ConfigurationException; import com.tangosol.config.xml.AbstractNamespaceHandler; import com.tangosol.config.xml.ElementProcessor; import com.tangosol.config.xml.ProcessingContext; import com.tangosol.config.xml.XmlSimpleName; import com.tangosol.run.xml.XmlElement; public class GreetingNamespaceHandler extends AbstractNamespaceHandler { public GreetingNamespaceHandler() { } @XmlSimpleName("message") public class MessageProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { System.out.println("Greeting is: " + xmlElement.getString()); return null; } } }
親トピック: ネームスペース・ハンドラ抽象クラスの拡張
要素および属性のプロセッサは、XMLコンテンツの処理を手動でコーディングするために使用されます。ただし、複雑なネームスペースの場合、これは繰返しの作業になることがあります。この作業を自動化するため、ProcessingContext.inject
メソッドは、特定のXML要素に使用できる識別可能なsetterメソッドと値に基づいて、強い型付き値を指定されたオブジェクトに注入できます。
たとえば、次のXMLがあるとします。
<ex:message> <ex:english>hello</ex:english> </ex:message>
要素プロセッサを使用して、<english>
要素の処理を手動でコーディングできます。
import com.tangosol.config.ConfigurationException; import com.tangosol.config.xml.AbstractNamespaceHandler; import com.tangosol.config.xml.ElementProcessor; import com.tangosol.config.xml.ProcessingContext; import com.tangosol.config.xml.XmlSimpleName; import com.tangosol.run.xml.XmlElement; public class GreetingNamespaceHandler extends AbstractNamespaceHandler { public GreetingNamespaceHandler() { } @XmlSimpleName("message") public class MessageProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { String engMsg = processingContext.getMandatoryProperty("english", String.class, xmlElement); Message message = new Message(); message.setEnglish(engMsg); System.out.println("Greeting is: "+ message.getEnglish()); return message; } } }
別の方法として、inject
メソッドで処理を実行できます。
@XmlSimpleName("message") public class MessageProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { return processingContext.inject(new Message(), xmlElement); } }
inject
メソッドは、構成されるオブジェクトはJava beanの命名規則に従うという想定のもとにJavaリフレクションを使用します。最初に、inject
メソッドは、Java beanでコールできる適切なsetterメソッドを識別します。通常、これは、@Injectable
注釈が付けられたsetterメソッドを特定することによって行います。次に、setterメソッドで必要な適切な値の型を判別します。最後に、指定されたXmlElement
を使用して検索、解析、変換、強制変換し、その後に使用可能なsetterメソッドを使用してオブジェクト内で適切な型付き値を設定します。inject
メソッドでは、プリミティブ、列挙、書式設定された値、複雑なユーザー定義の型、およびコレクション型(セット、リストおよびマップ)をサポートしています。inject
メソッドが失敗した場合は、ConfigurationException
例外がスローされます。たとえば、予想される型に値を形式設定するのに失敗した場合などです。
次の例は、前述の例用のMessage
クラスを示しており、inject
メソッドによる注入をサポートしています。
import com.tangosol.config.annotation.Injectable; public class Message { private String m_sEnglish = "a greeting"; public Message() { } @Injectable("english") public void setEnglish (String sEnglish) { m_sEnglish = sEnglish; } public String getEnglish() { return m_sEnglish; } }
ノート:
@Injectable
注釈プロパティが省略されている場合、inject
メソッドはsetterメソッドのJava bean名を使用しようとします。前述の例の場合、@injectable("")
はenglish
を使用することになります。
通常、要素および属性のプロセッサは、inject
メソッドを使用する場合と同じパターンに従います。たとえば:
@XmlSimpleName("element") public class XProcessor implements ElementProcessor { public Object process(ProcessingContext processingContext, XmlElement xmlElement) throws ConfigurationException { return processingContext.inject(new X(), xmlElement); } }
このような実装の宣言および登録は、要素および属性のそれぞれにつき、registerElementType
およびregisterAttributeType
メソッドを使用して自動化できます。これらのメソッドはAbstractNamespaceHandler
クラスで使用可能で、多くの場合はAbstractNamespaceHandler
サブクラスのコンストラクタで使用されます。次の例はregisterElementType
メソッドの使用を示しており、この場合、プロセッサの実装は必要ありません。
ノート:
型ベースのクラスの登録をサポートするには、指定されたクラスで引数なしのコンストラクタを用意する必要があります。
import com.tangosol.config.xml.AbstractNamespaceHandler; public class GreetingNamespaceHandler extends AbstractNamespaceHandler { public GreetingNamespaceHandler() { registerElementType("message", Message.class); } }
親トピック: ネームスペース・ハンドラ抽象クラスの拡張
<class-scheme>
または<instance>
要素を使用してリソースを静的に作成する必要性をなくすためによく使用されます。JNDIリソース・ネームスペース・ハンドラは、Github(https://github.com/coherence-community/coherence-incubator
)でホストされているCoherence Incubatorプロジェクトからここに複製されています。Incubatorには、いくつかのネームスペース・ハンドラの実装が含まれており、それらは共通パッケージ・モジュール内で見つかります。
この項には次のトピックが含まれます:
JNDIリソース・ネームスペース・ハンドラは、実行時に、キャッシュ構成ファイル内に見つかる<resource>
要素を処理するために使用されます。このハンドラは、AbstractNamespaceHandler
クラスを拡張し、<resource>
要素のためのJndiBasedParameterizedBuilder
クラスを登録します。次の例は、ネームスペース・ハンドラの定義を示しています。
import com.tangosol.coherence.config.builder.ParameterizedBuilder; import com.tangosol.config.xml.AbstractNamespaceHandler; public class JndiNamespaceHandler extends AbstractNamespaceHandler { public JndiNamespaceHandler() { registerElementType("resource", JndiBasedParameterizedBuilder.class); } }
JndiBasedParameterizedBuilder
クラスは、<resource-name>
および<init-parms>
要素にそれぞれ指定された名前と初期化パラメータを使用して、JNDIコンテキストのルックアップを実行し、オブジェクトを特定して作成します。これらの要素のsetterメソッド(setResourceNameExpression
およびsetParameterList
)は、@Injectable
注釈を使用して、キャッシュ構成ファイル内に構成された値を引き渡します。
import com.tangosol.coherence.config.ParameterList; import com.tangosol.coherence.config.SimpleParameterList; import com.tangosol.coherence.config.builder.ParameterizedBuilder; import com.tangosol.coherence.config.builder.ParameterizedBuilder. ReflectionSupport; import com.tangosol.config.annotation.Injectable; import com.tangosol.config.expression.Expression; import com.tangosol.config.expression.LiteralExpression; import com.tangosol.config.expression.Parameter; import com.tangosol.config.expression.ParameterResolver; import com.tangosol.util.Base; import java.util.Hashtable; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InitialContext; import javax.naming.NamingException; public class JndiBasedParameterizedBuilder implements ParameterizedBuilder<Object>, ReflectionSupport { private static final Logger logger = Logger.getLogger(JndiBasedParameterizedBuilder.class.getName()); private Expression<String> m_exprResourceName; private ParameterList m_parameterList; public JndiBasedParameterizedBuilder() { m_exprResourceName = new LiteralExpression<String>(""); m_parameterList = new SimpleParameterList(); } public Expression<String> getResourceNameExpression() { return m_exprResourceName; } @Injectable("resource-name") public void setResourceNameExpression(Expression<String> exprResourceName) { m_exprResourceName = exprResourceName; } public ParameterList getParameterList() { return m_parameterList; } @Injectable("init-params") public void setParameterList(ParameterList parameterList) { m_parameterList = parameterList; } public boolean realizes(Class<?> clazz, ParameterResolver parameterResolver, ClassLoader classLoader) { return clazz.isAssignableFrom(realize(parameterResolver, classLoader, null).getClass()); } public Object realize(ParameterResolver parameterResolver, ClassLoader classLoader, ParameterList parameterList) { InitialContext initialContext; try { String sResourceName = m_exprResourceName.evaluate(parameterResolver); Hashtable<String, Object> env = new Hashtable<String, Object>(); for (Parameter parameter : m_parameterList) { env.put(parameter.getName(), parameter.evaluate(parameterResolver)); } initialContext = new InitialContext(env); if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Looking up {0} using JNDI with the environment {1}", new Object[] {sResourceName, env}); } Object resource = initialContext.lookup(sResourceName); if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Found {0} using JNDI", resource); } return resource; } catch (NamingException e) { throw Base.ensureRuntimeException(e, "Unable to resolve the JNDI resource: " + m_exprResourceName.toString()); } } public String toString() { return String.format("%s{resourceName=%s, parameters=%s}", this.getClass().getName(), m_exprResourceName, m_parameterList); } }
親トピック: 例: JNDIリソース・ネームスペース・ハンドラ
JNDIリソース・ネームスペース・ハンドラは、キャッシュ構成ファイル内で宣言する必要があります。ハンドラ・クラスへのURIを指定し、ネームスペースの接頭辞を割り当てて、ネームスペースを宣言します。任意の接頭辞を使用できます。次の例では、jndi
を接頭辞として使用しています。
<?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" xmlns:jndi="class://com.examples.JndiNamespaceHandler"> ...
親トピック: 例: JNDIリソース・ネームスペース・ハンドラ
アプリケーションでリソースを特定して作成する必要がある場合はいつでもJNDIリソース・ネームスペース・ハンドラを使用できます。また、<class-scheme>
または<instance>
要素を使用してカスタム実装を定義する場合、ネームスペースを使用できます。ハンドラの実装に基づいて、<resource>
および<resource-name>
要素は必須、<init-params>
要素はオプションです。
次の例では、分散スキームを定義する際にキャッシュ・ストアにJNDIリソースを使用します。
<?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" xmlns:jndi="class://com.examples.JndiNamespaceHandler"> ... <caching-schemes> <distributed-scheme> <scheme-name>distributed-rwbm</scheme-name> <backing-map-scheme> <read-write-backing-map-scheme> <internal-cache-scheme> <local-scheme/> </internal-cache-scheme> <cachestore-scheme> <class-scheme> <jndi:resource> <jndi:resource-name>MyCacheStore</jndi:resource-name> <init-params> <init-param> <param-type>java.lang.String</param-type> <param-value>{cache-name}</param-value> </init-param> </init-params> </jndi:resource> </class-scheme> </cachestore-scheme> </read-write-backing-map-scheme> </backing-map-scheme> </distributed-scheme> <caching-schemes> </cache-config>
次の例では、JNDIリソースを使用してDNSレコードを解決します。
<?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" xmlns:jndi="class://com.examples.JndiNamespaceHandler"> ... <jndi:resource> <jndi:resource-name>dns:///www.oracle.com</jndi:resource-name> </jndi:resource>
次の例では、JNDIリソースを使用してJMS接続ファクトリを解決します。
<?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" xmlns:jndi="class://com.examples.JndiNamespaceHandler"> ... <jndi:resource> <jndi:resource-name>ConnectionFactory</jndi:resource-name> <init-params> <init-param> <param-name>java.naming.factory.initial</param-name> <param-value>org.apache.activemq.jndi.ActiveMQInitialContextFactory </param-value> </init-param> <init-param> <param-name>java.naming.provider.url</param-name> <param-value system-property="java.naming.provider.url"></param-value> </init-param> </init-params> </jndi:resource>
親トピック: 例: JNDIリソース・ネームスペース・ハンドラ