Examples of configuration

This section contains several examples of configuring various schemes of Cluster4Spring remoting via Spring configuration files. Please note that it is possible to use two forms of remote proxy factory configuration - one that uses generic proxy factory class or one that uses concrete classes of remote proxy factories (shorter form).

Generic Configuration of Remote Proxy

While it is possible to implement different schemes of remoting using Cluster4Spring, several common configuration options are common to all remoting schemes. In this section, we go into details about these options and later we will highlight only the specifics of every particular remoting scheme.

The following listing illustrates how to configure generic remote proxy factory bean (providing that RMI is used as underlying remoting protocol). This example uses generic form of remote proxy factory bean that is applicable to every remoting scheme and is parameterized by appropriated endpoints provider (to support specifics of particular remoting scheme).

There is shorter form of proxy factory declaration that requires shorter markup and combines both definition of proxy with definition of EndpointProvider. Examples of such scheme usage will be shown later.

Please refer to configuration comments below to find more information for every particular element of declaration.

[1]  <bean name="TestService.verbose"
             class="org.softamis.cluster4spring.rmi.RmiProxyFactoryBean">
[2]    <property name="serviceInterface"
                 value="org.softamis.cluster4spring.example.Service"/>
[3]    <property name="refreshEndpointsOnStartup" value="true"/>
[4]    <property name="refreshEndpointsOnConnectFailure" value="true"/>
[5]    <property name="switchEndpointOnFailure" value="false"/>
[6]    <property name="registerTraceInterceptor" value="true"/>
[7]    <property name="remoteInvocationTraceInterceptor">
          <bean class="...">
             ...          
           </bean>
        </property>
[8]    <property name="endpointProvider">
           ...
           ...       
       </property>
[9]    <property name="interceptorNames" value="_Interceptor1, _Interceptor2"/>
[10]   <property name="endpointFactory">
          <bean class="org.softamis.cluster4spring.rmi.support.RmiEndpointFactory"/>
       </property>
[11]   <property name="remoteInvocationFactory">
          <bean
            class="org.springframework.support.DefaultRemoteInvocationFactory"/>       
       </property>
     </bean>

Configuration details:

  1. We declare exporter using appropriate class of remote proxy factory bean;
  2. Specification of interface of remote service;
  3. Policy that controls whether endpoints should be located on startup;
  4. Policy that controls whether endpoints should be re-discovered on remoting failure and   another attempt to invoke remote service should be performed;
  5. Policy that controls whether attempt to select another endpoint on failure should be  performed and attempt to invoke remote service should be performed;
  6. Option that specifies whether trace interceptor should be created and applied for remote calls;
  7. Sample declaration of remote trace interceptor (optional). If declaration of bean assumes that remote call trace interceptor should be registered, and there is no explicit declaration of interceptor is defined, default interceptor will be created and used;
  8. Property that represent configuration of EndpointProvider used to locate remote services. Using this property, we can specify which implementation of EndpointProvider should be used. By specifying appropriate EndpointProvider there, we specify remoting scheme, which will be used by particular proxy;
  9. Optionally, it is possible to specify that appropriate interceptors should be
    applied to remote call invocation;
  10. Property that specifies which EndpointsFactory should be used by proxy. If factory is not specified explicitly, the default instance will be created internally;
  11. Property that specifies which factory should be used to create RemoteInvocation's.  If factory it not specified explicitly, default instance of factory will be created and used.

The listing above illustrates all properties that can be configured. However, most of them are optional and should be specified only if this is necessary for particular application.

Generic Configuration of Service Exporter

In general, using ServiceExporter implementation included into Cluster4Spring is required only if "one-to-many with dynamic services discovering" remoting scheme is used. For all other cases, it is possible to use standard services exporter provided by Spring. However, service exporter included in Cluster4Spring offers some additional functionality in comparison with Spring based one, which can be useful for particular applications.

The following listing illustrates generic configuration of service exporter (assuming that RMI is used as underlying remoting protocol).

Please refer to configuration comments below to find more information on every element of declaration.

[1]<bean name="TestService.custom.verbose"
         class="org.softamis.cluster4spring.rmi.RmiServiceExporter">
