59 Building Your First Coherence JCache Application

You can follow step-by-step instructions for building and running a basic Coherence JCache example that demonstrates fundamental concepts of both JCache and the Coherence JCache provider.The sample application is a simple application that stores a domain object (the Person object) into a cache. The example demonstrates using a local cache, a partitioned cache, and a pass-through cache.

If you are new to Coherence, you may consider also running the native Coherence NamedCache example. See Building Your First Coherence Application.

Application and Provider Lifecycle

Use Java 21 or later and the matching 26.1.0.0.0 Coherence/JCache artifacts. Configure the intended provider, cache URI, and class loader once, then reuse the CacheManager. Standard JCache entry processors and listeners have their own interfaces; when their definitions cross a Coherence boundary, provide the required application data/executable metadata as well.

This chapter includes the following sections:

Task 1: Create a Simple Object

Create a simple Person object to be cached using the Coherence JCache provider.The Person object contains a constructor and three fields for a first name, last name, and age. The Person object implements the Serializable interface. Serialization is required when the object is stored in a partitioned cache.

Example 59-1 A Simple Person Object

package com.examples;

import com.tangosol.util.function.Remote;
import java.io.Serializable;

@Remote.Allowed
public record Person(String firstName, String lastName, int age) implements Serializable {
    public String getFirstName() { return firstName; }
    public String getLastName() { return lastName; }
    public int getAge() { return age; }
}

Task 2: Store the Object in a Local Cache

Applications use the JCache API to access and interact with a cache.The API provides methods for creating and using a cache. The default cache type that Coherence uses if no cache type is defined is a local cache (local to the application process).

This section includes the following topics:

Create the Sample JCache Application

The following application stores a single Person object to a local cache. The application demonstrates getting a cache provider, creating a cache manager, configuring and creating a cache, and using the cache.

Build and metadata prerequisites

Use the matching 26.1 coherence-jcache provider and standard javax.cache API. Compile Person and JCacheExample in the same com.examples package. The Person record uses Java 21 or later and preserves JavaBean-style accessors for the examples that follow.

Run the security-config-maven-plugin generate goal during process-classes so Person’s @Remote.Allowed annotation produces META-INF/coherence/security-config.xml. Package that resource with the model and put the artifact on every required classpath. The default local-cache walkthrough uses Java serialization; POF examples additionally need POF type registration. See Generating Application Security Configuration.

Example 59-2 An Example JCache Application

package com.examples;

import javax.cache.Cache;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;

public class JCacheExample {
    public static void main(String[] args) {
        var provider = Caching.getCachingProvider();
        try (var manager = provider.getCacheManager()) {
            var config = new MutableConfiguration<String, Person>()
                    .setStoreByValue(true)
                    .setTypes(String.class, Person.class);
            Cache<String, Person> cache = manager.createCache("MyCache", config);
            cache.put("k", new Person("John", "Doe", 24));
            System.out.println("Cache: " + cache.getName() + " contains: " + cache.get("k"));
        }
    }
}

Run the Sample JCache Application

To run the standalone application example:

Project setup

Use the complete pom.xml in Building Examples with Application Security Metadata and put both source files under src/main/java/com/examples. The Maven build compiles the Java 21 sources, generates the allowed Person metadata and packages target/person.jar. For a partitioned or pass-through variant, put that artifact on the storage member classpath as well as the application classpath. The run command assumes the matching provider/API libraries from the installed distribution; translate the quoted classpath as described in the programming introduction on Windows.

  1. From a command prompt, compile the Person.java and JCacheExample.java files. The following example assumes that the files are in a single directory that is referred to as APPLICATION_HOME for the remainder of the tasks in this chapter:
    mvn clean package
    jar tf target/person.jar
  2. Run the JCacheExample class and include the location of the coherence.jar, coherence-jcache.jar, and cache-api.jar libraries on the classpath using the Java -cp option. For example:
    java -cp "target/classes:$COHERENCE_HOME/lib/cache-api.jar:$COHERENCE_HOME/lib/coherence-jcache.jar:$COHERENCE_HOME/lib/coherence.jar" com.examples.JCacheExample

    Coherence log messages are emitted that indicate the Coherence configuration resources that are being used and the Coherence cache factory being created. The application emits the entry that is in the cache and then the application exits.

Task 3: Configure an Example Cluster

Partitioned caches and pass-through caches use a Coherence cluster to distribute cached data.This task creates an operational override file to modify the out-of-box default cluster configuration. In particular, the default configuration is modified to create a private cluster which ensures that the JVM processes do not attempt to join an existing Coherence cluster that may be running on the network.

To configure an example cluster:

  1. Create a file named tangosol-coherence-override.xml.

  2. Add the following override configuration and replace cluster_name with a value that is unique for this cluster. For example, use your name for the cluster name.

    <?xml version='1.0'?>
    <coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
       xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
       coherence-operational-config.xsd">
       <cluster-config>
          <member-identity>
             <cluster-name>cluster_name</cluster-name>
          </member-identity>
       </cluster-config>
    </coherence>
    
  3. Save the file to the APPLICATION_HOME\config directory.

