Conflict Resolution

The most popular usage of replication callback events is conflict resolution. When an object was changed in both replicating databases you must have a strategy to decide, which value must be final. In the simplest case one of the databases is made "dominant" and the changes in this database always override other changes. The following example demonstrates this behavior:

 

EventsExample.java: conflictResolutionExample
01private static void conflictResolutionExample() { 02 Db4o.configure().generateUUIDs(ConfigScope.GLOBALLY); 03 Db4o.configure().generateVersionNumbers(ConfigScope.GLOBALLY); 04 05 // Open databases 06 ObjectContainer desktop = Db4o.openFile("desktop.db4o"); 07 ObjectContainer handheld = Db4o.openFile("handheld.db4o"); 08 09 Pilot pilot = new Pilot("Scott Felton", 200); 10 handheld.set(pilot); 11 handheld.commit(); 12 /* Clean the reference cache to make sure that objects in memory 13 * won't interfere 14 */ 15 handheld.ext().refresh(Pilot.class, Integer.MAX_VALUE); 16 17 /* Replicate changes from handheld to desktop 18 * Note, that only objects replicated from one database to another will 19 * be treated as the same. If you will create an object and save it to both 20 * databases, dRS will count them as 2 different objects with identical 21 * fields. 22 */ 23 ReplicationSession replication = Replication.begin(handheld, desktop); 24 ObjectSet changedObjects = replication.providerA().objectsChangedSinceLastReplication(); 25 while (changedObjects.hasNext()) 26 replication.replicate(changedObjects.next()); 27 replication.commit(); 28 29 // change object on the handheld 30 pilot = (Pilot)handheld.query(Pilot.class).next(); 31 pilot.setName("S.Felton"); 32 handheld.set(pilot); 33 handheld.commit(); 34 35 // change object on the desktop 36 pilot = (Pilot)desktop.query(Pilot.class).next(); 37 pilot.setName("Scott"); 38 desktop.set(pilot); 39 desktop.commit(); 40 41 /* The replication will face a conflict: Pilot object was changed on the 42 * handheld and on the desktop. 43 * To resolve this conflict we will add an event handler, which makes 44 * desktop changes dominating. 45 */ 46 ReplicationEventListener listener; 47 listener = new ReplicationEventListener() { 48 public void onReplicate(ReplicationEvent event) { 49 if (event.isConflict()) { 50 ObjectState chosenObjectState = event.stateInProviderB(); 51 event.overrideWith(chosenObjectState); 52 } 53 } 54 }; 55 56 replication = Replication.begin(handheld, desktop, listener); 57 58 //The state of the desktop after the replication should not change, as it dominates 59 changedObjects = replication.providerA().objectsChangedSinceLastReplication(); 60 while (changedObjects.hasNext()) 61 replication.replicate(changedObjects.next()); 62 63 //Commit 64 replication.commit(); 65 replication.close(); 66 67 // Check what we've got on the desktop 68 ObjectSet result = desktop.query(Pilot.class); 69 System.out.println(result.size()); 70 while (result.hasNext()) { 71 System.out.println(result.next()); 72 } 73 handheld.close(); 74 desktop.close(); 75 76 new File("handheld.db4o").delete(); 77 new File("desktop.db4o").delete(); 78 79 }