[2]  <property name="allowsAutoDiscovering" value="false"/>
[3]  <property name="clientSocketFactory" ref="_RMIClientSocketsFactory"/>
[4]  <property name="interceptorNames" value="_Interceptor1, _Interceptor2"/>
[5]  <property name="registerTraceInterceptor" value="true"/>
[6]  <property name="remoteInvocationExecutor" ref="_RemoteInvocationExecutor"/>
[7]  <property name="remoteInvocationTraceInterceptor">
        <bean class="...">
          ...         
        </bean>
     </property>
[8]  <property name="registry" ref="_RMIRegistry"/>
[9]  <property name="service" ref="TestService.bean"/>
[10] <property name="serviceInterface"
               value="org.softamis.cluster4spring.example.Service"/>
[11] <property name="serviceName"value="TestService"/>
  </bean>  

Configuration comments:

  1. Declaration of remote service exporter using appropriate class of exporter;
  2. Property that allows to specify whether this exporter should be available for publishing information on its remote service by ServicePublisher (optional);
  3. Socket which should be used to create sockets used by RMI (optional);
  4. Optional list of interceptors that should be applied for remote method invocation;
  5. Optional property which indicates that trace interceptor should be used;
  6. Optionally, it is possible to apply custom RemoteInvocationExcecutor;
  7. Optionally, it is possible to provide custom implementation of trace interceptor. If this property is not specified, default instance of trace interceptor will be created;
  8. Reference to RMI registry bean;
  9. Reference to bean which represents implementation of remote service;
  10. Interface of remote service;
  11. Name of remote service which will be used to publish it in RMI registry;

The listing above illustrates all properties that can be configured. However, most of them are optional and should be specified only if this is necessary for particular application.

Configuring one-to-one remoting

We provide example of one-to-one remoting scheme configuration. For simplicity's sake, only client-side configuration of remoting is shown. On the server side, for this remoting scheme either standard Spring exporter or Cluster4Spring one can be used.

In general, configuring proxy factory for one-to-one remoting scheme is very simple and is illustrated by examples below.

Using specialized factory bean

The listing below illustrates minimal configuration with specialized proxy factory bean that is used to implement one-to-one scheme of remoting.

Please refer to configuration comments below to find more information on every element of declaration.

[1]<bean name="TestService.compact.minimal" 
         class="org.softamis.cluster4spring.rmi.RmiSingleUrlProxyFactoryBean">
[2]   <property name="serviceInterface"
                value="org.softamis.cluster4spring.example.Service"/>
[3]   <property name="serviceUrl" value="rmi://localhost:1099/TestService"/>
   </bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate specialized class which supports one-to-one remoting scheme;
  2. Property which represents interface of remote service;
  3. Property represents explicitly specified URL of remote service. Cluster4Spring also supports short form of RMI URL without protocol prefix - for this example it can be specified as "localhost:1099/TestService";

Of course, it is possible to configure all generic properties as it shown above.

Using generic proxy factory bean

If the use of generic exporter is more preferable for some reasons, it possible to implement different configuration (which is functionally equivalent to one listed above) that utilizes generic exporter customized by specific EndpointProvider. The following listing illustrates examples of such configuration.

Please refer to configuration comments below to find more information on every element of declaration.

[1]<bean name="TestService.verbose.minimal"
          class="org.softamis.cluster4spring.rmi.RmiProxyFactoryBean">
[2] <property name="serviceInterface"
              value="org.softamis.cluster4spring.example.Service"/>
[3] <property name="endpointProvider">
[4]   <bean class="org.softamis.cluster4spring.support.provider.SingleUrlEndpointProvider">
[5]     <property name="serviceUrl" value="rmi://localhost:1099/TestService"/>
      </bean>
    </property>
  </bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate generic class which is agnostic to remoting scheme;
  2. Property which represents interface of remote service;
  3. Property used to specify EndpointProvider implementation;
  4. Here we specify particular EndpointProvider which is used to support one-to-one remoting scheme;
  5. Property that represents explicitly specified URL of remote service.

Configuring static one-to-many remoting

In this section we provide an example of configuration for "static one-to-many" remoting scheme that assumes that remote service is available in several known remoting locations. For simplicity's sake, here we illustrate only configuration that should be performed on client side. On the server side, for this remoting scheme either standard Spring exporter or Cluster4Spring one can be used.

