19 Introduction to Coherence Programming

This chapter provides an introduction to the Coherence Java API that is used for performing cache and data grid operations.

For details about using the Coherence C# and C++ API, see Extend Client APIs in Developing Remote Clients for Oracle Coherence.

This chapter includes the following sections:

19.1 Overview of the Coherence API

This section provides a brief overview of the programming features of the Coherence Java API. See also Java API Reference for Oracle Coherence.

Understanding the Session Interface and the CacheFactory Class

The Session interface and the CacheFactory class are the main entry point for Coherence applications. Both APIs are used to manage NamedCache instances and are most often used for creating, releasing, and destroying cache instances. See Getting a Cache Instance.

Understanding the NamedCache Interface

A NamedCache is a Map implementation that holds resources that are shared among members of a cluster. The resources are expected to be managed in memory and are typically composed of data that are often stored persistently in a database or data that have been assembled or calculated at some significant cost.

The NamedCache interface provides many methods for performing cache operations and extends many different Map operations that add features for querying cache, processing cache entries, registering listeners for cache events, and controlling concurrent access to cache entries.

The AsyncNamedCache interface is an asynchronous version of the NamedCache Interface. The interface makes use of the CompleteableFuture API from the Java java.util.concurrent package to asynchronously perform cache operations.

See Performing Basic Cache Operations.

API for Queries

The QueryMap interface provides the ability to query a cache using various filters that operate on values that are extracted from cache entries. The interface also includes the ability to add and remove indexes. Indexes are used to correlate values stored in the cache to their corresponding keys and can dramatically increase performance. See Querying Data In a Cache.

API for Cache Processing

The InvocableMap interface provides the ability to invoke both entry-targeted processing and aggregating operations on a cache. The operations against the cache contents are executed by (and thus within the localized context of) a cache. This is particularly useful in a distributed environment, because it enables the processing to be moved to the location at which the entries-to-be-processed are being managed, thus providing efficiency by localization of processing.

An entry processor is an agent that operates against the entry objects within a cache. Coherence includes many predefined entry processors that can be used to perform many common operations. The processors are defined in the com.tangosol.util.processor package.

An entry aggregator represents processing that can be directed to occur against some subset of the entries resulting in an aggregated result. Common examples of aggregation include functions such as minimum, maximum, sum and average. However, the concept of aggregation applies to any process that must evaluate a group of entries to come up with a single answer. Aggregation is explicitly capable of being run in parallel in a distributed environment.

See Processing Data In a Cache.

API for Events

Coherence provides two programming models for processing events. The ObservableMap interface enables an application to receive events when the contents of a cache changes. To register interest in change events, an application adds a Listener implementation to the cache that receives events that include information about the event type (inserted, updated, deleted), the key of the modified entry, and the old and new values of the entry. See Using Map Events.

The live event model uses event interceptors to listen for specific events that occur within the cluster. The interceptors are created specific to the event types and can be chained together. Event types are defined for partitioned cache and server events, lifecycle events, and federated caching events. See Using Live Events.

API for Transactions

Coherence offers various transaction options that provide different transaction guarantees. The ConcurrentMap API is locking API that provides explicit locking. Entry processors also provide a lock-free programming model that minimizes contention and latency and improves system throughput, without compromising the fault-tolerance of data operations. Lastly the Transaction Framework API is a connection-based API that provides atomic transaction guarantees across partitions and caches even with a client failure. See Performing Transactions.

Serialization in Coherence

Coherence caches value objects. These objects may represent data from any source, either internal (such as session data, transient data, and so on) or external (such as a database, mainframe, and so on).

Objects placed in the cache must be serializable. Because serialization is often the most expensive part of clustered data management, Coherence provides different options for serializing/deserializing data:

  • com.tangosol.io.pof.PofSerializer – The Portable Object Format (also referred to as POF) is a language agnostic binary format. POF was designed to be efficient in both space and time and is the recommended serialization option in Coherence. See Using Portable Object Format.

  • java.io.Serializable – The simplest, but slowest option.

  • java.io.Externalizable – This option requires developers to implement serialization manually, but can provide significant performance benefits. As compared to java.io.Serializable, serialized data sizes can be minimized by a factor of two or more. Smaller data sizes is especially helpful with Distributed caches, as they generally cache data in serialized form. Most importantly, CPU usage is dramatically reduced.

  • com.tangosol.io.ExternalizableLite – This option is very similar to java.io.Externalizable, but offers better performance and less memory usage by using a more efficient I/O stream implementation.

  • com.tangosol.run.xml.XmlBean – A default implementation of ExternalizableLite.

