Creating PMI Handlers
The basic form of a PMI handler is a CacheEntryForEach handler. Inherit from CacheEntryForEach and register your class as an invocation event handler to accept PMI requests from clients.
Prerequisites
ScaleOut StateServer Pro license
Procedure
Note
This sample in its entirety is available on our GitHub Samples Repo.
Determine the type parameters to use with your ForEach handler.
A PMI operation evaluates objects stored in a ScaleOut Cache. Caches in the library are strongly-typed, so invocation handlers are also strongly-typed.
This example analyzes a cache that tracks the most recent login date for an application’s users. The cache’s key type is a string (representing a User ID), and its value type is a long (representing a login time).
Create a class that inherits from ForEach<TKey, TValue>.
package com.scaleout.client.samples.compute; import com.scaleout.client.caching.CacheEntryForEachHandler; import com.scaleout.client.caching.OperationContext; public class FindInactiveUsersForEachHandler implements CacheEntryForEachHandler<String, Long, Void> { @Override public void evaluate(String key, OperationContext<String, Long, Void> operationContext) { // } }Implement your custom evaluation code.
During a PMI operation, your Evaluate method will be called for every object in the ScaleOut cache.
Your method can read, modify, delete, or perform any needed cache operation. In this example, login times are retrieved to identify inactive users.
// Use the cache in the PMI context to retrieve the object being evaluated: var readResponse = operationContext.getCache().read(key); if (readResponse.getStatus() == RequestStatus.ObjectNotFound) { System.out.println(key + " removed by another client during PMI operation."); return; } else if (readResponse.getStatus() != RequestStatus.ObjectRetrieved) { System.out.println("Unexpected error (" + readResponse.getStatus() + ") while reading key: " + key); return; } // Perform analysis: long lastLoginEpochMs = readResponse.getValue(); long inactiveTimeMs = System.currentTimeMillis() - lastLoginEpochMs; if (inactiveTimeMs > Duration.ofDays(7).toMillis()) { System.out.println(key + " inactive for {inactiveTime.TotalDays} days."); }At application startup, register the class as an invocation handler. If you are running your handler in an Invocation Grid, this code should be put in your project’s InvocationGridStartup.configure() method.
Tip
A PMI application can have multiple invocation handlers registered against multiple caches.
package com.scaleout.client.samples.compute; import com.scaleout.client.GridConnectException; import com.scaleout.client.GridConnection; import com.scaleout.client.ServiceEvents; import com.scaleout.client.ServiceEventsException; import com.scaleout.client.caching.Cache; import com.scaleout.client.caching.CacheBuilder; import java.io.IOException; public class PMIHandlerSample { public static void main(String[] args) throws GridConnectException, ServiceEventsException, IOException { GridConnection connection = GridConnection.connect("bootstrapGateways=localhost"); Cache<String, Long> cache = new CacheBuilder<String, Long>(connection, "PMISample", String.class) .build(); ServiceEvents.setForEachEventHandler(cache, "Find inactive users", new FindInactiveUsersForEachHandler()); System.out.println("Waiting for events..."); System.out.println("Press any key to exit."); System.in.read(); } }Build your handler application and deploy it to all the servers in your farm that are running the ScaleOut service.
Once your handler app is running on all your ScaleOut hosts, you are ready to process PMI requests.