Configuring proxy factory for such remoting scheme is also quite simple and is illustrated by listings below.

Using specialized proxy factory bean

The listing below illustrates minimal configuration with specialized proxy factory bean that is used to implement static one-to-may scheme of remoting.

Please refer to configuration comments below to find more information on every particular element of declaration.

[1]<bean name="TestService.compact.minimal"
       class="org.softamis.cluster4spring.rmi.RmiUrlListProxyFactoryBean">
[2] <property name="serviceInterface"
             value="org.softamis.cluster4spring.example.Service"/>
[3] <property name="serviceURLs">
        <list>
        <value>rmi://localhost:1097/TestService</value>
        <value>rmi://localhost:1098/TestService</value>
        <value>rmi://localhost:1099/TestService</value>
      </list>
    </property>
[4] <property name="endpointSelectionPolicy">
      <bean class="org.softamis.cluster4spring.support.invocation.DefaultEndpointSelectionPolicy"/>
    </property>
  </bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate specialized class which supports static one-to-many remoting scheme;
  2. Property which represents interface of remote service;
  3. Property that allows to assign list of available known locations of remote service;
  4. Property that allows specifying policy that should be used to select particular endpoint from list of available ones on remote method invocation. Specifying that policy is optional, if one is not provide explicitly, the instance of default policy will be created and internally used;

Again, it is possible to configure all generic properties as it shown above.

Using generic proxy factory bean

If, for some reasons, using generic exporter is more preferable, it possible to use a different configuration (which is functionally equivalent to the listing above) that utilizes generic exporter customized by specific EndpointProvider. The following listing illustrates such a configuration.

Please refer to configuration comments below to find more information on every particular element of declaration.

[1]<bean name="TestService.verbose.minimal"
           class="org.softamis.cluster4spring.rmi.RmiProxyFactoryBean">
[2]  <property name="serviceInterface"
                  value="org.softamis.cluster4spring.example.Service"/>
[3]  <property name="endpointProvider">
[4]     <bean class="org.softamis.cluster4spring.support.provider.UrlListEndpointProvider">
[5]        <property name="serviceURLs">
            <list>
              <value>rmi://localhost:1097/TestService</value>
              <value>rmi://localhost:1098/TestService</value>
              <value>rmi://localhost:1099/TestService</value>
            </list>
           </property>
        </bean>
     </property>
   </bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate generic class which is agnostic to remoting scheme;
  2. Property which represents interface of remote service;
  3. Property used to specify EndpointProvider implementation;
  4. Here we specify particular EndpointProvider which is used to support one-to-one remoting scheme (note that the listing does not explicitly declare endpoints selection policy);
  5. Property that allows to assign a list of known available locations of remote service;

Configuring one-to-many remoting with dynamic services discovering

This scheme requires more complicated configuration. However, that complexity doesn't relate to declaration of client proxy and service exporter, but rather is related to necessary additional configuration of distributed registry.

The following examples assume that DistRegistry implementation of distributed registry is used as well as appropriate implementations of endpoint providers and publisher that utilize DistRegistry. However, it is possible to create custom endpoint providers and publishers that will utilize different implementation of distributed services registry.

Please refer to documentation for DistRegistry (included into Cluster4Spring distributive or available from this site) to get more details on how to configure distributed registry.

Client part of distributed services registry

Before configuring the remote proxy factory itself, it is necessary to configure the distributed services registry used for services discovering. The following listing illustrates configuration for distributed services registry.

Please refer to configuration comments below to get more information on every particular element of declaration.

[1]  <beanid="_ClientServicesRegistry"
           class="org.softamis.net.registry.spring.DefaultConsumingRegistry">
[2]    <property name="communicationHelper">
[3]       <bean class="org.softamis.net.exchange.udp.UDPCommunicationHelper"
                init-method="init" destroy-method="close">
[4]        <property name="multicaster">
             <bean class="org.softamis.net.multicast.DefaultMulticaster"
                  init-method="start" destroy-method="close">
               <property name="groupName" value="230.0.0.10"/>
               <property name="timeToLive" value="5"/>
            <property name="port" value="1000"/>
          </bean>
        </property>
      </bean>
    </property>
[5] <property name="requestItemsOnInit" value="true"/>
[6] <property name="defaultMessageSignature" value="EX"/>
  </bean>

