3 Building Your First Extend Client

This chapter demonstrates basic tasks that are required to build and run Coherence*Extend clients. The example client that is used in this chapter is a Java-based extend client; however, the concepts that are demonstrated are common to both C++ and .NET extend clients. For complete C++ and .NET examples, see the Coherence Examples that are distributed as part of the Coherence for Java distribution.

This chapter includes the following sections:

3.1 Overview of the Extend Example

This chapter is organized into a set of steps that are used to create, configure, and run a basic Coherence*Extend client. The steps demonstrate many fundamental Coherence*Extend concepts, such as: configuring an extend proxy, configuring a remote cache, configuring the remote invocation service, and using the Coherence API.

Coherence for Java must be installed to complete the steps. For simplicity and ease of deployment, the client and cache server in this example are run on the same computer. Typically, extend clients and cache servers are located on separate systems.

3.2 Step 1: Configure the Cluster Side

The example extend client requires an extend proxy and cache to be configured in the cluster's cache configuration deployment descriptor. The extend proxy is configured to accept client TCP/IP communication on localhost and port 9099. A distributed cache named dist-extend is defined and is used to store client data in the cluster.

To configure the cluster side:

  1. Create an XML file named example-config.xml.

  2. Copy the following XML to the 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>dist-extend</cache-name>
             <scheme-name>extend</scheme-name>
          </cache-mapping>
       </caching-scheme-mapping>
    
       <caching-schemes>
          <distributed-scheme>
             <scheme-name>extend</scheme-name>
             <lease-granularity>member</lease-granularity>
             <backing-map-scheme>
                <local-scheme/>
             </backing-map-scheme>
             <autostart>true</autostart>
          </distributed-scheme>
    
          <proxy-scheme>
             <service-name>ExtendTcpProxyService</service-name>
             <acceptor-config>
                <tcp-acceptor>
                   <local-address>
                      <address>localhost</address>
                      <port>9099</port>
                   </local-address>
                </tcp-acceptor>
             </acceptor-config>
             <autostart>true</autostart>
          </proxy-scheme>
       </caching-schemes>
    </cache-config>
    
  3. Save and close the file.

3.3 Step 2: Configure the Client Side

The example extend client requires a remote cache scheme and a remote invocation scheme. The remote cache scheme must define a cache on the cluster that is used to cache data and must provide the address and port of the extend proxy to which the client connects. For this example (based on Step 1), the remote cache scheme is configured to use the dist-extend cache and connects to an extend proxy that is located on localhost and port 9099.

The example extend client queries the remote cache and therefore requires a remote invocation scheme. The remote invocation scheme must also define the host and port of the extend proxy to which the client connects.

To configure the client side:

  1. Create an XML file named example-client-config.xml.

  2. Copy the following XML to the 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>dist-extend</cache-name>
          <scheme-name>remote</scheme-name>
        </cache-mapping>
      </caching-scheme-mapping>
      
      <caching-schemes>
        <remote-cache-scheme>
          <scheme-name>remote</scheme-name>
          <service-name>ExtendTcpCacheService</service-name>
          <initiator-config>
            <tcp-initiator>
              <remote-addresses>
                <socket-address>
                  <address>localhost</address>
                  <port>9099</port>
                </socket-address>
              </remote-addresses>
              <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
              <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
          </initiator-config>
        </remote-cache-scheme>
     
        <remote-invocation-scheme>
          <scheme-name>extend-invocation</scheme-name>
          <service-name>ExtendTcpInvocationService</service-name>
          <initiator-config>
            <tcp-initiator>
              <remote-addresses>
                <socket-address>
                  <address>localhost</address>
                  <port>9099</port>
                </socket-address>
              </remote-addresses>
              <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
              <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
          </initiator-config>
        </remote-invocation-scheme>
      </caching-schemes>
    </cache-config>
    
  3. Save and close the file.

3.4 Step 3: Create the Sample Client

Example 3-1 is a simple client that increments an Integer value in a remote cache using the CacheService and then retrieves the value from the cache using the InvocationService. Lastly, the client writes the value to the system output before exiting.

Note:

This example could also be run on a Coherence node (that is, within the cluster) verbatim. The fact that operations are being sent to a remote cluster node over TCP/IP is completely transparent to the client application.

To create the sample application:

  1. Create a text file.

  2. Copy the following Java code to the file:

    Example 3-1 Sample Coherence*Extend Application

    import com.tangosol.net.AbstractInvocable;
    import com.tangosol.net.CacheFactory;
    import com.tangosol.net.InvocationService;
    import com.tangosol.net.NamedCache;
    import java.util.Map;
    
    public class TestClient {
        public static void main(String[] asArgs)
                throws Throwable
            {
            NamedCache cache  = CacheFactory.getCache("dist-extend");
            Integer IValue = (Integer) cache.get("key");
            if (IValue == null)
                {
                IValue = new Integer(1);
                }
            else
                {
                IValue = new Integer(IValue.intValue() + 1);
                }
            cache.put("key", IValue);
     
            InvocationService service = (InvocationService)
                    CacheFactory.getConfigurableCacheFactory()
                        .ensureService("ExtendTcpInvocationService");
     
            Map map = service.query(new AbstractInvocable()
                {
                    public void run()
                        {
                         setResult(CacheFactory.getCache("dist-extend").get("key"));
                        }
                }, null);
     
            Integer IValue1 = (Integer) map.get(service.getCluster().
                getLocalMember());
            System.out.print("The value of the key is " + IValue1);
            }
    }
    
  3. Save the file as TestClient.java and close the file.

  4. Compile TestClient.java:

    javac -cp .;COHERENCE_HOME\lib\coherence.jar TestClient.java
    

Coherence*Extend InvocationService

Since, by definition, a Coherence*Extend client has no direct knowledge of the cluster and the members running within the cluster, the Coherence*Extend InvocationService only allows Invocable tasks to be executed on the JVM to which the client is connected. Therefore, you should always pass a null member set to the query() method. As a consequence, the single result of the execution is keyed by the local Member, which is null if the client is not part of the cluster. This Member can be retrieved by calling service.getCluster().getLocalMember(). Additionally, the Coherence*Extend InvocationService only supports synchronous task execution (that is, the execute() method is not supported).

3.5 Step 4: Start the Cache Server Process

Extend Proxies are started as part of a cache server process(DefaultCacheServer). The cache server must be configured to use the cache configuration that was created in Step 1. In addition, the cache server process must be able to find the TestClient application on the classpath at run time.

The following command line starts a cache server process and explicitly names the cache configuration file created in Step 1 by using the tangosol.coherence.cacheconfig system property:

java -cp COHERENCE_HOME\lib\coherence.jar;PATH_TO_CLIENT -Dtangosol.coherence.cacheconfig=PATH\example-config.xml com.tangosol.net.DefaultCacheServer

Check the console output to verify that the proxy service is started. The output message is similar to the following:

(thread=Proxy:ExtendTcpProxyService:TcpAcceptor, member=1): TcpAcceptor now
 listening for connections on 192.168.1.5:9099

3.6 Step 5: Run the Application

The TestClient application is started using the java command and must be configured to use the cache configuration file that was created in Step 2.

The following command line runs the application and assumes that the TestClient class is located in the current directory. The cache configuration file is explicitly named using the tangosol.coherence.cacheconfig system property:

java -cp .;COHERENCE_HOME\lib\coherence.jar -Dtangosol.coherence.cacheconfig=PATH\example-client-config.xml TestClient

The output displays (among other things) that the client successfully connected to the extend proxy TCP address and the current value of the key in the cache. Run the client again to increment the key's value.