Capítulo 6. Configuración Avanzada

6.1. Arboles de Nodos

Los Nodos pueden ser organizados de modo que la sincronización fluya a través de una red en árbol.

Un Nodo siempre enviará y recibirá datos de otros grupos de Nodos conforme a la configuración de enlaces del grupo de Nodos. Un Nodo sólo puede enviar y recibir datos de otros nodos que se encuentren representados en su base de datos. Por lo tanto, se puede crear una jerarquía de Nodos en forma de árbol teniendo sólo un subconjunto de los Nodos representados en las diferentes ramas del árbol.

Si se inhabilita el registro automático, entonces esta configuración debe realizarse manualmente abriendo el registro de los Nodos deseados en el Nodo padre deseado, y asigando al registration.url de cada Nodo la url del Nodo padre. El nodo Padre siempre puede ser localizado por el valor del node_id del padre en la columna created_at_node_id del nuevo Nodo. Cuando un Nodo registra y descarga su configuración, siempre se le proporciona la configuración de todos los Nodos que fueron creados en el Nodo en el cual se registra.

6.2. Selección de Nodo

6.3. Carga Inicial

There are variables you can use when specifying the initial_load_select SQL for a Trigger that will be replaced at runtime:

  • $(nodeId) - the node ID of the target node

  • $(groupId) - the node group ID of the target node

  • $(externalId) - the external ID of the target node

6.4. Bi-Directional Synchronization

SymmetricDS allows tables to be synchronized bi-directionally. Note that an outgoing synchronization does not process changes during an incoming synchronization on the same node unless the trigger was created with the sync_on_incoming_batch flag set. If the sync_on_incoming_batch flag is set, then update loops are prevented by a feature that is available in most database dialects. During an incoming synchronization the source node_id is put into a database session variable that is available to the database trigger. Data events are not generated if the target node_id on an outgoing synchronization is equal to the source node_id.

When synchronizing tables in both directions, the sync_column_level flag may be enabled. This indicates to the data loader that only columns that have changed should be updated. In order to accomplish this, both old and new data are transmitted from the source node to the target node. Because of the extra data overhead this feature should only be enabled if needed.

More complex conflict resolution strategies can be accomplished by using the IDataLoaderFilter extension point which has access to both old and new data.

6.5. Dead Triggers

Normally a Trigger is specified to capture data changes to a table and send them to a target Node Group. A dead Trigger is one that does not capture data changes. In other words, the sync_on_insert, sync_on_update, and sync_on_delete properties for the Trigger are all set to false. Because the Trigger is specified, it will be included in the initial load of data for target Nodes.

A dead Trigger might be used to load a read-only lookup table. It could be used to load a table that needs populated with example or default data. Another use is a recovery load of data for tables that have a single direction of synchronization. For example, a retail store records sales transaction that synchronize in one direction by trickling back to the central office. If the retail store needs to recover all the sales transactions, they can be sent are part of an initial load from the central office by setting up dead Triggers that "sync" in that direction.

The following SQL statement sets up a non-syncing dead Trigger that sends the sale_transaction table to the "store" Node Group from the "corp" Node Group during an initial load.

insert into SYM_TRIGGER    (source_table_name, source_node_group_id, target_node_group_id, channel_id,     sync_on_insert, sync_on_update, sync_on_delete,     initial_load_order, last_updated_by, last_updated_time, create_time) values   ('sale_transaction', 'corp', 'store', 'sale_transaction',     0, 0, 0,     105, 'demo', current_timestamp, current_timestamp); 

6.6. Database Purging

6.7. Clustering

6.8. Extension Points

SymmetricDS may be extended via a plug-in like architecture where extension point interfaces may be implemented by a custom class and registered with the synchronization engine. All supported extension points extend the IExtensionPoint interface. The currently available extension points are documented in the following sections.

When the synchronization engine starts up, a Spring post processor searches the Spring ApplicationContext for any registered classes which implement IExtensionPoint. An IExtensionPoint designates whether it should be auto registered or not. If the extension point is to be auto registered then the post processor registers the known interface with the appropriate service.

The INodeGroupExtensionPoint interface may be optionally implemented to designate that auto registered extension points should only be auto registered with specific node groups.

/**  * Only apply this extension point to the 'root' node group.  */  public String[] getNodeGroupIdsToApplyTo() {      return new String[] { "root" };  } 

SymmetricDS will look for Spring configured extensions in the application Classpath by importing any Spring XML configuration files found matching the following pattern: META-INF/services/symmetric-*-ext.xml.

6.8.1. IParameterFilter

Parameter values can be specified in code using a parameter filter. Note that there can be only one parameter filter per engine instance. The IParameterFilter replaces the depreciated IRuntimeConfig from prior releases.