Note:

When serializing an object, Java serialization automatically crawls every visible object (by using object references, including collections like Map and List). As a result, cached objects should not refer to their parent objects directly (holding onto an identifying value like an integer is allowed). Objects that implement their own serialization routines are not affected.

19.2 Support for Generics

The Coherence programming API makes use of Java generics to provide compile and runtime type checking together with compile type-inference. If you are new to Java Generics, see Generics Lesson in Java Tutorials. Many Coherence interfaces and public classes have associated types. Generics provides cleaner code, less casting, and better type safety. Type checking is not required but it is a recommended best practice.

In addition to Java Generics support, Coherence allows types to be explicitly configured when creating a NamedCache instance or when defining a cache in the cache configuration file. See Using NameCache Type Checking.

Note:

The examples in this book may not be written to use generics. However, it is expected that the use of generics will be a standard approach when programming with the Coherence API.

19.3 Support for Java 8 Features

The Coherence API has been updated so that you can use programming features that were introduced in the Java 8 release: The features include lambda, streams, and default methods. These features provide ease of use and flexibility when performing data grid operations.

Lambdas

The Java lambda implementation provides a level of functional programming that allows code to be passed as arguments and returned as a result. Lambdas are often used instead of anonymous inner classes when working with functional interfaces (an interface that contains a single abstract method). There are many existing functional interfaces that are ideal for use with lambda expressions. There are also new generic functional interfaces (for example: Function, Predicate, Supplier, Consumer, and so on) that are useful as well.

Many Coherence interfaces are functional interfaces and can be used with lambda expressions and are demonstrated throughout this guide. The most common use of lambda expressions in Coherence is to extract values, query and filter entries and process entries. See Processing Entries Using Lambda Expressions and Coherence Java 8 Features Example in Installing Oracle Coherence.

If you are new to lambda in Java, see the following resources:

Streams

The Java streams implementation provides an efficient way to query and process data sequentially or in parallel to take advantage of multi core architectures. The processing occurs in steps:

  • Data is aggregated from a source (such as collections or arrays) into a read-only stream. The stream represents object references and does not actually store the data.

  • Intermediate operations are then declared on the stream. Intermediate operations for filtering, sorting, mapping, and so on are supported. Lambda expressions are often used when declaring intermediate operations and provide a functional way to work on the data. Intermediate operations are aggregated and can be chained together: each subsequent operation is performed on a stream that contains the result of the previous operation. Intermediate operations are lazy and are not actually executed until a final terminal operation is performed.

  • A final terminal operation is declared. Terminal operations for counting, adding, averaging, and so on are supported. The terminal operation automatically iterates over the objects in the stream returns an aggregated result.

Java streams provide similar functionality as Coherence data grid aggregation. However, streams are not efficient when executed in a distributed environment. To leverage the stream programming model and also ensure that streams can be executed remotely across the cluster, Coherence has extended the streams API in the com.tangosol.util.stream and com.tangosol.internal.util.stream packages.

See Performing Data Grid Aggregation Using Streams and Coherence Java 8 Features Example in Installing Oracle Coherence.

If you are new to streams, see the following resources:

Default Methods

The Java default method implementation provides a way to add new methods to existing interfaces without having to update existing implementations of the interface. New methods are added to the interface using the default keyword. Existing implementation can choose to use the default method as defined in the interface, re-declare the method as abstract to require a new implementation, or override the default implementation with a new implementation. Default methods can also be used to add methods that accept lambda expressions as parameters to existing interfaces.

The java.util.Map interface has been updated to include default methods that add functionality such as merging entries and replacing all entries. Coherence applications can take advantage of these methods through the NamedCache interface; however, the default method implementations assume data locality and are neither thread-safe or cluster-safe. Therefore, the default methods have been re-implemented using entry processors that take advantage of lambda expressions.

See Using Default Map Operations and Coherence Java 8 Features Example in Installing Oracle Coherence.

If you are new to default methods, see the following resources: