The clientServerConfigs examples use examples/cacheRunner to demonstrate the common recommended bridge server and bridge client configurations for client/server caching. The example configurations are located under the GemFire installation in examples/dist/clientServerConfigs. For information on client/server
caching, see the GemFire Enterprise Distributed Caching Programmer's Guide and
the online Java documentation under com.gemstone.gemfire.cache.util.
examples/dist/clientServerConfigs
directory contains the XML cache configuration files for the bridge server and client. There are two bridge server configuration files, one, bs_notify_all.xml, that configures the server for the notify-all client entry update behavior and the other, bs_notify_by_subscription.xml, that configures the server for notify-by-subscription behavior. There is one client file, bridge_client.xml.
In these files:
BridgeLoader and BridgeWriter as the region's loader and writer attributes. These
are configured to access the server process running on the local host on port 40404.
Thus, the client and server are configured to talk to each other.bridge-server port in both of the bs_notify*.xml files, and for the endpoints port settings for both the bridge loader and bridge writer in bridge_client.xml.
clientServerConfigs directory also contains subdirectories with gemfire.properties files in them.
These provide the distributed system configurations for the various client/server
caching models. They specify the server and client mcast-port settings that
define the distributed systems the VMs belong to or, for the standalone client, specify that the VM does not belong to any distributed system.
mcast-port settings to
avoid conflicting with ports that are already in use on your system. If you do, make sure
the setting in client_separate_dist_sys/gemfire.properties
is still different from the setting in server/gemfire.properties.
Do not change any of the settings in client_standalone/gemfire.properties
Follow these instructions to run the configuration examples.
Environment Setup
You will need at least two terminal sessions, one to run a bridge server VM and one to run
a bridge client VM. These examples show one server and one client running at
a time, but you can increase the number of either. However many you run,
you need a separate terminal session for each. For each session, make sure the environment is set
according to the instructions in examples/EnvSetup.html.
Change directory to examples/dist/clientServerConfigs.
The rest of the example instructions are relative to this directory.
Running the Server
To start the server, cd to the server subdirectory and
run the server either with the notify-by-subscription XML file or the notify-all file:
java cacheRunner.CacheRunner ../bs_notify_by_subscription.xml
or
java cacheRunner.CacheRunner ../bs_notify_all.xml
This starts the cache runner program with the server's XML file and the current working directory's gemfire.properties file settings. The xml file defines a region named /root/bridge_region and gives it a loader and a listener. The different configuration files determine how the server updates the client for server-side entry modifications. We'll see more about this at the end of the example.
Once the server has started, you will see this prompt:
/root>
Enter the commands listed here in bold (most of the output is included in this listing). You
will define a value, value1, for the first entry, entry1, and you will cause a loader
invocation by getting an entry, entry2, that doesn't exist in the cache.
The loader is programmed to return a value that is the string equivalent of the key. The listener reports on all entry creation and specifies whether the value came from a load operation.
/root> chrgn bridge_region
/root/bridge_region> put entry1 value1
CacheListener.afterCreate EntryEvent on region /root/bridge_region
[distributed, not expiration, local origin]
[not load]
Key: entry1
Old value: null
New value: value1
/root/bridge_region> get entry2
CacheListener.afterCreate EntryEvent on region /root/bridge_region
[distributed, not expiration, local origin]
[local load]
Key: entry2
Old value: null
New value: entry2
entry2 -> String: "entry2"
/root/bridge_region> ls
Region Entries:
entry2 -> String: "entry2"
entry1 -> byte[]: "value1"
Subregions:
/root/bridge_region>
Leave this running. The listener will report
when there are modifications to the server's bridge_region.
cd to it, and run the following:
java cacheRunner.CacheRunner ../bridge_client.xml
Once the client is started, enter the commands below. You can skip the registerInterest step if you are running the server with the notify-all XML file.
/root> chrgn bridge_region
/root/bridge_region> registerInterest entry1
Interest registered in entry1
/root/bridge_region> get entry1
entry1 -> byte[]: "value1"
/root/bridge_region> get entry2
entry1 -> byte[]: "entry2"
/root/bridge_region> des entry2
/root/bridge_region> get entry3
entry3 -> String: "entry3"
/root/bridge_region> put entry1 valueFromClient
/root/bridge_region>
As you are running these commands, note the output in the server VM.
When you ask for an entry that exists in the server, like entry1, it is passed directly
from the server cache. When you ask for an entry that the
server does not have, like entry3, it invokes its loader, updates the server cache,
and returns the result. When you put an entry on the client side, the new value is passed up to the server. You can run 'ls' on both the server and client to verify the cache contents. Both sides should report the same thing:
/root/bridge_region> ls
Region Entries:
entry2 -> String: "entry2"
entry3 -> String: "entry3"
entry1 -> byte[]: "valueFromClient"
With notify-by-subscription, the server automatically sends entry update notification, with values, for the entries the client has registered interest in. For entries that are not registered, the client can get values explicitly, but receives no updates for server-side update operations. With notify-all, the server automatically sends entry update notifications to the client as invalidations for all entries, with no values passed. Then if the client needs the value, the get operation will retrieve it from the server.
To see this, from the server side, update entry1 and entry2:
/root/bridge_region> put entry1 serverValue1
...
/root/bridge_region> put entry2 serverValue2
...
Final Client Cache for Notify-By-Subscription
For notify-by-subscription, the client side entry1 has the new server value. This is because the client registered interest in entry1 at the beginning of this session. The other entry, entry2, is not changed, so at this point it does not match the server cache. Since the client did not register interest in it, the server does not propagate any information on the server-side modification.
To see this, run 'ls' on the client side:
/root/bridge_region> ls
entry2 -> String: "entry2"
entry3 -> String: "entry3"
entry1 -> byte[]: "serverValue1"
Final Client Cache for Notify-All
For notify-all, both entry1 and entry2 are invalidated on the client.
To see this, run 'ls' on the client side:
/root/bridge_region> ls
entry2 -> String: No value in cache.
entry3 -> String: "entry3"
entry1 -> byte[]: No value in cache.
Running the Server and Client with Authentication/Authorization enabled
Follow these instructions to run the example with Authentication/Authorization enabled.
server and client_standalone/client_separate_dist_sys directories.
# set to use the sample implementation of LDAP server based authentication. security-client-authenticator=templates.security.LdapUserAuthenticator.create # should point to a valid LDAP server. security-ldap-server=ldap # should be the baseDN details (top level directory tree) of LDAP server mentioned above. security-ldap-basedn=ou=users,dc=gemstone,dc=com # set to use the sample implementation of Xml based authorization. security-client-accessor=templates.security.XmlAuthorization.create # provide the xml config file for XmlAuthorization accessor mentioned above. # modify the usernames in the provided XML to match those recognized by the # LDAP server mentioned above. security-authz-xml-uri=authz-ldap.xml
# set to use the username/password based sample implementation of AuthInitialize. security-client-auth-init=templates.security.UserPasswordAuthInit.create # provide the authentication credentials such as a username and password # these should be valid combinations recognized by the LDAP server mentioned # on the server side. security-username=gemfire security-password=gemfire
Running the Server and Running the Client sections after adding the above mentioned properties to gemfire.properties.
Additional Example Scenarios
There are a number of scenarios you can explore with this basic setup. You might add
other clients and see the effect on client peers when a client updates an entry. You could see how the behavior changes when the bridge writer's cache callback is
disabled (in the client's XML configuration file, change the true value
to false for the "establishCallbackConnection" parameter).