public class MyParameterFilter      implements IParameterFilter, INodeGroupExtensionPoint {      /**      * Only apply this filter to stores      */     public String[] getNodeGroupIdsToApplyTo() {         return new String[] { "store" };     }      public String filterParameter(String key, String value) {         // look up a store number from an already existing properties file.         if (key.equals(ParameterConstants.EXTERNAL_ID)) {             return StoreProperties.getStoreProperties().               getProperty(StoreProperties.STORE_NUMBER);         }          return value;     }      public boolean isAutoRegister() {         return true;     }  } 

6.8.2. IDataLoaderFilter

Data can be filtered as it is loaded into the target database or when it is extracted from the source database.

As data is loaded into the target database, a filter can change the data in a column or save it somewhere else. It can also specify by the return type of the function call that the data loader should continue on and load the data (by returning true) or ignore it (by returning false). One possible use of the filter might be to route credit card data to a secure database and blank it out as it loads into less-restricted reporting database.

An IDataLoaderContext is passed to each of the callback methods. A new context is created for each synchronization. The context provides methods to lookup column indexes by column name, get table meta data, and provides access to old data if the sync_column_level flag is enabled. The context also provides a means to share data during a synchronization between different rows of data that are committed in a database transaction and are in the same channel. It does so by providing a context cache which can be populated by the extension point.

Many times the IDataLoaderFilter will be combined with the IBatchListener. The XmlPublisherFilter (in the org.jumpmind.symmetric.ext package) is a good example of using the combination of the two extension points in order to create XML messages to be published to JMS.

A class implementing the IDataLoaderFilter interface is injected onto the DataLoaderService in order to receive callbacks when data is inserted, updated, or deleted.

public MyFilter implements IDataLoaderFilter {                      public boolean isAutoRegister() {         return true;     }       public boolean filterInsert(IDataLoaderContext context,         String[] columnValues) {         return true;     }          public boolean filterUpdate(IDataLoaderContext context,          String[] columnValues, String[] keyValues) {         return true;     }          public void filterDelete(IDataLoaderContext context,          String[] keyValues) {         return true;     }  } 

The filter class is specified as a Spring-managed bean. A custom Spring XML file is specified as follows in a jar at META-INF/services/symmetric-myfilter-ext.xml.

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"     xsi:schemaLocation="http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd            http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-context-2.5.xsd">       <bean id="myFilter" class="com.mydomain.MyFilter"/>       </beans> 

6.8.3. IColumnFilter

6.8.4. IBatchListener

6.8.5. IReloadListener

6.8.6. IExtractorFilter

6.8.7. INodeIdGenerator

This extension point allows SymmetricDS users to implement their own algorithms for how node ids and passwords are generated or selected during the registration process. There may be only one node generator per SymmetricDS instance.

6.8.8. ITriggerCreationListener

6.9. Secure Transport

By specifying the "https" protocol for a URL, SymmetricDS will communicate over Secure Sockets Layer (SSL) for an encrypted transport. The following properties need to be set with "https" in the URL:

my.url

This is the URL of the current node, so if you want to force other nodes to communicate over SSL with this node, you specify "https" in the URL.

registration.url

This is the URL where the node will connect for registration when it first starts up. To protect the registration with SSL, you specify "https" in the URL.

For incoming HTTPS connections, SymmetricDS depends on the webserver where it is deployed, so the webserver must be configured for HTTPS. As a standalone deployment, the "sym" launcher command provides options for enabling HTTPS support.

6.9.1. Sym Launcher

The "sym" launch command uses Jetty as an embedded web server. Using command line options, the web server can be told to listen for HTTP, HTTPS, or both.

sym --port 8080 --server

sym --secure-port 8443 --secure-server

sym --port 8080 --secure-port 8443 --mixed-server

6.9.2. Tomcat

If you deploy SymmetricDS to Apache Tomcat, it can be secured by editing the TOMCAT_HOME/conf/server.xml configuration file. There is already a line that can be uncommented and changed to the following:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"    maxThreads="150" scheme="https" secure="true"    clientAuth="false" sslProtocol="TLS"   keystoreFile="/symmetric-ds-1.x.x/security/keystore" /> 

6.9.3. Keystores

When SymmetricDS connects to a URL with HTTPS, Java checks the validity of the certificate using the built-in trusted keystore located at JRE_HOME/lib/security/cacerts. The "sym" launcher command overrides the trusted keystore to use its own trusted keystore instead, which is located at security/cacerts. This keystore contains the certificate aliased as "sym" for use in testing and easing deployments. The trusted keystore can be overridden by specifying the "javax.net.ssl.trustStore" system property.

When SymmetricDS is run as a secure server with the "sym" launcher, it accepts incoming requests using the key installed in the keystore located at security/keystore. The default key is provided for convenience of testing, but should be re-generated for security.

6.9.4. Generating Keys

To generate new keys and install a server certificate, use the following steps:

  1. Open a command prompt and navigate to the security subdirectory of your SymmetricDS installation.

  2. Delete the old key pair and certificate.

    keytool -keystore keystore -delete -alias sym

    keytool -keystore cacerts -delete -alias sym

    Enter keystore password:  changeit 
  3. Generate a new key pair.

    keytool -keystore keystore -alias sym -genkey -keyalg RSA -validity 10950

    Enter keystore password:  changeit What is your first and last name?   [Unknown]:  localhost What is the name of your organizational unit?   [Unknown]:  SymmetricDS What is the name of your organization?   [Unknown]:  JumpMind What is the name of your City or Locality?   [Unknown]: What is the name of your State or Province?   [Unknown]: What is the two-letter country code for this unit?   [Unknown]: Is CN=localhost, OU=SymmetricDS, O=JumpMind, L=Unknown, ST=Unknown, C=Unknown correct?   [no]:  yes  Enter key password for <sym>         (RETURN if same as keystore password): 
  4. Export the certificate from the private keystore.

    keytool -keystore keystore -export -alias sym -rfc -file sym.cer

  5. Install the certificate in the trusted keystore.

    keytool -keystore cacerts -import -alias sym -file sym.cer