I have made a connection from a Domino address book to AD, and it is
sniffing for changes in the Domino application (database). I have also
made a connection from AD to the same address book in Domino, and it
is also sniffing for changes in AD.
Basically I am trying to sync an address book i Domino with AD, both
ways. If a change in one system occurs, it will update the other.
The problem is that when a change occurs in one system, the other
system is updated. When this happens, it is triggered as a change, and
the first system is updated again. So both sides will never stop
updating each other.
Can someone please tell how to prevent this?
Regards
Gunnar Vinje
hahaha that made me laugh.. Quite interesting situation. How is your
solution set up.
I know there must be a more cleaner way to do but at the top of my
head i can think of this. Have a custom attribute in your work entry
of both iterators something like 'updateFrom', and set it to something
like "exteranl" initially, but if a change is received by either of
the target systems, send that attribute along with a value of "fromAD"
or "fromDomino" (depending on who is making the update), and before
the other AL decides to push the change, it should check the status of
this attribute, if updateFrom=="Domino" || "AD {relax} elseif
(updateFrom=="external" synchronize, and set the value of updateFrom
to Domino' or 'AD' depending on who is making the call.
I am sure someone else will respond with much efficient method. I
still can't stop smiling :-)
OR you can chose not to run your Assembly line continuously "sniffing
for change", instead run it at schedule and use system/delta store for
both Assembly Lines that way both are up-to date and won't chase its
own tail.
Let us know if you figure out before someone posts a suggestion.
thanks
-kash
I actually had a good laugh myself, and I think the sytem is working
as intended, only too good :D.
I will try out your and other solutions this weekend, as I am sure
there is an easy approach to this.
Have a nice weekend.
Gunnar
1. Let Update Mode's Compute Changes feature handle this
for you. Compute Changes takes the Attributes you map out
and compares them with those of the entry found by the
the prior lookup operation (that's why any lookup reads data
both into conn and another Entry called "current": so that
they can be compared). If Compute Changes is turned on, then
no write is done if these values are all the same. This is one
way to stop the ping-pong effect.
2. If you can detect which user/account made the change, and
if TDI uses its own credentials into both systems, your ALs can
use this to determine if a sync action is required.
3. Use the System Store. This is available by default, although
if you have never used the System Store features before (like
Delta Engine, Sandbox or Change Detection Iterator State
persistence)
then you may want to make sure your System Store is configured
for Network mode, and not the default Embedded setting.
More on this here:
http://www.tdi-users.org/twiki/bin/view/Integrator/SystemStore
Then whenever your AL from A2B picks up a change, it
saves a "flag" value under the unique ID, or combination
of unique IDs if necessary, so that the B2A AL can detect
this. For example:
o AL A2B detects a change, in the Iterator After GetNext Hook
uid = work.getString("mail"); // or some other unique id
pingPong = system.getPersistentObject("B2A:" + uid);
if (pingPong) {
system.deletePersistentObject("B2A:" + uid);
system.exitFlow(); // skip the Pong
}
// Otherwise, set the property for this ping
system.setPersistentObject("A2B:" + uid, conn);
// Continue to sync to target(s)
...
Here I am even persisting the Conn Entry as it was
received from the Connector Interface's "read next"
operation; getNextEntry(). This allows you to add even
more discerning logic to determine whether or not
the sync should take place, basing it one information
in the changed Entry.
4. If you're not worried about persisting these "flags" between
AL runs, then do it all in the memory of the JVM by replacing
the PersistentObject() calls with
java.lang.System.getProperties().get(key)
java.lang.System.getProperties().put(key, obj)
java.lang.System.getProperties().remove(key)
Points 2 and onwards are not foolproof. There may be
situations where modifier-id or a semaphore prevents
a "wanted" sync. I have not had enough coffee today to
think of one (any takers?). This may be fixed by using
the Conn Entry stored as the "flag" value.
Of course, as a Javamateur (seeing the world through
TDI-colored specs lets me get away as such) I know the
right way would be to use a synchronized semaphor class
instead. I would love to see a simple (repeat, simple) example
of how the above could be done using such an object/library.
Looking forward to it.
Hope this helps :)
-Eddie