Task 4: Store the Object in a Partitioned Cache

A partitioned cache is a cache that distributes cache entries among any number of cache servers in a Coherence cluster.Entries that are stored in partitioned caches are backed up and persist on the cluster after the application process ends. See Creating Partitioned Caches.

In this task, two separate Java processes form the cluster: a cache server process and the JCacheExample application process. For simplicity, the two processes are collocated on a single computer. The cache server, by default, is configured to store cache data. Lastly, a Coherence CacheFactory is used to verify that the JCacheExample application successfully created and loaded the cache on the cluster.

This section includes the following topics:

Start the Example Cache Server

From a command prompt, start a cache server instance using the Coherence class and use the Java -cp option to include the APPLICATION_HOME\config directory. The classpath must also include the cache-api.jar, coherence-jcache.jar, and coherence.jar libraries. Ensure that the operational override file and the coherence-jcache.jar are loaded on the classpath before the coherence.jar library. Lastly, use the coherence.cacheconfig system property to explicitly use the JCache coherence-jcache-cache-config.xml cache configuration file that is located in the coherence-jcache.jar. For example:

java -Dcoherence.cacheconfig=coherence-jcache-cache-config.xml -cp "$APPLICATION_HOME/target/person.jar:$APPLICATION_HOME/config:$COHERENCE_HOME/lib/cache-api.jar:$COHERENCE_HOME/lib/coherence-jcache.jar:$COHERENCE_HOME/lib/coherence.jar" com.tangosol.net.Coherence

From the cache server output, notice that a distributed cache service that is called jcache-partitioned-service is created and is the senior member of the cluster:

(thread=DistributedCache:jcache-partitioned-service, member=1): Service 
jcache-partitioned-service joined the cluster with senior service member 1

Run The Application

The coherence.jcache.configuration.classname system property configures the Coherence JCache provider to use a partitioned cache instead of a local cache. The application code does not need to be modified in any way, which allows portability between JCache providers. In addition, Coherence manages the application scope and cache configuration.

To store the Person object in a partitioned cache:

  1. From a command prompt, run the application that was created in Example 59-2 and set the coherence.jcache.configuration.classname system property to partitioned and the coherence.distributed.localstorage system property to false. Use the Java -cp option to include the APPLICATION_HOME\config directory. The classpath must also include the cache-api.jar, coherence-jcache.jar, and coherence.jar libraries. Ensure that the operational override file and the coherence-jcache.jar library are loaded on the classpath before the coherence.jar library. For example:
    java -Dcoherence.jcache.configuration.classname=partitioned -Dcoherence.distributed.localstorage=false -cp "$APPLICATION_HOME/target/person.jar:$APPLICATION_HOME/config:$COHERENCE_HOME/lib/cache-api.jar:$COHERENCE_HOME/lib/coherence-jcache.jar:$COHERENCE_HOME/lib/coherence.jar" com.examples.JCacheExample

    Coherence log messages are emitted that indicate the Coherence configuration resources that are being used. Notice that the tangosol-coherence-override.xml file was loaded. Lastly, notice that the application process joins the cluster and that the jcache-partitioned-service instance joins with the senior service on the cache server:

    (thread=DistributedCache:jcache-partitioned-service, member=2): Service
    jcache-partitioned-service joined the cluster with senior service member 1
    

Verify the Cache

The cache server in this example is configured, by default, to store the cache's data. The data is available to all members of the cluster and persists even after members leave the cluster. For example, the application exits after it loads and displays a key in the cache. However, the cache and key are still available for all cluster members.

This step uses the cache factory command-line tool to connect to the cache and list all items in the cache.

To verify the cache:

  1. From a command prompt, start a standalone cache factory instance using the CacheFactory class. Use the Java -cp option to include the APPLICATION_HOME\config directory. The classpath must also include the Person object, cache-api.jar, coherence-jcache.jar, and coherence.jar libraries. Ensure that the operational override file and the coherence-jcache.jar are loaded on the classpath before the coherence.jar library. Lastly, set the coherence.cacheconfig system property to coherence-jcache-cache-config.xml and the coherence.distributed.localstorage system property to false. For example:
    java -Dcoherence.cacheconfig=coherence-jcache-cache-config.xml -Dcoherence.distributed.localstorage=false -cp "$APPLICATION_HOME/config:$APPLICATION_HOME/target/person.jar:$COHERENCE_HOME/lib/cache-api.jar:$COHERENCE_HOME/lib/coherence-jcache.jar:$COHERENCE_HOME/lib/coherence.jar" com.tangosol.net.CacheFactory

    The cache factory instance starts and becomes a member of the cluster and returns a command prompt for the command-line tool.

  2. At the command-line tool command prompt, get the MyCache cache using the cache command:
    cache jcache-partitioned-coherence-jcache-cache-config.xml$MyCache
    

    Note:

    For this example, the cache name includes the application scope. Applications do not need to explicitly include the application scope when using a cache.

  3. At the command-line tool command prompt, retrieve the contents of the cache using the list command.
    list
    

    The command returns and displays:

    k = Person[firstName=John, lastName=Doe, age=24]
    
  4. Shutdown all processes.

