48 多言語Coherenceアプリケーションの開発
この機能を使用するには、Oracle GraalVM Enterprise EditionとともにOracle Coherenceをインストールする必要があります。『GraalVM Enterprise EditionでのOracle WebLogic ServerおよびCoherenceの実行』を参照してください。
この章の内容は次のとおりです。
- JavaScriptプロジェクトの設定
Coherenceの多言語機能のデモを行うには、CoherenceキャッシュにJavaオブジェクトを移入し、JavaScriptを使用してそれらのキャッシュ・エントリにアクセスし、処理する単純なJavaアプリケーションを開発する必要があります。 - アプリケーション・クラスの実装
アプリケーション・クラスを実装するには、Coherenceキャッシュ内のオブジェクト・エントリにアクセスして更新できるサーバー側のJavaScriptオブジェクトを開発する必要があります。 - 依存関係のインストールおよび使用
リアルタイム環境では、日時操作にlodash
モジュールまたはmoment
モジュールを使用できます。 - マルチソース・プロジェクトの作成
複雑なプロジェクトでは、クラスを複数のモジュール(ソース・ファイル)に分割できます。複数のソース・ファイルがある場合は、ソース・ファイルをトランスパイルして出力ディレクトリにバンドルできるように、そのソース・ファイルについてwebpack
に指示する必要があります。 - JavaScriptモジュールのビルドとパッケージ化
JavaScriptモジュールをビルドし、それらの依存関係とともにパッケージ化できます。 - JavaScriptモジュールの自動事前ロード
記憶域が有効なCoherenceメンバーが起動されると、scripts/js
ディレクトリ(クラスパス内)の下に存在するすべてのJavaScriptファイルが自動的に評価され、内部マップに登録されます。 - クラスパスの設定および記憶域が有効なサーバーの起動
クラスパスを設定し、記憶域が有効なサーバーを起動するには、次のコマンドを実行します。 - JavaアプリケーションでのJavaScriptオブジェクトの使用
JavaScriptオブジェクトを使用するJavaクラスを記述することで、多言語アプリケーションの作成を完了する必要があります。
親トピック: 多言語Coherenceアプリケーションの開発および実行
JavaScriptプロジェクトの設定
Coherenceサーバー側のオブジェクトを含むJavaScriptモジュールをパッケージ化して、記憶域が有効なノードにデプロイする必要があります。最初に、多言語アプリケーションの開発およびパッケージ化に役立つ必要なツールおよびプロジェクト構造を設定します。
この項には次のトピックが含まれます:
webpackおよびwebpack-cliのインストール
webpackおよびwebpack-cliをインストールするには、Node.js
(12.6以上)およびノード・パッケージ・マネージャ(npm)がインストールされている必要があります。
親トピック: JavaScriptプロジェクトの設定
アプリケーション・クラスの実装
アプリケーション・クラスの実装例では、firstName
、lastName
、age
、gender
などの属性を持つPerson
オブジェクトがキャッシュに移入されることを想定します。
この項には次のトピックが含まれます:
フィルタの使用
NamedCache
には、エントリのキーに基づいてエントリにアクセスできるget()
およびput()
メソッドがあります。ただし、多くの場合、キー以外の属性に基づいてエントリを取得する必要があります。Coherenceでは、このような状況に対してフィルタ・インタフェースを定義します。
たとえば、13-19
の年齢グループで、ティーンエイジャに属するすべてのPerson
を検索するとします。これを実装する方法の1つは、すべてのエントリを取得して、年齢が13から19の間のエントリのみを選択することですが、この方法は非効率的です。Coherenceは、述語を記憶域ノードに移動する際に役立ちます。これにより、大量のデータ移動が回避されるだけでなく、記憶域ノードに対する述語のパラレル実行も可能になります。
Coherenceでは、記憶域ノードのエントリにアクセスするための組込みフィルタがいくつか提供されます。「キャッシュ内のデータの問合せ」を参照してください。
この項には次のトピックが含まれます:
フィルタ・インタフェースの使用
フィルタ・インタフェースでは、単一のメソッドevaluate(object)
が定義されます。このメソッドは、評価するオブジェクトを引数として受け取り、指定されたオブジェクトがフィルタによって定義された条件を満たす場合はtrue
を返し、指定されたオブジェクトがフィルタによって定義された条件を満たさない場合はfalse
を返します。
- 1つの引数を受け取る
evaluate
というメソッドを含むクラスを定義してエクスポートする必要があります。 obj
がフィルタで表される条件を満たす場合、evaluate(obj)
はtrue
を返す必要があります。それ以外の場合は、false
を返す必要があります。
親トピック: フィルタの使用
フィルタの実装
Personがティーンエイジャであるかどうかをチェックするフィルタを記述するには:
./src/main.js
に移動し、編集ファイルを編集して次のコンテンツを追加します:
ノート:
このファイルは、webpack.config.js
に記載されていますexport class IsTeen { // [1] evaluate(person) { // [2] return person.age >= 13 && person.age <= 19; } }
- [1]
IsTeen
というクラスを定義し、エクスポートします。 - [2] 単一のパラメータを受け取る
evaluate
というメソッドを定義します。このメソッドは、age
属性が13から19の間にあるかどうかをチェックします。
親トピック: フィルタの使用
EntryProcessorsの使用
Coherenceには、キャッシュ・エントリに対してパラレル更新を実行するのに役立つ組込みのEntryProcessors
が用意されています。「エントリ・プロセッサ・エージェントの概要」を参照してください。
すべてのlastName
属性が大文字となるように、キャッシュ・エントリ(この章で使用している例のようにPerson
オブジェクトで充填したもの)を更新する場合、すべてのエントリを取得して反復処理し、1つずつ更新して、最終的にキャッシュにライトバックする方法があります。これは非効率的な方法です。Coherenceでは、データが存在する処理ロジックをより効率的に送るアプローチが用意されているため、データ移動の必要性がなくなります。キャッシュ・エントリのパラレル更新をより効率的に実行する必要がある場合は、EntryProcessor
を使用する必要があります。
この項には次のトピックが含まれます:
EntryProcessorインタフェースの使用
EntryProcessor
は、引数として処理するキャッシュ・エントリを取得し、処理結果を返すprocess(entry)
という必須メソッドを定義します。JavaScriptでEntryProcessor
を実装するには、クラスが次のようになっている必要があります。
- 1つの引数(キャッシュ・エントリ)を受け取る
process
という名前のメソッドを使用して、エクスポートしたクラスを定義します。 process(entry)
メソッドでキャッシュ・エントリの値を変更する場合は、エントリ値を明示的に更新する必要があります。
親トピック: EntryProcessorsの使用
EntryProcessorの実装
lastName
をその大文字値に更新するEntryProcessor
を記述します。
main.js
ファイルを編集し、次のコンテンツを追加します。
export class UpperCaseProcessor { // [1] process(entry) { // [2] let person = entry.value; person.lastName = person.lastName.toUpperCase(); // [3] entry.value = person; // [4] return person.lastName; // [5] } }
- [1]
UpperCaseProcessor
というクラスを定義し、エクスポートします。 - [2] 単一のパラメータを受け取る
process()
というメソッドを定義します。処理が必要なNamedCache
エントリは、このメソッドに渡されるentry
引数を通じてアクセス可能です。 - [3] 人物の
lastName
を大文字に変換します。 - [4]
entry
を新しい値で更新します。 - [5] 更新された(大文字の)姓をプロセッサの実行結果として戻します。
親トピック: EntryProcessorsの使用
ValueExtractorsの使用
ValueExtractor
は、オブジェクトから値を抽出する場合に使用します。「問合せの概念」を参照してください。
この項には次のトピックが含まれます:
ValueExtractorインタフェースの使用
ValueExtractor
インタフェースは、extract(value)
という1つのメソッドを定義します。これは、値の抽出元となる1つの引数を受け取り、抽出された値を戻します。
親トピック: ValueExtractorsの使用
ValueExtractorの作成
Person
オブジェクトからage属性を抽出するValueExtractor
を定義するには:
ディレクトリを${PRJ_DIR}/src/main/js
に変更します。main.js
ファイルを編集し、次のコンテンツを追加します。
export class AgeExtractor { // [1] extract(value) { // [2] return value.age; // [3] } }
- [1]
AgeExtractor
というクラスを定義し、エクスポートします。 - [2] 単一のパラメータを受け取る
extract
というメソッドを定義します。 - [3]
value
のage属性を返します。
親トピック: ValueExtractorsの使用
Aggregatorの使用
Coherence Aggregator
を使用して、特定の基準に基づいて、キャッシュから単一の集計結果を取得できます。
たとえば、この章の前の例で作成したCache
内の最も古いPerson
のキーを取得します。すべてのエントリを取得し、最大年齢のPerson
を探すことができますが、ロット・データがクライアントに移動されることがわかります。Coherenceでは、部分的な結果を計算し、それらの部分的な結果を結合して単一の集計結果を取得できるAggregator
インタフェースを定義します。データ・グリッドの集計の実行を参照してください。
この項には次のトピックが含まれます:
Aggregatorインタフェースの使用
Aggregatorインタフェースでは、次のメソッドを実装する必要があります。
accumulate(entry):
すべてのメンバーに対してパラレルに実行し、単一エントリをそのメンバーの部分的な結果に累計します。このメソッドでは、部分的な結果は、エントリの1つ以上の属性を使用して計算されます。このメソッドは、特定のクラスタ・メンバーでの集計用に選択されたエントリごとに1回、Aggregatorに対して複数回呼び出されます。getPartialResult():
各メンバーからのパラレル集計の部分的な結果を戻します。combine(partialResult):
各クラスタ・メンバーから返された部分的な結果を最終結果に結合します。このメソッドでは、部分的な結果は、エントリの1つ以上の属性を使用して計算されます。このメソッドは、各クラスタ・メンバーの部分的な結果について1回ずつ、ルート集計機能インスタンスに対して複数回呼び出されます。finalizeResult():
集計の最終結果を計算し、返します。
親トピック: Aggregatorの使用
Aggregatorの記述
最も古いPerson
のキーを戻すAggregator
を定義するには、main.js
ファイルを編集して、次のコンテンツを追加します。
export class OldestPerson { constructor() { this.key = -1; this.age = 0; } accumulate(entry) { // Compare this entry's age with the result computed so far. if (entry.value.age > this.age) { this.key = entry.key; this.age = entry.value.age; } return true; } getPartialResult() { // Return the partial result accumulated / computed so far. return JSON.stringify({key:this.key, age:this.age}); } combine(partialResult) { // Compute a (possibly) new result from the perviously computed // partial result. let p = JSON.parse(partialResult); if (p.age > this.age) { this.key = p.key; this.age = p.age; } return true; } finalizeResult() { // Return the final computed result. return this.key; } }
親トピック: Aggregatorの使用
依存関係のインストールおよび使用
lodash
モジュールまたはmoment
モジュールを使用できます。npm install
を使用して依存関係をインストールする既知のアプローチを使用し、require()
関数を使用して依存関係を使用できます。
次に、lodash
モジュールの使用例を示します。
const _ = require('lodash') export class InitCaseProcessor { process(entry) { let value = entry.value; value.firstName = _.startCase(_.toLower(value.firstName)); value.lastName = _.startCase(_.toLower(value.lastName)); entry.value = value; return value.lastName; } }
lodash
モジュールをインストールするには、次のコマンドを使用します。
cd ${PRJ_DIR}/src npm install lodash
親トピック: 多言語Coherenceアプリケーションの開発
マルチソース・プロジェクトの作成
複雑なプロジェクトでは、クラスを複数のモジュール(ソース・ファイル)に分割できます。複数のソース・ファイルがある場合は、ソース・ファイルをトランスパイルして出力ディレクトリにバンドルできるように、そのソース・ファイルについてwebpack
に指示する必要があります。
フィルタおよび集計機能に個別のソース・ファイルを指定するwebpack.config.js
ファイルを次に示します。
const path = require('path'); module.exports = [ { entry: { filters: './src/filters.js', aggregators: './src/aggregators.js' } }, output: { filename: '<name>.js', path: __dirname + '/dist' library: '<name>', libraryTarget: 'commonjs2', } ]
ノート:
この例の<name>エントリを、js
ファイルの実際の名前で置き換えます。
親トピック: 多言語Coherenceアプリケーションの開発
JavaScriptモジュールの作成とパッケージ化
cd ${PRJ_DIR}
npm run build
単一ソース・プロジェクトとマルチ・ソース・プロジェクトのどちらがあるかに関係なく、「マルチソース・プロジェクトの作成」で説明したwebpack.config.js
設定ファイルを使用して、webpackはtarget/scripts/js
ディレクトリ内で1つ以上の最適化されたJavaScriptファイルをコンパイル、トランスパイルおよび作成します。target/scripts/js
ディレクトリには、JavaScriptモジュールだけでなく、すべての依存関係が含まれます。つまり、target/scripts/js directory
は自己充足的です。
親トピック: 多言語Coherenceアプリケーションの開発
JavaScriptモジュールの自動事前ロード
scripts/js
ディレクトリ(クラスパス内)の下に存在するすべてのJavaScriptファイルが自動的に評価され、内部マップに登録されます。マップ・キーはクラスのエクスポートされた名前で、マップ値はクラス・オブジェクトです。これらの名前は、対応するクラスを実行するためにscript()
APIで使用できます。
ノート:
scripts/js
の親ディレクトリがクラスパスに存在する必要があります。
クラスパスに${PRJ_DIR}/target
を追加するか、またはjarファイルのルートにscripts
ディレクトリを含むjarファイルを作成できます。
親トピック: 多言語Coherenceアプリケーションの開発
クラスパスの設定と記憶域が有効なサーバーの起動
ノート:
scripts/js
の親ディレクトリがクラスパスに存在する必要があります。事前ロードが機能するためにはスクリプト/jsの親ディレクトリがクラスパスに存在する必要があるため、新しいターミナル・ウィンドウで次のコマンドを実行して、Coherenceを起動する必要があります。
CP=${COHERENCE_HOME}/lib/coherence.jar CP=${PRJ_DIR}/target:/myapp.jar:${CP} CP=${PRJ_DIR}/target:${CP} java -cp ${CP} com.tangosol.net.DefaultCacheServer
${COHERENCE_HOME}
はCoherenceのインストール・ディレクトリです。必要な数のサーバーを実行できますが、この例では1つのサーバーを実行するだけで十分です。
ノート:
Myapp.jar
は、myapp-client
Javaプロジェクトのものです。Javaプロジェクトの作成手順は、「JavaアプリケーションでのJavaScriptオブジェクトの使用」を参照してください。この例を使用するには、このファイルをmyapp-client/target
からmyapp/target
にコピーする必要があります。
親トピック: 多言語Coherenceアプリケーションの開発
JavaアプリケーションでのJavaScriptオブジェクトの使用
この項には次のトピックが含まれます:
Javaプロジェクトの作成
前提条件:
Graal VMとmaven-3.5+がインストールされている必要があります。
Javaプロジェクトを作成するには:
- 新しいターミナル・ウィンドウを開き、新しいディレクトリを作成します。
mkdir myapp-client cd myapp-client export JAVA_PRJ_DIR=`pwd` cd ${JAVA_PRJ_DIR} mkdir -p src/main/java
- pom.xmlを作成し、次の内容をコピーします。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.oracle.coherence.example</groupId> <artifactId>myapp</artifactId> <version>1.0.0-SNAPSHOT</version> <name>Coherence Graal Demo</name> <properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> <graal.version>19.1.1</graal.version> <coherence.version>14.1.1.-2206-1</coherence.version> </properties> <dependencies> <dependency> <groupId>${coherence.groupId}</groupId> <artifactId>coherence</artifactId> <version>${coherence.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
キャッシュの移入
NamedCache
を作成して「アプリケーション・クラスの実装」で説明されているPerson
オブジェクトを移入するJavaクラスを作成する必要があります。
この項には次のトピックが含まれます:
Person Javaクラスの定義
キャッシュの移入に使用するPerson
クラスを定義するには:
cd ${JAVA_PRJ_DIR}/src/main/java mkdir -p com/oracle/coherence/example
${JAVA_PRJ_DIR}/src/main/java/com/oracle/coherence/example
ディレクトリの下にPerson.javaというファイルを作成し、次のコンテンツを貼り付けます。
package com.oracle.coherence.example; import java.io.Serializable; public class Person implements Serializable { Person() { } Person(String firstName, String lastName, String gender, int age) { m_sFirstName = firstName; m_sLastName = lastName; m_sGender = gender; m_iAge = age; } public String getLastName() { return m_sLastName; } public void setLastName(String sLastName) { m_sLastName = sLastName; } public String getFirstName() { return m_sFirstName; } public void setFirstName(String sFirstName) { m_sFirstName = sFirstName; } public String getGender() { return m_sGender; } public void setGender(String sGender) { m_sFirstName = sGender; } public int getAge() { return m_iAge; } public void setAge(int iAge) { m_iAge = iAge; } // ----- Object methods -------------------------------------------------- @Override public String toString() { return "Person{" + "first name='" + m_sFirstName + '\'' + "last name='" + m_sLastName + '\'' + ", age=" + m_iAge + ", gender='" + m_sGender + '}'; } private String m_sFirstName; private String m_sLastName; private String m_sGender; private int m_iAge; }
親トピック: キャッシュの移入
Coherenceキャッシュの移入
Coherenceキャッシュに移入するには:
${JAVA_PRJ_DIR}/src/main/java/com/oracle/coherence/example
ディレクトリの下にMyAppClient.java
というファイルを作成し、次の内容を追加します。
package com.oracle.coherence.example;
public class MyAppClient
{
public NamedCache<Integer, Person> getCache()
{
return CacheFactory.getTypedCache("DemoCache", TypeAssertion.withTypes(Integer.class, Person.class));
}
public void populateCache()
{
Map<Integer, Person> persons = new HashMap<>();
persons.put(1, new Person("Ashley", "Jackson", "Female", 84));
persons.put(2, new Person("John", "Campbell", "Male", 36));
persons.put(3, new Person("Jeffry", "Trayton", "Male", 95));
persons.put(4, new Person("Florence", "Campbell", "Female", 35));
persons.put(5, new Person("Kevin", "Kelvin", "Male", 15));
persons.put(5, new Person("Jane", "Doe", "Female", 17));
getCache().putAll(persons);
System.out.println("Populated cache with " + getCache().size() + " entries");
}
親トピック: キャッシュの移入
アプリケーションの実行
アプリケーションを実行するには、まずCoherenceサーバーを起動し、次のコードを使用してキャッシュに少数のPerson
オブジェクトを移入する必要があります。
cd ${JAVA_PRJ_DIR} mvn clean install cp -rf ${PRJ_DIR}/target/scripts ${CLIENT_PRJ_DIR}/target CP=${COHERENCE_HOME}/lib/coherence.jar CP=${PRJ_DIR}/target/myapp-client.jar:${CP} CP=${PRJ_DIR}/target:${CP} java -Dstore.storageEnabled=false -cp ${CP} com.tangosol.net.DefaultCacheServer
親トピック: キャッシュの移入
Javaからのサーバー側JavaScriptオブジェクトの起動
ここで、クライアント・アプリケーションを拡張して、サーバー側のJavaScriptオブジェクトにアクセスする必要があります。更新されたアプリケーションを実行するには、「アプリケーションの実行」を参照してください。
この項には次のトピックが含まれます:
JavaScriptフィルタの起動
JavaScriptで記述されたFilter
は、com.tangosol.util.Filters
クラスのscript()
メソッドを呼び出すことでインスタンス化できます。次のように定義されます。
public static <V> Filter<V> script(String language, String filterName, Object... args);
最初の引数は、スクリプトが実装されている言語を指定するために使用されます。JavaScriptの場合は、js
を使用します。2番目の引数はFilter
のexported
名を指定するために使用し、最後の引数(可変の数の引数)はフィルタにコンストラクタ引数を渡すために使用できます。たとえば、クラスでコンストラクタを定義する場合、使用する引数を渡すことができます。
次をMyAppClient.java
に追加します。
public void displayTeens() { getCache().getAll(Filters.script("js", "IsTeen")) // Use our "Teen Filter" .stream() .forEach(System.out::println); }
public static void main(String[] args) { MyAppClient appClient = new MyAppClient(); appClient.populateCache(); appClient.displayTeens(); }
JavaScript EntryProcessorを使用したパラレル更新の実行
JavaScriptで記述されたEntryProcessor
は、com.tangosol.util.Processors
クラスのscript()
メソッドを呼び出すことでインスタンス化できます。次のように定義されます。
public static <K, V, R> EntryProcessor<K, V, R> script(String language, String processorName, Object... args);
次をMyAppClient.java
に追加します。
public void toInitCase() { // Make Updates using our "InitCaseProcessor" getCache().invokeAll(Processors.script("js", "UpperCaseProcessor")); // Display updated entries getCache().values() .forEach(System.out::println); }
フィルタでのValueExtractorの使用
ValueExtractor
は、汎用フィルタの作成に使用されます。たとえば、BetweenFilterではValueExtractor
と2つの値を受け取り、抽出した値がこの2つの値の間にある必要があるかどうかをチェックします。
public static <T, E> ValueExtractor<T, E> script(String language, String extractorName, Object... args);
次をMyAppClient.java
に追加します。
public void getPersonsInTeens() { // Construct a BetweenFilter with our AgeExtractor BetweenFilter filter = (BetweenFilter) Filters.between( Extractors.script("js", "AgeExtractor"), 13, 19); // Retrieve entries using our filter getCache().values(filter) .forEach(System.out::println); }
Aggregatorの実行
JavaScriptで記述されたAggregator
は、com.tangosol.util.Aggregators
クラスのscript()
メソッドを呼び出すことでインスタンス化できます。
最高齢の男性や女性を見つけるには、組込み集計機能とともにOldestPerson
フィルタを使用します。
次をMyAppClient.java
に追加します。
public void oldestPersons() { int oldestMaleKey = getCache().aggregate(Filters.equal("gender", "Male"), Aggregators.script("js", "OldestPerson")); int oldestFemaleKey = getCache().aggregate(Filters.equal("gender", "Female"), Aggregators.script("js", "OldestPerson")); System.out.println("Oldest Male : " + getCache().get(oldestMaleKey)); System.out.println("Oldest Female: " + getCache().get(oldestFemaleKey)); }
完全なMyAppClient.java
ファイルを次に示します:
package com.oracle.coherence.example;
import com.tangosol.net.NamedCache;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.cache.TypeAssertion;
import com.tangosol.util.Aggregators;
import com.tangosol.util.Extractors;
import com.tangosol.util.Filters;
import com.tangosol.util.Processors;
import com.tangosol.util.filter.BetweenFilter;
import java.util.HashMap;
import java.util.Map;
public class MyAppClient
{
public NamedCache<Integer, Person> getCache()
{
return CacheFactory.getTypedCache("DemoCache", TypeAssertion.withTypes(Integer.class, Person.class));
}
public void populateCache()
{
Map<Integer, Person> persons = new HashMap<>();
persons.put(1, new Person("Ashley", "Jackson", "Female", 84));
persons.put(2, new Person("John", "Campbell", "Male", 36));
persons.put(3, new Person("Jeffry", "Trayton", "Male", 95));
persons.put(4, new Person("Florence", "Campbell", "Female", 35));
persons.put(5, new Person("Kevin", "Kelvin", "Male", 15));
persons.put(5, new Person("Jane", "Doe", "Female", 17));
getCache().putAll(persons);
System.out.println("Populated cache with " + getCache().size() + " entries");
}
public void displayTeens()
{
getCache().values(Filters.script("js", "IsTeen")) // Use our "Teen Filter"
.stream()
.forEach(System.out::println);
}
public void getPersonsInTeens()
{
// Construct a BetweenFilter with our AgeExtractor
BetweenFilter filter = (BetweenFilter) Filters.between(
Extractors.script("js", "AgeExtractor"), 13, 19);
// Retrieve entries using our filter
getCache().values(filter)
.forEach(System.out::println);
}
public void oldestPersons()
{
int oldestMaleKey = getCache().aggregate(Filters.equal("gender", "Male"),
Aggregators.script("js", "OldestPerson"));
int oldestFemaleKey = getCache().aggregate(Filters.equal("gender", "Female"),
Aggregators.script("js", "OldestPerson"));
System.out.println("Oldest Male : " + getCache().get(oldestMaleKey));
System.out.println("Oldest Female: " + getCache().get(oldestFemaleKey));
}
public void toInitCase()
{
// Make Updates using our "InitCaseProcessor"
getCache().invokeAll(Processors.script("js", "UpperCaseProcessor"));
// Display updated entries
getCache().values()
.forEach(System.out::println);
}
// ----- data members ----------------------------------------------------
public static void main(String[] args)
{
MyAppClient appClient = new MyAppClient();
appClient.populateCache();
System.out.println("------------ Display Teens -------------------");
appClient.displayTeens();
System.out.println("------------ Get Teens -------------------");
appClient.getPersonsInTeens();
System.out.println("------------ To Upper Case -------------------");
appClient.toInitCase();
System.out.println("------------ Oldest Persons -------------------");
appClient.oldestPersons();
}
}