Detailed Example

Let's look at a primitive example, demonstrating manual implementation of Activatable/IActivatable interface for TP. We will use a class similar to the one used in Transparent Activation chapters.

SensorPanel.java
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.tpexample; 04 05import com.db4o.activation.*; 06import com.db4o.ta.*; 07 08public class SensorPanel implements Activatable { 09 10 private Object _sensor; 11 12 private SensorPanel _next; 13 14 /*activator registered for this class*/ 15 transient Activator _activator; 16 17 public SensorPanel() { 18 // default constructor for instantiation 19 } 20 // end SensorPanelTA 21 22 public SensorPanel(int value) { 23 _sensor = new Integer(value); 24 } 25 // end SensorPanelTA 26 27 /*Bind the class to the specified object container, create the activator*/ 28 public void bind(Activator activator) { 29 if (_activator == activator) { 30 return; 31 } 32 if (activator != null && _activator != null) { 33 throw new IllegalStateException(); 34 } 35 _activator = activator; 36 } 37 // end bind 38 39 /*Call the registered activator to activate the next level, 40 * the activator remembers the objects that were already 41 * activated and won't activate them twice. 42 */ 43 public void activate(ActivationPurpose purpose) { 44 if (_activator == null) 45 return; 46 _activator.activate(purpose); 47 } 48 // end activate 49 50 public SensorPanel getNext() { 51 /*activate direct members*/ 52 activate(ActivationPurpose.READ); 53 return _next; 54 } 55 // end getNext 56 57 public Object getSensor() { 58 /*activate direct members*/ 59 activate(ActivationPurpose.READ); 60 return _sensor; 61 } 62 // end getSensor 63 64 public void setSensor(Object sensor) { 65 /*activate for persistence*/ 66 activate(ActivationPurpose.WRITE); 67 _sensor = sensor; 68 } 69 // end setSensor 70 71 public SensorPanel createList(int length) { 72 return createList(length, 1); 73 } 74 // end createList 75 76 public SensorPanel createList(int length, int first) { 77 int val = first; 78 SensorPanel root = newElement(first); 79 SensorPanel list = root; 80 while (--length > 0) { 81 list._next = newElement(++val); 82 list = list._next; 83 } 84 return root; 85 } 86 // end createList 87 88 protected SensorPanel newElement(int value) { 89 return new SensorPanel(value); 90 } 91 // end newElement 92 93 public String toString() { 94 return "Sensor #" + getSensor(); 95 } 96 // end toString 97}

Note, that the only place where we can modify SensorPanel members is setSensor method/Sensor property, and that is where activate method is added.

Now we will only need to add Transparent Activation support:

TPExample.java: configureTA
1private static Configuration configureTA() { 2 Configuration configuration = Db4o.newConfiguration(); 3 // add TA support 4 configuration.add(new TransparentActivationSupport()); 5 return configuration; 6 }

Initial storing of the objects is done as usual with a single store call:

TPExample.java: storeSensorPanel
01private static void storeSensorPanel() { 02 new File(DB4O_FILE_NAME).delete(); 03 ObjectContainer container = database(Db4o.newConfiguration()); 04 if (container != null) { 05 try { 06 // create a linked list with length 10 07 SensorPanel list = new SensorPanel().createList(10); 08 container.store(list); 09 } finally { 10 closeDatabase(); 11 } 12 } 13 }

Now we can test how Transparent Persistence helped us to keep the code simple. Let's select all elements from the linked SensorPanel list, modify them and store. As you remember default update depth is one, so without TP, we would have to store each member of the linked list (SensorPanel) separately. With TP enabled there is absolutely nothing to do: commit call will find all activatable objects and store those that were modified.

TPExample.java: testTransparentPersistence
01private static void testTransparentPersistence() { 02 storeSensorPanel(); 03 Configuration configuration = configureTA(); 04 05 ObjectContainer container = database(configuration); 06 if (container != null) { 07 try { 08 ObjectSet result = container.queryByExample(new SensorPanel(1)); 09 listResult(result); 10 SensorPanel sensor = null; 11 if (result.size() > 0) { 12 System.out.println("Before modification: "); 13 sensor = (SensorPanel) result.get(0); 14 // the object is a linked list, so each call to next() 15 // will need to activate a new object 16 SensorPanel next = sensor.getNext(); 17 while (next != null) { 18 System.out.println(next); 19 // modify the next sensor 20 next.setSensor(new Integer(10 + (Integer)next.getSensor())); 21 next = next.getNext(); 22 } 23 // Explicit commit stores and commits the changes at any time 24 container.commit(); 25 } 26 } finally { 27 // If there are unsaved changes to activatable objects, they 28 // will be implicitly saved and committed when the database 29 // is closed 30 closeDatabase(); 31 } 32 } 33 // reopen the database and check the modifications 34 container = database(configuration); 35 if (container != null) { 36 try { 37 ObjectSet result = container.queryByExample(new SensorPanel(1)); 38 listResult(result); 39 SensorPanel sensor = null; 40 if (result.size() > 0) { 41 System.out.println("After modification: "); 42 sensor = (SensorPanel) result.get(0); 43 SensorPanel next = sensor.getNext(); 44 while (next != null) { 45 System.out.println(next); 46 next = next.getNext(); 47 } 48 } 49 } finally { 50 closeDatabase(); 51 } 52 } 53 }

That's all. The benefits that we've got: