This chapter includes the following sections:
This section provides a brief overview of the programming features of the Coherence Java API. For additional details, see Java API Reference for Oracle Coherence.
Understanding the CacheFactory Class
CacheFactory class is the main entry point for Coherence applications. The
CacheFactory class is a factory for managing
NamedCache instances. The class is most often used for creating, releasing, and destroying cache instances.
Understanding the NamedCache Interface
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.
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.
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.
For instructions creating and using NamedCache instances, see "Performing Basic Cache Operations."
API for Queries
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.
For instructions querying caches, see "Querying Data In a Cache."
API for Cache Processing
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
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.
For instructions on cache processing, 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.
For instructions on using map events, 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.
For instructions on using live evens, 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.
For instructions on transactions, 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
When serializing an object, Java serialization automatically crawls every visible object (by using object references, including collections like
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.
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, start by reading the
Generics Lesson from the 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. For details about
NamedCache type checking, see "Using NameCache Type Checking."
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.
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.
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:
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. For details on using lambdas expressions to process entries, see "Processing Entries Using Lambda Expressions." For examples of using lambda expressions in Coherence, see the Coherence examples in Installing Oracle Coherence.
If you are new to lambda in Java, see the following resources:
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. For details see the
com.tangosol.internal.util.stream packages in the Java API Reference for Oracle Coherence.
If you are new to streams, see the following resources:
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.
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. There fore, the default methods have been re-implemented using entry processors that take advantage of lambda expressions.
If you are new to default methods, see the following resources: