11/37

# 4 Building Your First Extend Client

This chapter demonstrates basic tasks that are required to build and run Coherence*Extend clients. The example client 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 as well. See the `/examples` directory in both the C++ and .NET distribution for specific examples for these technologies.

The following sections are included in this chapter:

- Overview

- Step 1: Configure the Cluster Side

- Step 2: Configure the Client Side

- Step 3: Create the Sample Client

- Step 4: Start the Cache Server Process

- Step 5: Run the Application

## Overview

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 in order 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.

## 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"?>
       <!DOCTYPE cache-config SYSTEM "cache-config.dtd">
       <cache-config>
          <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>
                <thread-count>5</thread-count>
                <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.

## 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"?>
       <!DOCTYPE cache-config SYSTEM "cache-config.dtd">

       <cache-config>
         <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.

## Step 3: Create the Sample Client

Example 4-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 4-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 of this, the single result of the execution will be keyed by the local `Member`, which will be 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).

## 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\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

## 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.