Skip to content

Commit

Permalink
User guide updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
mhanes committed Mar 17, 2010
1 parent 8768a3f commit 8bcc496
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 37 deletions.
24 changes: 19 additions & 5 deletions symmetric/src/docbook/configuration.xml
Expand Up @@ -753,14 +753,28 @@ values
</para>
<section id="configuration-dead-triggers">
<title>Dead Triggers</title>
<para>
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.
<para>
Occasionally the decision of what data to load initially results in additional triggers. These triggers, known as <emphasis>Dead Triggers</emphasis>,
are configured such that they do not capture any data changes.
A "dead" Trigger is one that does not capture data changes.
In other words, the <literal>sync_on_insert</literal>, <literal>sync_on_update</literal>, and <literal>sync_on_delete</literal> properties
for the Trigger are all set to false. However, because the Trigger is specified,
it <emphasis>will</emphasis>
for the Trigger are all set to false. However, since the Trigger is specified, it <emphasis>will</emphasis>
be included in the initial load of data for target Nodes.
</para>
<para>
Why might you need a Dead Trigger?
A dead Trigger might be used to load a read-only lookup table, for example. It could also
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 from the central office,
they can be sent
are part of an initial load from the central office by setting up dead Triggers
that "sync" in that direction.
</para>

<para>
The following SQL statement sets up a non-syncing dead Trigger that sends
the <literal>sale_transaction</literal> table to the "store" Node Group from the "corp" Node Group during
Expand Down
256 changes: 256 additions & 0 deletions symmetric/src/docbook/extensions.xml
@@ -0,0 +1,256 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0" xml:id="extensions" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns="http://docbook.org/ns/docbook"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml">
<title>Extending SymmetricDS</title>


<para>
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.
</para>
<para>
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.
</para>
<para>
The INodeGroupExtensionPoint interface may be optionally implemented to designate that auto registered
extension points should only be auto registered with specific node groups.
<programlisting><![CDATA[/**
* Only apply this extension point to the 'root' node group.
*/
public String[] getNodeGroupIdsToApplyTo() {
return new String[] { "root" };
}
]]></programlisting>
</para>
<para>
SymmetricDS will look for Spring configured extensions in the application Classpath by importing any Spring
XML configuration files found matching the following pattern: <literal>META-INF/services/symmetric-*-ext.xml</literal>. When packaged in
a jar file the <literal>META-INF</literal> directory should be at the root of the jar file. When packaged in a war file, the <literal>META-INF</literal> directory
should be in the <literal>WEB-INF/classes</literal> directory.
</para>
<section id="configuration-parameter-filter">
<title>IParameterFilter</title>
<para>
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 deprecated IRuntimeConfig from prior releases.
<programlisting><![CDATA[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;
}
}]]></programlisting>
</para>
</section>
<section id="configuration-extensions-data-loader-filter">
<title>IDataLoaderFilter</title>
<para>
Data can be filtered as it is loaded into the target database. It can also be
filtered 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 value 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 a less-restricted reporting database.
</para>
<para>
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 access to
old data if the <literal>sync_column_level</literal> 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.
</para>
<para>
Many times the IDataLoaderFilter will be combined with the IBatchListener. The
XmlPublisherFilter (in the <literal>org.jumpmind.symmetric.ext</literal> 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.
</para>
<para>
A class implementing the IDataLoaderFilter interface is injected onto the
DataLoaderService in order to receive callbacks when data is inserted,
updated, or deleted.

<programlisting><![CDATA[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;
}
}]]></programlisting>
</para>
<para>
The filter class is specified as a Spring-managed bean. A custom Spring XML file
is specified as follows in a jar at <literal>META-INF/services/symmetric-myfilter-ext.xml</literal>.

