Server-Managed Caching Example

Error formatting macro: composition-setup: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil

Server-managed caching is the model for vertical scalability. You isolate data management in a relatively small number of cache servers and connect to them from thin clients, so many clients benefit from the management resources of only a few servers.

GemFire's client/server caching gives you dynamic server pool management, server load balancing and conditioning, logical server grouping, and automatic server failover for high availability.

The servers run in one distributed system. Each client runs in its own separate distributed system. The clients forward data requests to the servers that their caches cannot fulfill. The clients also forward client-side updates. Additionally, clients can register interest in server-side data, either by specifying the data keys or by registering queries that run continuously. In both cases, updates on the server side are automatically forwarded to the client.

Read more about client/server caching.

Running the Example

This example shows a simple client/server installation with one worker client, that gets and puts data in its cache, and one consumer client, that just receives events from the server. Both clients are connected to a single cache server. The worker client requests data from the server. If the server does not have the data cached, it automatically runs a data loader to get it. The server returns the data to the worker client. The worker client then updates the data in its cache. The update is automatically distributed to the server. The server forwards all changes made by the worker client to the consumer client. Both clients have an asynchronous listener that reports local caching activity to standard out, so you can see what is happening.

To run this example, you must have terminal sessions configured for the QuickStart examples, as described in Setting Up the Environment.
  1. In one session, start the GemFire cacheserver:
    $ cacheserver start cache-xml-file=xml/Server.xml
    

    The server starts in the background, sending information to the screen:

    Starting CacheServer with pid: 11283
    CacheServer pid: 11283 status: running
    $
    
  2. In the same session, start the consumer client:  
    $ java quickstart.ClientConsumer all-keys
    
  3. When the consumer client asks you to start the worker client, start it in another session:
    $ java quickstart.ClientWorker
    
  4. Follow the instructions on the screens, noting the listener output from each client. When both clients have exited, stop the cacheserver:  
    $ cacheserver stop
    

Example Listings

Program and cache configuration file listings for the clients and the server, including the loader and listener declared in the Server.xml and Client.xml files. (The server is a GemFire cacheserver process and does not have a java listing.)

Error formatting macro: deck: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
<?xml version="1.0"?>

<!-- Server.xml
     Configures a cache to serve caching clients at port 40405.
     The example region also is configured with a loader. 
-->

<!DOCTYPE cache PUBLIC
  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
  "http://www.gemstone.com/dtd/cache6_5.dtd">
<cache>
    <cache-server port="40404"/>
    <region name="exampleRegion">
      <region-attributes refid="REPLICATE">
        <cache-loader>
          <class-name>quickstart.SimpleCacheLoader</class-name>
        </cache-loader>
      </region-attributes>
    </region>
</cache>
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
<?xml version="1.0"?>
<!DOCTYPE client-cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
    "http://www.gemstone.com/dtd/cache6_5.dtd">

<!--
  | Client.xml
  |
  | Configures a region as a client region in a client/server cache. The 
  | region's pool connects to a cacheserver listening on port 40404.
 -->
<client-cache>
	<pool name="client" subscription-enabled="true">
		<server host="localhost" port="40404" />
	</pool>

	<region name="exampleRegion">
		<region-attributes refid="CACHING_PROXY">
			<cache-listener>
				<class-name>quickstart.SimpleCacheListener</class-name>
			</cache-listener>
		</region-attributes>
	</region>
</client-cache>
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.Region;

/**
 * In this example of client/server caching, the server listens on a port for client requests and updates. The client
 * forwards all data requests it cannot fulfill to the server and is configured to update the server as well. Please
 * refer to the quickstart guide for instructions on how to run this example.
 *
 * @author GemStone Systems, Inc.
 *
 * @since 5.8
 */
public class ClientWorker {

	public static final String EXAMPLE_REGION_NAME = "exampleRegion";

	public static void main(String[] args) throws Exception {

		System.out.println("Connecting to the distributed system and creating the cache.");
		// Create the cache which causes the cache-xml-file to be parsed
		ClientCache cache = new ClientCacheFactory()
                  .set("name", "ClientWorker")
                  .set("cache-xml-file", "xml/Client.xml")
                  .create();

		// Get the exampleRegion
		Region<String, String> exampleRegion = cache.getRegion(EXAMPLE_REGION_NAME);
		System.out.println("Example region \"" + exampleRegion.getFullPath() + "\" created in cache.");
		System.out.println();
		System.out.println("Getting three values from the cache server.");
		System.out.println("This will cause the server's loader to run, which will add the values");
		System.out.println("to the server cache and return them to me. The values will also be");
		System.out.println("forwarded to any other client that has subscribed to the region.");

		// Get three values from the cache
		for (int count = 0; count < 3; count++) {
			String key = "key" + count;
			System.out.println("Getting key " + key);
			exampleRegion.get(key);
		}

		System.out.println("Note the other client's region listener in response to these gets.");
		System.out.println("Press Enter to continue.");
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		bufferedReader.readLine();

		System.out.println("Changing the data in my cache - all destroys and updates are forwarded");
		System.out.println("through the server to other clients. Invalidations are not forwarded.");

		// Update one value in the cache
		System.out.println("Putting new value for key0");
		exampleRegion.put("key0", "ClientValue0");

		// Invalidate one entry in the cache
		System.out.println("Invalidating key1");
		exampleRegion.invalidate("key1");

		// Destroy one entry in the cache
		System.out.println("Destroying key2");
		exampleRegion.destroy("key2");

		// Close the cache and disconnect from GemFire distributed system
		System.out.println("Closing the cache and disconnecting.");
		cache.close();

		System.out.println("In the other session, please hit Enter in the Consumer client");
		System.out.println("and then stop the cacheserver with 'cacheserver stop'.");
	}
}
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.Region;

