In this exercise, you will create and configure an Oracle Coherence cache in Eclipse. It highlights the use of the Coherence CacheStore
, ContinuousQueryCache
, IdentityExtractor
, and Filter
APIs.
In this exercise you will create these items:
A Java class that creates a NamedCache
instance and can put and get cache entries.
A cache configuration file to define the mapping for cache names, cache types, and naming patterns.
A Java class that creates a connection to Oracle Database and can retrieve and store table data.
A database cache. This class will add cache entries, query the database cache, and retrieve entries.
This chapter contains the following sections:
A Coherence cache is a collection of data objects that acts as an intermediary between the database and the client applications. Database data can be loaded into a cache and made available to different applications. Thus, Coherence caches reduce load on the database and provide faster access to database data.
Coherence caches provide higher availability through database isolation and data replication. Modifications made to a cache can be synchronized with the database whenever the database is available. Even if the database or an application server node is not available, database updates are still reliable due to the lazy load and lazy write mechanism used by a Coherence cache and due to the failover and fail back provided by Coherence.
Coherence caches provide distributed processing not only across a cluster of application server nodes but also across the data objects in the cache, because data modification operations can be performed on the data objects.
Coherence also provides event-based processing. The state of data objects in a cache can be monitored and actions invoked on other processes such as the start of a business process execution language (BPEL) process.
Coherence supports different types of caches:
Replicated caches, where data is replicated to each of the application server nodes in the cluster. This type of cache is recommended if faster read access is required but not suitable for write operations, because data must be written to each of the nodes. The drawback of replicated caches is that they require a large amount of memory because every node has a copy of every object.
Distributed (or partitioned) caches, where data is distributed (load-balanced) across different nodes. Failover is implemented in a distributed cache using backups, which are also distributed across the cluster nodes.
Coherence is implemented by using services such as the cluster service, the distributed cache service, and the replicated cache service. Whichever type of cache is used, an application uses the same API to access and store data.
A cache configuration deployment descriptor is used to configure a cache. The root element of the cache configuration file is cache-config
. Cache names and name patterns are mapped to cache types in the caching-scheme-mapping
element using the subelement cache-mapping
. Cache types are defined in the caching-schemes
element. Table 9-1 describes some of the cache types commonly used by Coherence.
Table 9-1 Descriptions of Cache Types
Cache Type | Description |
---|---|
distributed scheme |
Defines a distributed cache in which data is stored across a cluster of nodes. |
replicated scheme |
Defines a cache in which cache entries are replicated across all the cluster nodes. |
read-write-backing-map scheme |
Defines a map, which provides a cache of a persistent store such as a relational database. |
external scheme |
Defines an external cache such as a disk. |
class scheme |
Defines a custom cache implementation, which is required to implement the |
This section describes how to create and run an application that puts data into the cache and retrieves it.
To create a Java class that constructs a Coherence cache:
Create a project in Eclipse.
Use the JPA perspective in Eclipse to create a JPA Project called Interaction
. Select the JPAConfiguration
you created in Chapter 8, "Using JPA with Coherence."
In the JPA Facet page, ensure that EclipseLink 2.4.x appears in the Platform field. Ensure that Coherence12.1.2 and TopLink are selected under User Libraries. In the Connection field, select the connection you created in "Configure the Project for JPA" (XE_HR), from the Connection drop down list. Click the Connect link to connect to the Oracle XE Database if necessary. (Note, this assumes that the database connection that you created is still running.) Select Add Driver Library to Build Path and select Oracle Database 11g Driver from the drop-down list. Click Next.
In the Coherence page, ensure that Coherence12.1.2 and TopLink are selected. Click Finish.
Create a Java class, CoherenceCache
, that will be used to create a Coherence cache. Include a main
method in the class. See "Creating a Java Class" for detailed information on creating a class.
Create a cache in the CoherenceCache
Java class. Import the CacheFactory
class and the NamedCache
interface.
import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache;
Create the cache (NamedCache
) instance by using the CacheFactory.
getCache
method. Use the cache name VirtualCache
, which is mapped to a distributed caching scheme.
NamedCache cache = CacheFactory.getCache ( "VirtualCache");
A NamedCache
is a java.util.Map
instance that holds resources that are shared across nodes in a cluster. Add a cache entry by using the put
method.
cache.put (key, "Hello Cache");
Retrieve a cache entry by using the get
method.
System.out.println((String)cache.get("hello"));
Example 9-1 illustrates a possible implementation of CoherenceCache
class. You can copy the code to the CoherenceCache
file in Eclipse.
Example 9-1 Implementation of a Coherence Cache
package com.oracle.handson; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; public class CoherenceCache { NamedCache cache; public CoherenceCache() { } public void putCache() { cache = CacheFactory.getCache ( "VirtualCache"); String key = "hello"; cache.put (key, "Hello Cache"); } public void retrieveCache() { System.out.println((String)cache.get("hello")); } public static void main (String [] args) { CoherenceCache cache = new CoherenceCache(); cache.putCache(); cache.retrieveCache(); } }
In the Project Explorer, rename the coherence-cache-config.xml
cache configuration file to be cache-config.xml
. Open the file in the Eclipse Editor.
In the cache configuration file:
Define mappings for cache names and naming patterns with the cache-mapping
elements in the caching-scheme-mapping
element.
Map the cache name VirtualCache
to cache type distributed-eclipselink
.
Define the distributed caching scheme with the distributed-scheme
element using the EclipseLinkJPA
service.
The cache configuration file is illustrated in Example 9-2. Copy the contents of this example to the cache-config.xml
.
Example 9-2 Cache Configuration 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>VirtualCache</cache-name> <scheme-name>distributed-eclipselink</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <!-- Default Distributed caching scheme. --> <distributed-scheme> <scheme-name>distributed-eclipselink</scheme-name> <service-name>EclipseLinkJPA</service-name> <backing-map-scheme> <class-scheme> <scheme-ref>default-backing-map</scheme-ref> </class-scheme> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> <class-scheme> <scheme-name>default-backing-map</scheme-name> <class-name>com.tangosol.util.SafeHashMap</class-name> </class-scheme> </caching-schemes> </cache-config>
Create a run configuration for the application to add the cache configuration file as a run-time Java option.
Right click CoherenceCache.java
in the Project Explorer and choose Run As then Run Configurations. In the Run Configurations dialog box, click the New launch configuration icon.
Enter CoherenceCacheServer
in the Name field. Ensure that Interaction
is in the Project field and com.oracle.handson.CoherenceCache
is in the Main class field.
In the Coherence tab, enter the path to the cache configuration file, C:\home\oracle\workspace\Interaction\src\cache-config.xml
. Select the Enabled (cache server) button. Enter a unique value, such as 3155
, in the Cluster port field. Click Apply.
The Classpath tab should look similar to Figure 9-1.
Figure 9-1 Classpath for the CoherenceCacheServer Executable
To create a cache sever start-up configuration for the Interaction project:
Right click the Interaction project and select Properties. In the Properties for Interact dialog box, select Java Build Path. In the Order and Export tab, the Interaction project, the JRE, Coherence12.1.2, TopLink, and the Oracle Database 11g Driver Default libraries should be present. Ensure that they are all selected. The Order and Export tab should look similar to Figure 9-2.
Figure 9-2 Order and Export Tab for Libraries for the Java Build Path
Edit the JPA cache server start-up configuration (JPAServer
) that you created in Chapter 8, "Using JPA with Coherence".
Right click the Interaction project and select Run As then Run Configurations. In the Main tab click Browse and select the Interaction project from the Project Selection dialog box.
In the General tab of the Coherence tab, replace the name and path of the configuration file with C:\home\oracle\workspace\Interaction\cache-config.xml
.
In the Classpath tab, remove the JPA (default classpath) folder. Click Add Project to add the Interaction project. The Classpath tab should look similar to Figure 9-3.
Figure 9-3 Classpath for the Interaction Project Cache Server
In the Shared file field of the Common tab, click Browse to select the Interaction project. Click Apply, then Close.
To run the cache creation application CoherenceCache.java
:
Stop any running cache servers. See "Stopping Cache Servers" for more information.
Run the JPAServer
to start the cache server.
Right-click the Coherence application CoherenceCache.java
and click Run As then Run Configurations. Select the CoherenceCacheServer
configuration and click Run. The Eclipse console window displays the output:
The operational configuration is loaded from the tangosol-coherence.xml
file. This file specifies the operational and run-time settings used by Coherence for its clustering, communication, and data management services.
The cache configuration is loaded from the cache-config.xml
file.
A new cluster is created and the DistributedCache
service joins the cluster.
The output of the CoherenceCache.java
program, Hello
Cache
is displayed.
Example 9-3 Output of the Coherence Cache Application
... 2013-02-14 16:30:37.735/0.735 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=main, member=n/a): Loaded cache configuration from "file:/C:/home/oracle/workspaceNov/Interaction/src/cache-config.xml" 2013-02-14 16:30:37.891/0.891 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=main, member=n/a): Created cache factory com.tangosol.net.ExtensibleConfigurableCacheFactory 2013-02-14 16:30:38.110/1.110 Oracle Coherence GE 12.1.2.0.0 <Warning> (thread=main, member=n/a): Local address "127.0.0.1" is a loopback address; this cluster node will not connect to nodes located on different machines 2013-02-14 16:30:38.250/1.250 Oracle Coherence GE 12.1.2.0.0 <D4> (thread=main, member=n/a): TCMP bound to /127.0.0.1:8090 using SystemDatagramSocketProvider 2013-02-14 16:30:38.610/1.610 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=Cluster, member=n/a): This Member(Id=2, Timestamp=2013-02-14 16:30:38.469, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5400, Role=OracleHandsonCoherenceCache, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) joined cluster "cluster:0x47DB" with senior Member(Id=1, Timestamp=2013-02-14 16:30:11.094, Address=127.0.0.1:8088, MachineId=60314, Location=site:,machine:localhost,process:5024, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) 2013-02-14 16:30:38.844/1.844 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0x47DB Group{Address=224.12.1.0, Port=3155, TTL=4} MasterMemberSet( ThisMember=Member(Id=2, Timestamp=2013-02-14 16:30:38.469, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5400, Role=OracleHandsonCoherenceCache) OldestMember=Member(Id=1, Timestamp=2013-02-14 16:30:11.094, Address=127.0.0.1:8088, MachineId=60314, Location=site:,machine:localhost,process:5024, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=2 Member(Id=1, Timestamp=2013-02-14 16:30:11.094, Address=127.0.0.1:8088, MachineId=60314, Location=site:,machine:localhost,process:5024, Role=CoherenceServer) Member(Id=2, Timestamp=2013-02-14 16:30:38.469, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5400, Role=OracleHandsonCoherenceCache) ) MemberId|ServiceVersion|ServiceJoined|MemberState 1|12.1.2|2013-02-14 16:30:11.094|JOINED, 2|12.1.2|2013-02-14 16:30:38.469|JOINED RecycleMillis=1200000 RecycleSet=MemberSet(Size=0 ) ) TcpRing{Connections=[1]} IpMonitor{Addresses=0} 2013-02-14 16:30:38.891/1.891 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Invocation:Management, member=2): Service Management joined the cluster with senior service member 1 2013-02-14 16:30:38.938/1.938 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=main, member=2): Loaded Reporter configuration from "jar:file:/C:/Oracle7/coherence/lib/coherence.jar!/reports/report-group.xml" 2013-02-14 16:30:39.125/2.125 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=DistributedCache:EclipseLinkJPA, member=2): Service EclipseLinkJPA joined the cluster with senior service member 1 2013-02-14 16:30:39.172/2.172 Oracle Coherence GE 12.1.2.0.0 <D4> (thread=DistributedCache:EclipseLinkJPA, member=2): Asking member 1 for primary ownership of PartitionSet{0..127} Hello Cache
In this section, create a cache backed by Oracle Database. This is also referred to as an Oracle Database cache.
To use SQL*Plus and the Oracle Database Express Edition (Oracle XE) to create an Oracle Database cache follow these steps. You must have the database installed on your system.
Invoke SQL*Plus.
Navigate to Start then All Programs then Oracle Database Express Edition and then Run SQL Command Line.
Connect as hr
user with hr
as the password.
connect hr/hr;
Create an Oracle Database table.
Open a text editor and copy the following SQL code. Save it as a file named dbscript.sql
in the /home/oracle/workspace/
folder.
Run the SQL script.
Example 9-5 illustrates the output from the script.
Example 9-5 Running the SQL Script for Creating a Database Table
SQL*Plus: Release 11.2.0.2.0 - Production on Wed Dec 19 17:42:21 2012 Copyright (c) 1982, 2010, Oracle. All rights reserved. SQL> connect hr/hr; Connected. SQL> @/home/oracle/workspace/dbscript.sql Table created 1 row created 1 row created
To create a Java class that connects to the database and retrieves table data:
Create a Java class DBCacheStore
in the Interaction project in Eclipse. See "Creating a Java Class" for detailed information.
Create the code to connect to the database and get table data.
Example 9-6 illustrates a possible implementation of the DBCacheStore
class. Copy the code to the DBCacheStore
application in the Eclipse IDE. The DBCacheStore
application uses Java Database Connectivity (JDBC) to access Oracle Database, but you could use another mechanism, such as Hibernate or Java Data Objects (JDO), instead.
Example 9-6 Database Cache Store Implementation
package com.oracle.handson; import com.tangosol.net.cache.CacheStore;import com.tangosol.util.Base; import java.sql.DriverManager; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; public class DBCacheStore extends Base implements CacheStore { protected Connection m_con; protected String m_sTableName; private static final String DB_DRIVER = "oracle.jdbc.OracleDriver"; private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:XE"; private static final String DB_USERNAME = "hr"; private static final String DB_PASSWORD = "hr"; public DBCacheStore(String sTableName) { m_sTableName = sTableName; configureConnection(); } protected void configureConnection() { try { Class.forName("oracle.jdbc.OracleDriver"); m_con = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); m_con.setAutoCommit(true); } catch (Exception e) { throw ensureRuntimeException(e, "Connection failed"); } } public String getTableName() { return m_sTableName; } public Connection getConnection() { return m_con; } public Object load(Object oKey) { Object oValue = null; Connection con = getConnection(); String sSQL = "SELECT id, value FROM " + getTableName() + " WHERE id = ?"; try { PreparedStatement stmt = con.prepareStatement(sSQL); stmt.setString(1, String.valueOf(oKey)); ResultSet rslt = stmt.executeQuery(); if (rslt.next()) { oValue = rslt.getString(2); if (rslt.next()) { throw new SQLException("Not a unique key: " + oKey); } } stmt.close(); } catch (SQLException e) { throw ensureRuntimeException(e, "Load failed: key=" + oKey); } return oValue; } public void store(Object oKey, Object oValue) { Connection con = getConnection(); String sTable = getTableName(); String sSQL; if (load(oKey) != null) { sSQL = "UPDATE " + sTable + " SET value = ? where id = ?"; } else { sSQL = "INSERT INTO " + sTable + " (value, id) VALUES (?,?)"; } try { PreparedStatement stmt = con.prepareStatement(sSQL); int i = 0; stmt.setString(++i, String.valueOf(oValue)); stmt.setString(++i, String.valueOf(oKey)); stmt.executeUpdate(); stmt.close(); } catch (SQLException e) { throw ensureRuntimeException(e, "Store failed: key=" + oKey); } } public void erase(Object oKey) { Connection con = getConnection(); String sSQL = "DELETE FROM " + getTableName() + " WHERE id=?"; try { PreparedStatement stmt = con.prepareStatement(sSQL); stmt.setString(1, String.valueOf(oKey)); stmt.executeUpdate(); stmt.close(); } catch (SQLException e) { throw ensureRuntimeException(e, "Erase failed: key=" + oKey); } } public void eraseAll(Collection colKeys) { throw new UnsupportedOperationException(); } public Map loadAll(Collection colKeys) { throw new UnsupportedOperationException(); } public void storeAll(Map mapEntries) { throw new UnsupportedOperationException(); } public Iterator keys() { Connection con = getConnection(); String sSQL = "SELECT id FROM " + getTableName(); List list = new LinkedList(); try { PreparedStatement stmt = con.prepareStatement(sSQL); ResultSet rslt = stmt.executeQuery(); while (rslt.next()) { Object oKey = rslt.getString(1); list.add(oKey); } stmt.close(); } catch (SQLException e) { throw ensureRuntimeException(e, "Iterator failed"); } return list.iterator(); } }
Modify the cache configuration file (cache-config.xml
) that you created earlier for the database cache. To connect a cache to a database, you must configure the cachestore-scheme
element with a custom class that implements either the com.tangosol.net.cache.CacheLoader
or com.tangosol.net.cache.CacheStore
interface.
Replace the code in the existing cache-config.xml
file in Eclipse with the cache configuration code for the database cache in Example 9-7.
Example 9-7 Database Cache Configuration File
<?xml version="1.0" encoding="UTF-8" ?> <cache-config> <caching-scheme-mapping> <!-- Caches with names that start with 'DBBacked' will be created as distributed-db-backed. --> <cache-mapping> <cache-name>DBBacked*</cache-name> <scheme-name>distributed-db-backed</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <!-- DB Backed Distributed caching scheme. --> <distributed-scheme> <scheme-name>distributed-db-backed</scheme-name> <service-name>DistributedCache</service-name> <backing-map-scheme> <read-write-backing-map-scheme> <internal-cache-scheme> <class-scheme> <class-name>com.tangosol.util.ObservableHashMap</class-name> </class-scheme> </internal-cache-scheme> <cachestore-scheme> <class-scheme> <class-name>com.oracle.handson.DBCacheStore</class-name> <init-params> <init-param> <param-type>java.lang.String</param-type> <param-value>CATALOG</param-value> </init-param> </init-params> </class-scheme> </cachestore-scheme> <read-only>false</read-only> <!-- To make this a write-through cache just change the value below to 0 (zero) --> <write-delay-seconds>0</write-delay-seconds> </read-write-backing-map-scheme> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> </caching-schemes> </cache-config>
In the cache configuration file, you have done the following:
Defined a cache name pattern DBBacked*
, which is mapped to a distributed caching scheme distributed-db-backed
.
Specified the CacheStore
scheme in the distributed scheme using the class coherence.DBCacheStore
, which implements the CacheStore
interface.
Specified for the DBCacheStore
class an init
parameter for the database table that is at the back end of the cache. The table name is specified in the init-param
element. The DBCacheStore
class performs database operations such as reading and writing cache entries.
Specified a read-write-backing-map-scheme
as the backing map. This scheme defines a backing map, which provides a size-limited cache of a persistent store. Here, by setting the write-delay-seconds
parameter to 0, you specify the write-through mechanism.
Table 9-2 describes the types of read/write caching that you can use with Coherence.
Table 9-2 Types of Read/Write Caching Supported by Coherence
Types of Read/Write Caching | Action |
---|---|
read-through |
A cache entry is read into a cache from the database when required and made available to an application. |
write-through |
Updates to cache entries are synchronized with the database without a delay. |
refresh-ahead |
Cache entries are refreshed periodically. |
write-behind |
Updates to cache entries are asynchronously written to a database after a delay specified in the |
Create a Java class DatabaseCache
for the database cache in the Interaction project in Eclipse. The class must contain a main
method. See "Creating a Java Class" for detailed information.
In the class file, provide the code to add a cache entry, query a database cache, and retrieve a cache entry. Add the following methods: createCache()
, addEntry()
, retrieveEntry()
, eraseEntry()
, and queryCache()
. Example 9-8 illustrates a possible implementation.
Example 9-8 Implementation for the Database Cache Class File
package com.oracle.handson; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import com.tangosol.net.cache.ContinuousQueryCache; import com.tangosol.util.Filter; import com.tangosol.util.extractor.IdentityExtractor; import com.tangosol.util.filter.LikeFilter; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; public class DatabaseCache { NamedCache cache; public DatabaseCache() { } public void createCache() { cache = CacheFactory.getCache("DBBackedCache"); } public void addEntry() { cache.put(new String("catalog3"), new String("Tuning Grid Management")); cache.put(new String("catalog4"), new String("Tuning Coherence")); cache.put(new String("catalog5"), new String("Tuning Database")); } public void retrieveEntry() { System.out.println((String) cache.get( "catalog3")); } public void eraseEntry() { cache.remove(new String("catalog3")); } public void queryCache() { Filter filter = new LikeFilter(IdentityExtractor.INSTANCE, "Tuning%", '\\', true); HashSet hashSet=new HashSet(); hashSet.add(new String("catalog3")); hashSet.add(new String("catalog4")); hashSet.add(new String("catalog5")); Map map=cache.getAll(hashSet); Set results = cache.entrySet(filter); for (Iterator i = results.iterator(); i.hasNext();) { Map.Entry e = (Map.Entry) i.next(); System.out.println("Catalog ID: "+e.getKey() + ", Title: "+e.getValue()); } } public static void main(String[] args) { DatabaseCache databaseCache = new DatabaseCache(); databaseCache.createCache(); databaseCache.addEntry(); databaseCache.queryCache(); } }
Note the following features of the database cache class file:
A NamedCache
object is created using the getCache
method of the CacheFactory
class in the createCache
method.
NamedCache cache = CacheFactory.getCache("DBBackedCache");
The DBBackedCache
matches the cache pattern DBBacked*
and is, therefore, mapped to a distributed caching scheme distributed-db-backed
in the cache-config.xml
file. Add a cache entry using the put()
method of the NamedCache
object.
cache.put(new String("catalog3"), new String("Tuning Grid Management"));
Because the write-through mechanism is used, the new cache entry gets synchronized with the database; a new row is added to the CATALOG
table. Comment out all the methods except the createCache
and addEntry
methods.
When the put
method is invoked, the store
method, which maps the new cache entry to the database table CATALOG
using JDBC, gets invoked in the DBCacheStore
class. The output from the Coherence application is displayed in the Log window and a new cache entry is added. The output shows that the operational configuration deployment descriptor is loaded, the cache configuration is loaded, a new cluster is created, and the DistributedCache
service has joined the cluster.
The new cache entry can be removed with the remove
method of the NamedCache
object.
cache.remove(new String("catalog3"));
Bulk uploading of cache entries is performed using the putAll
method.
A cache entry is retrieved using the get
method of the NamedCache
object. For example, retrieving the cache entry for ID catalog1
:
System.out.println((String) cache.get("catalog1"));
When the get()
method is invoked, the load
method, which retrieves database table data using JDBC, gets invoked in the DBCacheStore
class.
Bulk retrieval is performed using the getAll
method of the NamedCache
object.
Coherence supports searching for cache entries based on a search criteria using filters. Coherence filters are available in the com.tangosol.util.filter
package. In Oracle Coherence Enterprise Edition and Grid Edition, indexes can be added to the Coherence cache to improve performance. You query the database cache using a LikeFilter
filter, which matches cache entries with a specified pattern. To query a database cache, the cache entries must be created before querying, and the cache entries must be retrieved into the cache using the get()
or getAll()
method before a query using a filter can be performed. Therefore, you can retrieve database data and create a collection of cache entries using the getAll()
method.
HashSet hashSet=new HashSet(); hashSet.add(new String("catalog1")); hashSet.add(new String("catalog2")); hashSet.add(new String("catalog3")); Map map=cache.getAll(hashSet);
Create a LikeFilter
filter to search for cache entries starting with Tuning
.
Filter filter = new LikeFilter(IdentityExtractor.INSTANCE, "Tuning%", '\\', true);
Query the database cache using the entrySet()
method with the LikeFilter
filter.
Set results = cache.entrySet(filter);
Iterate over the results of the query. Display the key and value of the cache entries that are retrieved.
for (Iterator i = results.iterator(); i.hasNext();) { Map.Entry e = (Map.Entry) i.next(); System.out.println("Catalog ID: "+e.getKey() + ", Title: "+e.getValue()); }
Coherence supports continuous query using the com.tangosol.net.cache.ContinuousQueryCache
class. A continuous query is a query that is kept up-to-date using a continuous query cache. In a ContinuousQueryCache
, the results of a query are updated using event listeners on events that could change the results of the query. Create a ContinuousQueryCache
object using the NamedCache
object and the LikeFilter
object.
ContinuousQueryCache queryCache = new ContinuousQueryCache(cache, filter);
Create a result set by using the entrySet()
method.
Set results = queryCache.entrySet(filter);
To run the Oracle Database cache application:
Stop any running cache servers. See "Stopping Cache Servers" for more information.
Start the cache server (JPAServer
). Right click the project and select Run As then Run Configurations. In the Run Configurations dialog box, select JPACacheServer to display its configuration. Click Run.
Create a run configuration for the DatabaseCache
program.
In the Run Configurations dialog box, click the New launch configuration icon.
Enter DatabaseCacheClient
in the Name field. Ensure that Interaction
is in the Project field and com.oracle.handson.DatabaseCache
is in the Main class field.
In the Coherence tab, enter the path to the cache configuration file in the Cache configuration descriptor field: C:\home\oracle\workspace\Interaction\cache-config.xml
. Select Local storage: Disabled (cache client). Enter a unique value, such as 3155
, in the Cluster port field.
Open the Classpath tab. The Classpath tab should look similar to Figure 9-4.
Figure 9-4 Classpath for the DatabaseCache Program
Click Apply then Run.
Example 9-9 illustrates the expected results.
Example 9-9 Output of the DatabaseCache Program
... Group{Address=224.12.1.0, Port=3155, TTL=4} MasterMemberSet( ThisMember=Member(Id=2, Timestamp=2013-02-14 17:55:03.149, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5544, Role=OracleHandsonDatabaseCache) OldestMember=Member(Id=1, Timestamp=2013-02-14 17:49:57.125, Address=127.0.0.1:8088, MachineId=60314, Location=site:,machine:localhost,process:5644, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=2 Member(Id=1, Timestamp=2013-02-14 17:49:57.125, Address=127.0.0.1:8088, MachineId=60314, Location=site:,machine:localhost,process:5644, Role=CoherenceServer) Member(Id=2, Timestamp=2013-02-14 17:55:03.149, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5544, Role=OracleHandsonDatabaseCache) ) MemberId|ServiceVersion|ServiceJoined|MemberState 1|12.1.2|2013-02-14 17:49:57.125|JOINED, 2|12.1.2|2013-02-14 17:55:03.149|JOINED RecycleMillis=1200000 RecycleSet=MemberSet(Size=0 ) ) TcpRing{Connections=[1]} IpMonitor{Addresses=0} 2013-02-14 17:55:03.532/1.719 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Invocation:Management, member=2): Service Management joined the cluster with senior service member 1 2013-02-14 17:55:03.563/1.750 Oracle Coherence GE 12.1.2.0.0 <Info> (thread=main, member=2): Loaded Reporter configuration from "jar:file:/C:/Oracle7/coherence/lib/coherence.jar!/reports/report-group.xml" 2013-02-14 17:55:03.782/1.969 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=DistributedCache, member=2): Service DistributedCache joined the cluster with senior service member 1 Catalog ID: catalog3, Title: Tuning Grid Management Catalog ID: catalog4, Title: Tuning Coherence Catalog ID: catalog5, Title: Tuning Database
Example 9-10 illustrates the cache server response to the DatabaseCache
program.
Example 9-10 Cache Server Response to the DatabaseCache Program
... Started DefaultCacheServer... 2013-02-14 17:55:03.250/307.297 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2013-02-14 17:55:03.149, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5544, Role=OracleHandsonDatabaseCache) joined Cluster with senior member 1 2013-02-14 17:55:03.532/307.579 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Invocation:Management, member=1): Member 2 joined Service Management with senior member 1 2013-02-14 17:55:03.813/307.860 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=DistributedCache, member=1): Member 2 joined Service DistributedCache with senior member 1 2013-02-14 17:55:06.750/310.797 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Cluster, member=1): TcpRing disconnected from Member(Id=2, Timestamp=2013-02-14 17:55:03.149, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5544, Role=OracleHandsonDatabaseCache) due to a peer departure; removing the member. 2013-02-14 17:55:06.750/310.797 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2013-02-14 17:55:06.75, Address=127.0.0.1:8090, MachineId=60314, Location=site:,machine:localhost,process:5544, Role=OracleHandsonDatabaseCache) left Cluster with senior member 1 2013-02-14 17:55:06.766/310.813 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=Invocation:Management, member=1): Member 2 left service Management with senior member 1 2013-02-14 17:55:06.766/310.813 Oracle Coherence GE 12.1.2.0.0 <D5> (thread=DistributedCache, member=1): Member 2 left service DistributedCache with senior member 1
If you receive any exceptions, such as the following:
java.lang.IllegalArgumentException: No scheme for cache: "cachename,
You may be able to remove them by editing the cache-config.xml
file and replacing DBBacked*
in the <cache-name>
element with *
. Re-run the DatabaseCache
application in Eclipse. You should not see any exceptions.
Note that because you are using a write-through cache, the database table is also updated. From the SQL prompt, enter the following code:
select * from hr.catalog;
Example 9-11 illustrates the results.
Example 9-11 Output from the SELECT Statement
SQL> select * from hr.catalog; ID ------------------------- VALUE ------------------------------------------------------------------------------- catalog1 Tuning Undo Tablespace catalog2 Tuning Your View Objects catalog3 Tuning Grid Management ID ------------------------- VALUE ------------------------------------------------------------------------------- catalog4 Tuning Coherence catalog5 Tuning Database SQL>