Task 5: Store the Object in a Pass-Through Cache

A pass-through cache is a cache that delegates to a pre-existing Coherence cache (a cache that is defined in a Coherence cache configuration file).Pass-through caches allow you to use all of the native features of Coherence and provide greater control over cache configuration.

In this task, two separate Java processes form the cluster: a cache server process and the JCacheExample application process. For simplicity, the two processes are collocated on a single computer. The cache server, by default, is configured to store cache data. Lastly, a Coherence CacheFactory is used to verify that the JCacheExample application successfully created and loaded the cache on the cluster.

This section includes the following topics:

Define the Example Cache

For this example, a cache configuration is created that defines a distributed cache that is explicitly mapped to the MyCache name.

To define the example cache:

  1. Create an XML file named example-config.xml.
  2. Copy the following distributed cache definition to the file:
    <?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>MyCache</cache-name>
             <scheme-name>distributed</scheme-name>
          </cache-mapping>
       </caching-scheme-mapping>
       
       <caching-schemes>
          <distributed-scheme>
             <scheme-name>distributed</scheme-name>
             <service-name>DistributedCache</service-name>
             <backing-map-scheme>
                <local-scheme/>
             </backing-map-scheme>
             <autostart>true</autostart>
          </distributed-scheme>
       </caching-schemes>
    </cache-config>
    
  3. Save the file to the APPLICATION_HOME\config directory.

Start the Example Cache Server

From a command prompt, start a cache server instance using the Coherence class and use the Java -cp option to include the APPLICATION_HOME\config directory and the coherence.jar library. Ensure that the operational override file is loaded on the classpath before the coherence.jar library. Lastly, use the coherence.cacheconfig system property to explicitly define the example-config.xml cache configuration file. For example:

java -Dcoherence.cacheconfig=example-config.xml -cp "$APPLICATION_HOME/target/person.jar:$APPLICATION_HOME/config:$COHERENCE_HOME/lib/coherence.jar" com.tangosol.net.Coherence

Run the Application

The coherence.jcache.configuration.classname system property configures the Coherence JCache provider to use a pass-through cache. The application code does not need to be modified in any way.

From a command prompt, run the JCacheExample class and set the coherence.jcache.configuration.classname system property to passthrough, the coherence.cacheconfig system property to example-config, and the coherence.distributed.localstorage system property to false. Use the Java -cp option to include the APPLICATION_HOME\config directory. The classpath must also include the cache-api.jar, coherence-jcache.jar, and coherence.jar libraries. Ensure that the operational override file is loaded on the classpath before the coherence.jar library. For example:

java -Dcoherence.jcache.configuration.classname=passthrough -Dcoherence.cacheconfig=example-config.xml -Dcoherence.distributed.localstorage=false -cp "$APPLICATION_HOME/target/person.jar:$APPLICATION_HOME/config:$COHERENCE_HOME/lib/cache-api.jar:$COHERENCE_HOME/lib/coherence-jcache.jar:$COHERENCE_HOME/lib/coherence.jar" com.examples.JCacheExample

Coherence log messages are emitted that indicate the Coherence configuration resources that are being used. Notice that the tangosol-coherence-override.xml file and example-config.xml file were loaded. The application process connects to the cluster that contains the cache server process and both processes are running the DistributedCache service. As before, the application emits the entry that is in the cache and then the application exits.

Verify the Cache

The cache server in this example is configured, by default, to store the cache's data. The data is available to all members of the cluster and persists even after members leave the cluster. For example, the application exits after it loads and displays a key in the cache. However, the cache and key are still available for all cluster members.

This step uses the cache factory command-line tool to connect to the MyCache cache and list all items in the cache.

To verify the cache:

  1. From a command prompt, start a standalone cache factory instance using the CacheFactory class. Use the Java -cp option to include the APPLICATION_HOME\config directory. The classpath must also include the Person object and the coherence.jar library. Ensure that the operational override file is loaded on the classpath before the coherence.jar library. Lastly, set the coherence.cacheconfig system property to example-config.xml and the coherence.distributed.localstorage system property to false. For example:
    java -Dcoherence.cacheconfig=example-config.xml -Dcoherence.distributed.localstorage=false -cp "$APPLICATION_HOME/config:$APPLICATION_HOME/target/person.jar:$COHERENCE_HOME/lib/coherence.jar" com.tangosol.net.CacheFactory

    The cache factory instance starts and becomes a member of the cluster and returns a command prompt for the command-line tool.

  2. At the command-line tool command prompt, get the MyCache cache using the cache command:
    cache MyCache
    
  3. At the command-line tool command prompt, retrieve the contents of the cache using the list command.
    list
    

    The command returns and displays:

    k = Person[firstName=John, lastName=Doe, age=24]