Configuration comments:

  1. Declaration of client part for distributed services registry. Here we define a registry, which provides information on remote services locations. This is a client part of the distributed services registry. Also, there is the corresponding part, which should be declared on server that publishes it services. This registry will be used by appropriate endpoint providers to obtain the list of available service locations. In general, any class, which implements appropriate protocol for registry, may be used in remoting (for example, one that utilizes some remote cache, like JBoss cache). However, we use default ready to use implementation of client registry there.
  2. This property specifies communication helper, which hides details of underlying   network communications;
  3. In this example, we use UDP multicast based protocol; however, a different    implementation of internal registry communication can be used, such as JGroups based one.
  4. Multicaster which is used to issue and receive UDP multicast messages, which contain information about published services locations;
  5. Property that Indicates whether registry should issue request for published items   during startup;
  6. Signature used to filter UDP messages that contain information about service's locations. Only data obtained with packets which has such signature will be stored in client registry;

Using specialized proxy factory bean

The listing below illustrates minimal configuration with specialized proxy factory bean that is used to implement dynamic one-to-may scheme of remoting.

Please refer to configuration comments below to find more information on every particular element of declaration.

[1]<bean name="TestService.compact.minimal"
          class="org.softamis.cluster4spring.rmi.RmiDiscoveringProxyFactoryBean">
[2]<property name="serviceInterface"
               value="org.softamis.cluster4spring.example.Service"/>
[3]  <property name="serviceName" value="TestService"/>
[4]  <property name="serviceGroup" value="DEFAULT"/>
[5]  <propertyname="clientServicesRegistry" value="_ClientServicesRegistry"/>
  </bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate specialized class which supports dynamic one-to-many remoting scheme;
  2. Property which represents interface of remote service;
  3. Property which specifies name of the service;
  4. Property that specifies name of group which particular remote service belongs to.     Group defines the prefix of key which is used to publish information about service in distributed registry (key is composed as "serviceGroup/serviceName"). If one is not specified, default name of group is used;
  5. Reference to client part of distributed services registry used to get information about available locations of service;

Please note that it is not necessary to define one bean that represent client services registry for every declaration of remote service proxy. On the contrary, several remote service proxies may use the same instance of distributed services registry.

Again, it is possible to configure all generic properties as it shown above.

Using generic proxy factory bean

If, for some reasons, using generic exporter is more preferable, it is possible to use a different configuration (which is functionally equivalent to listing above) that utilizes generic exporter customized by specific EndpointProvider. The following listing illustrates such a configuration.

Please refer to configuration comments below to find more information on every particular element of declaration.

[1]<bean name="TestService.verbose.minimal"
      class="org.softamis.cluster4spring.rmi.RmiProxyFactoryBean">
    <property name="serviceInterface" value="org.softamis.cluster4spring.example.Service"/>
   <property  name="endpointProvider">
[2] <bean class="org.softamis.cluster4spring.support.provider.DiscoveringEndpointProvider">
[3]   <property name="serviceName" value="TestService"/>
[4]   <property name="serviceGroup" value="DEFAULT"/>
[5]   <property name="clientServicesRegistry" value="_ClientServicesRegistry"/>
    </bean>
   </property>
</bean>

Configuration comments:

  1. Declaration of proxy factory bean using appropriate generic class which is agnostic to remoting scheme;
  2. Declaration of EndpointProvider that supports appropriate remoting scheme;
  3. Property which specifies name of the service;
  4. Property that specifies a name of the group which particular remote service belongs to.
  5. Reference to client part of distributed services registry used to get information about available locations of service;

Server part of distributed services registry

To support one-to-many remoting scheme with dynamic services discovering, it is necessary to configure server part of distributed services registry.

The following listing illustrates configuration for server part of distributed services registry.

Please refer to configuration comments below to find more information for every particular element of declaration.

[1] <bean name="ServerServicesRegistry"
       class="org.softamis.net.registry.spring.DefaultProvidingRegistry"
                init-method="init"
        destroy-method="close">   
[2]    <property name="communicationHelper">
[3]      <bean class="org.softamis.net.exchange.udp.UDPCommunicationHelper"
                  init-method="init" destroy-method="close">