<programlisting><![CDATA[<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="myFilter" class="com.mydomain.MyFilter"/>
</beans>]]></programlisting>
</para>
</section>
<section id="configuration-extensions-table-column-filter">
<title>ITableColumnFilter</title>
<para>
Implement this extension point to filter out specific columns from
use by the dataloader. Only one column filter may be added per target table.
</para>
</section>
<section id="configuration-extensions-batch-listener">
<title>IBatchListener</title>
<para>
This extension point is called whenever a batch has completed loading but before
the transaction has committed.
</para>
</section>
<section id="configuration-extensions-acknowledge-event-listener">
<title>IAcknowledgeEventListener</title>
<para>
Implement this extension point to receive callback events when a batch is acknowledged.
The callback for this listener happens at the point of extraction.
</para>
</section>
<section id="configuration-extensions-reload-listener">
<title>IReloadListener</title>
<para>
Implement this extension point to listen in and take
action before or after a reload is requested for a Node. The callback for this listener
happens at the point of extraction.
</para>
</section>
<section id="configuration-extensions-extractor-filter">
<title>IExtractorFilter</title>
<para>
This extension point is called after data has been extracted, but before it has been streamed. It
has the ability to inspect each row of data to take some action and indicate, if necessary, that the
row should not be streamed.
</para>
</section>
<section id="configuration-extensions-sync-url-extension">
<title>ISyncUrlExtension</title>
<para>
This extension point is used to select an appropriate URL based on
the URI provided in the <literal>sync_url</literal> column of <literal>sym_node</literal>.
</para>
<para>
To use this extension point configure the sync_url for a node with the
protocol of ext://beanName. The beanName is the name you give the extension
point in the extension xml file.
</para>
</section>
<section id="configuration-extensions-node-id-generator">
<title>INodeIdGenerator</title>
<para>
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.
</para>
</section>
<section id="configuration-extensions-trigger-creation-listener">
<title>ITriggerCreationListener</title>
<para>
Implement this extension point to get status callbacks during trigger creation.
</para>
</section>
<section id="configuration-extensions-batch-algorithm">
<title>IBatchAlgorithm</title>
<para>
Implement this extension point and set the name of the Spring bean on the batch_algorithm column of the Channel table to use.
This extension point gives fine grained control over how a channel is batched.
</para>
</section>
<section id="configuration-extensions-data-router">
<title>IDataRouter</title>
<para>
Implement this extension point and set the name of the Spring bean on the router_type column
of the Router table to use. This extension point gives the ability to programatically decide
which nodes data should be routed to.
</para>
</section>
<section id="configuration-extensions-heartbeat-listener">
<title>IHeartbeatListener</title>
<para>
Implement this extension point to get callbacks during the heartbeat job.
</para>
</section>
<section id="configuration-extensions-offline-client-listener">
<title>IOfflineClientListener</title>
<para>
Implement this extension point to get callbacks for offline events on client nodes.
</para>
</section>
<section id="configuration-extensions-offline-server-listener">
<title>IOfflineServerListener</title>
<para>
Implement this extension point to get callbacks for offline events detected on a server node during monitoring of client nodes.
</para>
</section>
<section id="configuration-extensions-node-password">
<title>INodePasswordFilter</title>
<para>
Implement this extension point to intercept the saving and rendering of the node password.
</para>
</section>
<section id="configuration-extensions-servlets">
<title>IServletExtension</title>
<para>
Implement this extension point to allow additional Servlets to be registered with SymmetricDS. This is probably only
useful if SymmetricDS is running in standalone or embedded mode.
</para>
</section>
</chapter>
7 changes: 2 additions & 5 deletions symmetric/src/docbook/introduction.xml
Expand Up @@ -2,8 +2,7 @@
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns="http://docbook.org/ns/docbook"
xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml">
<title>Introduction</title>
<section id="overview">
<title>Overview</title>

<para>This User Guide will introduce both basic and advanced concepts in the configuration
of SymmetricDS. By the end of this chapter, you will have a better understanding of SymmetricDS' capabilities, and
many of its basic concepts. This chapter also includes a hands-on, step-by-step, tutorial meant to demonstrate some of
Expand Down Expand Up @@ -178,7 +177,7 @@
used to send data. The data payload can be any SQL statement. The event is processed and acknowledged just like
any other event type.</para>
</section>
</section>

</section>
<section id="requirements">
<title>System Requirements</title>
Expand Down Expand Up @@ -286,6 +285,4 @@
statistics, have been moved over to the batch tables themselves. The statistics in the batch tables now always represent the
latest synchronization attempt.</para>
</section>

<xi:include href="tutorial.xml" />
</chapter>
24 changes: 3 additions & 21 deletions symmetric/src/docbook/planning.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0" xml:id="concepts" xmlns="http://docbook.org/ns/docbook"
<chapter version="5.0" xml:id="planning" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns="http://docbook.org/ns/docbook"
xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml">
Expand Down Expand Up @@ -280,7 +280,7 @@


<section id="defining-data-changes-trigger-routers">
<title>Planning Initial Loads and Dead Triggers</title>
<title>Planning Initial Loads</title>

<para>The mapping between Triggers and Routers defines more than just the many-to-many relationship between your Triggers and your Routers. It also defines
two aspects of how initial loads occur, so now is a good time to plan how your <emphasis>Initial Loads</emphasis> will work.
Expand All @@ -293,25 +293,7 @@
<!-- MDH need content here -->
</para>

<para>
Occasionally the decision of what data to load initially results in additional triggers. These triggers, known as <emphasis>Dead Triggers</emphasis>,
are configured such that they do not capture any data changes. In other words, their settings for synchronizing on
updates, inserts, and deletes are all set to false. However, since the Trigger is specified, it <emphasis>will</emphasis>
be included in the initial load of data for target Nodes.
</para>
<para>
Why might you need a Dead Trigger?
A dead Trigger might be used to load a read-only lookup table, for example. It could also
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 from the central office,
they can be sent
are part of an initial load from the central office by setting up dead Triggers
that "sync" in that direction.
</para>

</section>


Expand Down

0 comments on commit 8bcc496

Please sign in to comment.