43 多言語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-0-0</coherence.version> </properties> <dependencies> <dependency> <groupId>com.oracle.coherence</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();
}
}