/**
 * In this example of client/server caching, the server listens on a port for client requests and updates. A
 * clientworker forwards data requests to the server and sends data updates to the server.
 *
 * This client is a consumer. It registers interest in events on the server and the server sends automatic updates for
 * the events.
 *
 * Please refer to the quickstart guide for instructions on how to run this example.
 *
 * @author GemStone Systems, Inc.
 *
 * @since 5.8.
 */
public class ClientConsumer {

	public static final String USAGE = "Usage: java ClientConsumer <register-interest-type>\n"
			+ "  register-interest-type may be one of the following:\n"
			+ "    all-keys    Register interest in all keys on the server\n"
			+ "    keyset      Register interest in a set of keys on the server\n"
			+ "    regex       Register interest in keys on the server matching a regular expression\n";

	public static final String EXAMPLE_REGION_NAME = "exampleRegion";

	private static enum RegisterInterestType {
		ALL_KEYS, KEYSET, REGEX
	}

	public static void main(String[] args) throws Exception {

		if (args.length != 1) {
			System.out.println(USAGE);
			System.exit(1);
		}

		RegisterInterestType registerInterestType;
		if (args[0].equals("all-keys")) {
			registerInterestType = RegisterInterestType.ALL_KEYS;
		} else if (args[0].equals("keyset")) {
			registerInterestType = RegisterInterestType.KEYSET;
		} else if (args[0].equals("regex")) {
			registerInterestType = RegisterInterestType.REGEX;
		} else {
			registerInterestType = null;
			System.out.println(USAGE);
			System.exit(2);
		}

		// Subscribe to the indicated key set
		System.out.println("Connecting to the distributed system and creating the cache.");
		// Create the cache which causes the cache-xml-file to be parsed
		ClientCache cache = new ClientCacheFactory()
                  .set("name", "ClientConsumer")
                  .set("cache-xml-file", "xml/Client.xml")
                  .create();

		// Get the exampleRegion which is a subregion of /root
		Region<String,?> exampleRegion = cache.getRegion(EXAMPLE_REGION_NAME);
		System.out.println("Example region \"" + exampleRegion.getFullPath() + "\" created in cache. ");

		switch (registerInterestType) {
		case ALL_KEYS:
			System.out.println("Asking the server to send me all data additions, updates, and destroys. ");
			exampleRegion.registerInterest("ALL_KEYS");
			break;
		case KEYSET:
			System.out.println("Asking the server to send me events for data with these keys: 'key0', 'key1'");
			exampleRegion.registerInterest("key0");
			exampleRegion.registerInterest("key1");
			break;
		case REGEX:
			System.out.println("Asking the server to register interest in keys matching this");
			System.out.println("regular expression: 'k.*2'");
			exampleRegion.registerInterestRegex("k.*2");
			break;
		default:
			// Can't happen
			throw new RuntimeException();
		}

		System.out.println("The data region has a listener that reports all changes to standard out.");
		System.out.println();
		System.out.println("Please run the worker client in another session. It will update the");
		System.out.println("cache and the server will forward the updates to me. Note the listener");
		System.out.println("output in this session.");
		System.out.println();
		System.out.println("When the other client finishes, hit Enter to exit this program.");

		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		bufferedReader.readLine();

		System.out.println("Closing the cache and disconnecting.");
		cache.close();
	}
}
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.Declarable;
import com.gemstone.gemfire.cache.LoaderHelper;
import java.util.Properties;

public class SimpleCacheLoader implements CacheLoader<String,String>, Declarable {
  
  public String load(LoaderHelper<String,String> helper) {
    String key = helper.getKey();
    System.out.println("    Loader called to retrieve value for " + key);
    
    // Create a value using the suffix number of the key (key1, key2, etc.)
    return "LoadedValue" + (Integer.parseInt(key.substring(3)));
  }
  
  public void close() {
    // do nothing
  }
  
  public void init(Properties props) {
    // do nothing
  }
}
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import com.gemstone.gemfire.cache.Declarable;
import com.gemstone.gemfire.cache.EntryEvent;
import com.gemstone.gemfire.cache.RegionEvent;
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
import java.util.Properties;

public class SimpleCacheListener<K,V> extends CacheListenerAdapter<K,V> implements Declarable {

  public void afterCreate(EntryEvent<K,V> e) {
    System.out.println("    Received afterCreate event for entry: " +
      e.getKey() + ", " + e.getNewValue());
  }
  
  public void afterUpdate(EntryEvent<K,V> e) {
    System.out.println("    Received afterUpdate event for entry: " +
      e.getKey() + ", " + e.getNewValue());
  }
  
  public void afterDestroy(EntryEvent<K,V> e) {
    System.out.println("    Received afterDestroy event for entry: " +
      e.getKey());
  }

  public void afterInvalidate(EntryEvent<K,V> e) {
    System.out.println("    Received afterInvalidate event for entry: " +
      e.getKey());
  }

  public void afterRegionLive(RegionEvent e) {
    System.out.println("    Received afterRegionLive event, sent to durable clients after \nthe server has finished replaying stored events.  ");
  }

  public void init(Properties props) {
    // do nothing
  }

}

Related Javadocs

ClientCacheFactory, Pool, REPLICATE in RegionShortcut, and CACHING_PROXY in ClientRegionShortcut.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.