[4]       <property name="multicaster">
             <bean class="org.softamis.net.multicast.DefaultMulticaster"
                  init-method="start" destroy-method="close">
                <property name="groupName" value="230.0.0.10"/>
                <property name="timeToLive" value="5"/>
                <property name="port" value="1000"/>
             </bean>
          </property>
        </bean>
      </property>
[5]  <property name="defaultMessageSignature" value="EX"/>
  </bean>

Configuration comments:

  1. Declaration of server part of distributed services registry used to publish information about remote service locations.
  2. This property specifies communication helper, which hides the details of underlying   network communications;
  3. In this example, we use UDP multicast based protocol; however, a different    implementation of internal registry communication can be used, such as JGroups based one.
  4. Multicaster which is used to issue and receive UDP multicast messages, which contains information about published services locations;
  5. Signature used to filter UDP messages that contain information about service's locations. Only data obtained with packets which have such a signature will be stored in client's registry;

Configuring remote service exporter

If one-to-many remoting scheme with dynamic services discovering is used, it is necessary to use remote service exporter included into Cluster4Spring.

The following listing illustrates server-side configuration for remote service exporter.

Please refer to configuration comments below to find more information on every element of declaration.

[1]<bean class="org.softamis.cluster4spring.rmi.RmiServiceExporter">
[2]   <property name="allowsAutoDiscovering" value="true"/>
[3]   <property name="registry" ref="RMIRegistry"/>
[4]   <property name="service">
       <bean class="org.softamis.cluster4spring.example.ServiceImpl"/>
      </property>
[5]   <property name="serviceInterface"
               value="org.softamis.cluster4spring.example.Service"/>
[6]  <property name="serviceName" value="TestService"/>
  </bean>

Configuration comments:

  1. This is fairly simple configuration of service exporter which is required to let publishing information about service in distributed registry and so dynamic discovering of service by client;
  2. This property is used by appropriate ExporterAcceptor and should be set to true if one of acceptors included into Cluster4Spring is used. Default is true.
  3. Reference to RMI registry (declaration of registry is not included there);
  4. Declaration of bean which represents implementation of remote service;
  5. Property which specifies interface of remote service;
  6. Property that specifies the name of remote service - the corresponding name should be used for client-side proxy of service.

Please note that general properties that can be configured for service exporter were considered earlier and are not included into the listing above.

Configuring remote services publisher

It is responsibility of ServicePublisher to collect information about exported remote services and store it in the distributed services registry. The following listing illustrates server-side configuration for ServicePublisher.

Please refer to configuration comments below to get more information on every element of declaration.

[1]<bean id="RMIServicesPublisher"
        class="org.softamis.cluster4spring.rmi.RmiServicePublisher">
[2]  <property name="servicesRegistry" ref="ServerServicesRegistry"/>
[3]  <property name="cacheAutoDiscoveredServicesInfo" value="true"/>
[4]  <propertyname="serverID"value="123"/>
[5]  <property name="serviceGroup" value="DEFAULT"/>
[6]  <property name="serverType"value="DEF"/>
[7]  <property name="exporterAcceptor">
       <bean class="org.softamis.cluster4spring.support.context.DefaultExporterAcceptor"/>
     </property>
   </bean>

Configuration comments:

  1. First, we declare ServicePublisher using appropriate class;
  2. Property that contains reference to server part of distributed services registry. This registry is used to publish information about services and this information is discoverable by a client's part of registry;
  3. Property that indicates whether publisher should cache information about services it published internally and use it during services un-publishing (instead of re-discovering them). This function is optional and default value is false;
  4. Server ID represents unique ID of server within a cluster (or within the same providing registry). If there are several servers of the same type within the same cluster, it is necessary to distinguish them;
  5. Name of group which services published by particular publisher belongs to. Group defines the prefix of key which is used to publish information about service in distributed registry (key is composed as "serviceGroup/serviceName"). If one is not specified, default name of group is used; IMPORTANT: If service group is specified there, it's REQUIRED that the same service group should be specified in configuration of appropriate client part of remote service to insure that both server and client use the same key for service publishing and discovering with the use of distribute registry;
  6. This is a type of the server. In general, this property is optional (default is "DEF"), but can be useful for some monitoring tools, for example;
  7. Acceptor that is used to define whether particular remote service exporter should be published via this publisher to underlying distributed services registry. Specifying acceptor is optional.

