25 Performing Basic Cache Operations
This chapter includes the following sections:
- Overview of the NamedMap API
Thecom.tangosol.net.NamedMap<K, V>
interface is the primary interface used by applications to get and interact with cache instances. - Getting a Cache Instance
To get a reference to aNamedMap
instance, applications can use theSession
API and theCacheFactory
API. - Performing Cache Put Operations
Basic cacheput
operations are performed using theput
method as defined by theMap
interface. - Performing Cache Get Operations
Basic cache get operations are performed using theget
method as defined by theMap
interface. - Performing Cache Remove Operations
Basic cache remove operations are performed using theremove
method as defined by theMap
interface. - Using Default Map Operations
Coherence overrides manyMap
method implementations to ensure these operations perform well in a distributed environment. - Pre-Loading a Cache
Pre-Loading a cache is a common scenario used to populate a cache before an application uses the data. - Clearing Caches
The contents of a map can be cleared using either theclear
ortruncate
methods that are defined by theNamedMap
interface. - Releasing Caches
Applications that no longer require a cache should use theNamedMap.release
method to release local resources associated with the specified instance of the cache. - Destroying Caches
NamedMaps or NamedCaches that are created using aSession
or aCacheFactory
class can be destroyed using theNamedMap.destroy
method. - Closing Sessions
Applications should close a session when the session is no longer required. - Performing NamedMap Operations Asynchronously
Thecom.tangosol.net.AsyncNamedMap<K, V>
interface allows cache operations to be completed in parallel. - Using NamedMap Type Checking
Coherence includes the ability to request strongly-typedNamedMap
instances when using either theSession
or theCacheFactory
API by using explicit types.
Parent topic: Performing Data Grid Operations
Overview of the NamedMap API
com.tangosol.net.NamedMap<K,
V>
interface is the primary interface used by applications to get and
interact with cache instances. The NamedMap<K, V>
interface extends other interfaces, which each provide additional cache capabilities that
are unique to Coherence and used to perform data grid operations.
The extended interfaces include:
-
java.util.Map<K, V>
– This interface provides basicMap
methods such asget()
,put()
, andremove()
. -
com.tangosol.net.cache.CacheMap<K, V>
– This interface provides methods for getting a collection of keys (as aMap
) that are in the cache and for putting objects in the cache. This interface also supports adding an expiry value when putting an entry in a cache. -
com.tangosol.util.QueryMap<K, V>
– This interface provides methods for querying the cache. See Querying Data in a Cache. -
com.tangosol.util.InvocableMap<K, V>
– This interface provides methods for server-side processing of cache data. See Processing Data In a Cache. -
com.tangosol.util.ObservableMap<K, V>
– This interface provides methods for listening to cache events. See Using Map Events. -
com.tangosol.util.ConcurrentMap<K, V>
– This interface provides methods for concurrent access such aslock()
andunlock()
. See Performing Transactions.
Note:
If you want to issue aput
with expiry, which is not available with
NamedMap
, you can use the com.tangosol.net.NamedCache<K,
V>
interface, which extends NamedMap
. You can retrieve
a NamedCache
instance by using the Session API as shown in the examples
provided in the subsequent sections.
Parent topic: Performing Basic Cache Operations
Getting a Cache Instance
NamedMap
instance, applications can use the Session
API and the
CacheFactory
API.The Session
API is
the preferred approach for getting a cache because it offers a concise set of methods that
allows for the use and injection of Coherence sessions that are non-static. In contrast, the
CacheFactory
API exposes many static methods that require knowledge of
internal Coherence concepts and services. Lastly, the Session
API allows
for a more efficient lifecycle and integration with other frameworks, especially frameworks
that use injection.
The following example creates a session using a default session provider then gets a
reference to a NamedMap
instance using the
Session.getCache
method. The name of the cache is included as a
parameter.
import com.tangosol.net.*;
...
Session session = Session.create();
NamedMap<Object, Object> map = session.getMap("MyCache");
The CoherenceSession
class implements the Session
interface and allows applications to use the new
operator. For example:
import com.tangosol.net.*;
...
Session session = new CoherenceSession();
NamedMap<Object, Object> map = session.getMap("MyCache");
The following example gets a reference to a NamedCache
instance using the CacheFactory.getCache
method and includes the name of the cache as a parameter:
import com.tangosol.net.*;
...
NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache");
Note:
Although you can use CacheFactory to getNamedCache
instances, Oracle
recommends you to use the Session API to get NamedMap
and
NamedCache
instances.
Both the Session
API and CacheFactory
API start the underlying cache service if necessary. The cache instance is created using a cache scheme that is defined in the cache configuration file (coherence-cache-config.xml
by default). The cache scheme is mapped to the name MyCache
. See Configuring Caches.
A NamedMap
instance can store keys and values of any type. However,
applications must ensure type safety when interacting with cache entries. Applications
can create NamedMap
instances for specific types and Coherence also
offers API-level type checking. See Using NamedMap Type Checking.
Requirements for Cached Objects
Cache keys and values must be serializable (for example, java.io.Serializable
or Coherence Portable Object Format serialization). Furthermore, cache keys must provide an implementation of the hashCode()
and equals()
methods, and those methods must return consistent results across cluster nodes. This implies that the implementation of hashCode()
and equals()
must be based solely on the object's serializable state (that is, the object's non-transient fields); most built-in Java types, such as String
, Integer
and Date
, meet this requirement. Some cache implementations (specifically the partitioned cache) use the serialized form of the key objects for equality testing, which means that keys for which equals()
returns true
must serialize identically; most built-in Java types meet this requirement as well. See Using Portable Object Format.
Parent topic: Performing Basic Cache Operations
Performing Cache Put Operations
put
operations are
performed using the put
method as defined by the Map
interface.The put
method adds an entry to the cache and
returns the previous value for the specified key. For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);"
The putAll
method is used to add multiple entries to a cache in a single bulk load operation and requires the entries to be in a Map
type data structure. See Pre-Loading a Cache.
Parent topic: Performing Basic Cache Operations
Performing Cache Get Operations
get
method as defined by the Map
interface.The mapped value is returned for the specified key. For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
Parent topic: Performing Basic Cache Operations
Performing Cache Remove Operations
remove
method as defined by the Map
interface.The mapping for the specified key is removed from the cache and the previous value is returned. For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.remove(key)
Parent topic: Performing Basic Cache Operations
Using Default Map Operations
java.util.Map
interface includes default methods for performing operations such as putIfAbsent
, replaceAll
, and merge
, to name a few. Coherence overrides many Map
method implementations to ensure these operations perform well in a distributed environment.The methods have been re-implemented to use entry processors and to take advantage of lambda expressions. The methods are available when using the NamedCache
interface. For example:
String key = "k1";
String value = "Hello World!";
NamedCache<Object, Object> cache = CacheFactory.getCache("hello-example");
cache.putIfAbsent(key, value);
System.out.println(cache.get(key));
Lambda expressions can also be used to perform any required processing on the entries. For example,
map.replaceAll((key, value) -> { value.setLastName(value.getLastName().toUpperCase()); return value; });
Parent topic: Performing Basic Cache Operations
Pre-Loading a Cache
This section includes the following topics:
- Bulk Loading Data Into a Cache
- Performing Distributed Bulk Loading
- A Distributed Bulk Loading Example
Parent topic: Performing Basic Cache Operations
Bulk Loading Data Into a Cache
The put
method can be used to bulk load data into a cache. However; each call to put
may result in network traffic, especially for partitioned and replicated caches. Additionally, each call to put
returns the object it just replaced in the cache (as defined in the java.util.Map
interface) which adds more unnecessary overhead.
public static void bulkLoad(NamedMap map, Connection conn) { Statement s; ResultSet rs; try { s = conn.createStatement(); rs = s.executeQuery("select key, value from table"); while (rs.next()) { Integer key = new Integer(rs.getInt(1)); String value = rs.getString(2); cache.put(key, value); } ... } catch (SQLException e) {...} }
Loading the cache can be made much more efficient by using the ConcurrentMap.putAll
method instead. For example:
public static void bulkLoad(NamedMap map, Connection conn) { Statement s; ResultSet rs; Map buffer = new HashMap(); try { int count = 0; s = conn.createStatement(); rs = s.executeQuery("select key, value from table"); while (rs.next()) { Integer key = new Integer(rs.getInt(1)); String value = rs.getString(2); buffer.put(key, value); // this loads 1000 items at a time into the cache if ((count++ % 1000) == 0) { cache.putAll(buffer); buffer.clear(); } } if (!buffer.isEmpty()) { cache.putAll(buffer); } ... } catch (SQLException e) {...} }
Parent topic: Pre-Loading a Cache
Performing Distributed Bulk Loading
When pre-populating a Coherence partitioned cache with a large data set, it may be more efficient to distribute the work to Coherence cluster members. Distributed loading allows for higher data throughput rates to the cache by leveraging the aggregate network bandwidth and CPU power of the cluster. When performing a distributed load, the application must decide on the following:
-
which cluster members performs the load
-
how to divide the data set among the members
The application should consider the load that is placed on the underlying data source (such as a database or file system) when selecting members and dividing work. For example, a single database can easily be overwhelmed if too many members execute queries concurrently.
Parent topic: Pre-Loading a Cache
A Distributed Bulk Loading Example
This section outlines the general steps to perform a simple distributed load. The example assumes that the data is stored in files and is distributed to all storage-enabled members of a cluster.
-
Retrieve the set of storage-enabled members. For example, the following method uses the
getStorageEnabledMembers
method to retrieve the storage-enabled members of a distributed cache.protected Set getStorageMembers(NamedMap map) { return ((PartitionedService) map.getCacheService()) .getOwnershipEnabledMembers(); }
-
Divide the work among the storage enabled cluster members. For example, the following routine returns a map, keyed by member, containing a list of files assigned to that member.
protected Map<Member, List<String>> divideWork(Set members, List<String> fileNames) { Iterator i = members.iterator(); Map<Member, List<String>> mapWork = new HashMap(members.size()); for (String sFileName : fileNames) { Member member = (Member) i.next(); List<String> memberFileNames = mapWork.get(member); if (memberFileNames == null) { memberFileNames = new ArrayList(); mapWork.put(member, memberFileNames); } memberFileNames.add(sFileName); // recycle through the members if (!i.hasNext()) { i = members.iterator(); } } return mapWork; }
-
Launch a task that performs the load on each member. For example, use Coherence's
InvocationService
to launch the task. In this case, the implementation ofLoaderInvocable
must iterate throughmemberFileNames
and process each file, loading its contents into the cache. The cache operations normally performed on the client must execute through theLoaderInvocable
.public void load() { NamedCache cache = getCache(); Set members = getStorageMembers(cache); List<String> fileNames = getFileNames(); Map<Member, List<String>> mapWork = divideWork(members, fileNames); InvocationService service = (InvocationService) CacheFactory.getService("InvocationService"); for (Map.Entry<Member, List<String>> entry : mapWork.entrySet()) { Member member = entry.getKey(); List<String> memberFileNames = entry.getValue(); LoaderInvocable task = new LoaderInvocable(memberFileNames, cache.getCacheName()); service.execute(task, Collections.singleton(member), this); } }
Parent topic: Pre-Loading a Cache
Clearing Caches
clear
or truncate
methods that are defined by the
NamedMap
interface.The clear
method
can result in significant memory and CPU overhead and is generally not recommended to clear
a distributed cache. As an alternative, the truncate
method can be used.
For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.truncate();
The truncate
method makes better use of memory and CPU resources and is often the best option when clearing large caches and caches that use listeners. The truncate
method is also ideal for clearing a near cache as it clears both the front map and back map. The removal of entries caused by the truncate
method are not observable by listeners, triggers, and interceptors. However, a CacheLifecycleEvent
event is raised to notify all subscribers of the execution of this operation.
Parent topic: Performing Basic Cache Operations
Releasing Caches
NamedMap.release
method to release local resources associated with
the specified instance of the cache.Releasing a cache makes it no longer
usable but does no affect the contents of a cache or other references to the cache across
the cluster. For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.release();
Parent topic: Performing Basic Cache Operations
Destroying Caches
Session
or a CacheFactory
class can be destroyed
using the NamedMap.destroy
method. The
destroy
method destroys the specified cache across the entire cluster.
References to the cache are invalidated; the cached data is cleared; and, all resources are
released. The destroy
method is often preferred over the
NamedMap.clear()
method, which can be both a memory and CPU intensive
task in a distributed environment. For example:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.destroy();
Parent topic: Performing Basic Cache Operations
Closing Sessions
Use the close
method to close a session. For example:
String key = "k1";
String value = "Hello World!";
try(Session session = Session.create()) {
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
session.close();
}
catch (Exception e){
...
}
Parent topic: Performing Basic Cache Operations
Performing NamedMap Operations Asynchronously
com.tangosol.net.AsyncNamedMap<K,
V>
interface allows cache operations to be completed in
parallel.The interface makes use of the Java CompletableFuture
class, which provides completion and/or exception callbacks, chaining multiple asynchronous
calls to execute one after another, and waiting for all the calls executing in parallel to
complete. Performing NamedMap
operations asynchronously can improve
throughput and result in more responsive user interfaces. The Coherence examples provide
additional examples of performing asynchronous cache operations. See Coherence Asynchronous Features
Example in Installing Oracle Coherence.
To perform asynchronous cache operations, you must use the CompletableFuture
class and implement the Future
interface. For example:
import com.tangosol.net.AsyncNamedCache; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; public class HelloWorld { public static void main(String[] args) throws ExecutionException, InterruptedException { String key = "k1"; String value = "Hello World!"; NamedMap<Object, Object> map = CacheFactory.getCache("MyCache"); AsyncNamedMap<Object, Object> as = map.async(); Future future = as.put(key, value); future.get(); CompletableFuture cf = as.get(key); System.out.println(cf.get()); CompletableFuture cfremove = as.remove(key); System.out.print("Removing key/value: " + cfremove.get() + "\n" ); System.out.println("The key/value is: " + future.get()); } }
Parent topic: Performing Basic Cache Operations
Using NamedMap Type Checking
NamedMap
instances when using either the Session
or the CacheFactory
API by using explicit types.By default,
NamedMap<Object, Object>
instances return. This is the most flexible
mechanism to create and use NamedMap
instances; however, it is the responsibility
of the application to ensure the expected key and value types when interacting with cache
instances.
NamedMap<Object,Object> map = session.getMap("MyCache");
NamedCache<Object,Object> cache = CacheFactory.getCache("MyCache");
getCache
or getMap
method can be used to
request a NamedCache
or a NamedMap
instance of a specific
type, including if necessary, without type checking. The TypeAssertion
interface is used with the getCache
or NamedCache
method to
assert the correctness of the type of keys and values used with a NamedCache
or NamedMap
instance. The method can be used to assert that a cache should
use raw types. For
example:NamedMap<Object, Object> map = session.getMap("MyCache", TypeAssertion.withRawTypes());
CacheFactory
,NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache", TypeAssertion.withRawTypes());
String
, an application can
use:NamedMap<String, String> map = session.getMap("MyCache", TypeAssertion.withTypes(String.class, String.class));
NamedMap
instance is not required to adhere to the asserted type
and may choose to disregard it; however, a warning message is emitted at compile-time. For
example:NamedMap map = session.getCache("MyCache", TypeAssertion.withTypes(String.class, String.class));
NamedMap
instance may use specific types. However, in both cases, this
could lead to errors if types are left unchecked. For
example:NamedMap<String, String> map = session.getCache("MyCache", TypeAssertion.withRawTypes());
For the strongest type safety, specific types can also be declared as part of a cache definition in the cache configuration file. A runtime error occurs if an application attempts to use types that are different than those configured as part of the cache definition. The following examples configures a cache that only supports keys and values that are of type String
.
<cache-mapping> <cache-name>MyCache</cache-name> <scheme-name>distributed</scheme-name> <key-type>String</key-type> <value-type>String</value-type> </cache-mapping>
NamedCache<Object, Object> map = session.getMap("MyCache", TypeAssertion.withoutTypeChecking());
Parent topic: Performing Basic Cache Operations