Of course, it is not necessary to declare one instance of ServicePublisher per instance of ServiceExporter. Instead of this, one ServicePublisher should be declared for one instance of distributed service registry.

Generic configuration tips

The examples above are correct, but since their main purpose was demonstrating options that could be configured, they are not optimal.

This section of document contains some small tips that allow having optimal setup of remoting subsystem with the use of short-form configuration. In general, they are not specific to Cluster4Spring remoting and are quite general.

The list of such tips is very short and contains just two major recommendations (funny, but they are applicable to configuring standard Spring remoting subsystem):

  1. Do not rely on built-in defaults for internal remoting components.

    The implementation of Cluster4Spring remoting provides many places of creating default components of, for example, client remote proxy factory "by default" if ones are not specified explicitly. While it is fine and will work, this is not optimal solution - if you have several instances of, for example, client proxy factory, each such instance will contain references to unique instances of these components (the following ones could mentioned there - RemoteInvocationFactory, EndpointFactory, EndpointSelectionPolicy and so on). It is optimal solution to declare instances of such components explicitly and share them between appropriate instances of client-side proxy factory beans. The same is applicable to the server-side part of remoting too.

  2. Use bean definition inheritance.

    Imagine that the server exports, say, twenty remote services (and client imports them, accordingly). Instead of defining configuration for every instance of remote service exporter, use abstract bean definition which contains common configuration for all properties of exporter (or remote proxy bean) and later use child bean definition which extends such generic one and represents configuration of particular instance or exporter (or proxy factory).

The following example illustrates the preferred way to define remoting related configuration assuming that client uses more than one remote service applied to configuration of one-to-one remoting (for simplicity's sake). Obviously, it will be even more effectively applied to other remoting schemes.

[1]<bean name="_RmiEndpointFactory"
            class="org.softamis.cluster4spring.rmi.support.RmiEndpointFactory"/>
  
  <bean name="_RemoteInvocationFactory"
              class="org.springframework.support.DefaultRemoteInvocationFactory"/>

[2]<bean name="REMOTE_SERVICE_CLIENT"
        class="org.softamis.cluster4spring.rmi.RmiSingleUrlProxyFactoryBean"
        abstract="true">
    <property name="refreshEndpointsOnConnectFailure" value="true"/>
    <property name="refreshEndpointsOnStartup" value="true"/>
    <property name="registerTraceInterceptor" value="true"/>
    <property name="switchEndpointOnFailure" value="false"/>
    <property name="interceptorNames"
            value="_TestClientLoggingInterceptor, _TestClientEmptyInterceptor"/>
    <property name="endpointFactory" ref="_RmiEndpointFactory"/>
    <property name="remoteInvocationFactory" ref="_RemoteInvocationFactory"/>
  </bean>

[3]
  <bean name="TestService1" parent="REMOTE_SERVICE_CLIENT">
    <property name="serviceInterface"
             value="org.softamis.cluster4spring.example.ServiceImpl"/>
    <property name="serviceUrl" value="rmi://serverA:1099/TestService"/>
  </bean>
  <bean name="TestService2" parent="REMOTE_SERVICE_CLIENT">
    <property name="serviceInterface"
              value="org.softamis.cluster4spring.example.ServiceImpl"/>
    <property name="serviceUrl" value="rmi://serverB:1099/TestService"/>
  </bean>

Configuration comments:

  1. First, we define beans instances that will be used by all instances of remote proxies. In general, if these instances are not declared explicitly, they will be created by default for every proxy. Therefore explicit declaration of them is needed if custom implementations are used or to increase the efficiency of the internal structures (no additional instances created) of remote proxies. Potentially, these declarations could be defined directly in-place within the appropriate property of remote proxy factory bean;
  2. Than we define an abstract definition of remote proxy factory as abstract bean and specify all necessary properties for it. Later, if concrete remote proxies will be declared as used by this abstract definition, they will share all these properties. Such approach allows to have single place where common properties for remote proxies are managed and simplify declaration of particular remote proxy factory beans;
  3. Finally, we declare concrete instances of RMI remote proxy factory beans. Since we declare them with the use of declaration inheritance, definition of particular proxy become quite compact;
  SourceForge.net Logo   Support This Project