13.6 The Synchronized Contact Manager Now, we revisit the PointBase Contact Manager application discussed in Section 11.11. We can use PointBase's UniSync engine to simplify both the data backup and database provisioning processes. Figure 13.5 demonstrates the synchronized Contact Manager application in action.
![](/image/library/english/10153_13fig05.gif) Using techniques and APIs we learned in Section 13.2, we use class ResetServer to set up the hub, publications, and spokes on the UniSync server. Listing 13.6 shows the relevant code snippets from class ResetServer.Listing 13.6. Snippet from the ResetServer class to setup the UniSync server
// Connects to the backend server manager = SyncManager.getInstance(caturl,catdriver, catuser,catpassword); String dsname; dsname=SyncDataSource.DEFAULT; String hubname="Hub"; Hub hub=manager.createHub(hubname); Publication pub; String pubname; SpokeConfig spoke; Subscription sub; String subname="SubNameCard"; String tablename="NAMECARD"; String[] tables=new String[]{tablename}; // publish the complete namecard table pubname="PubNameCard"; pub=hub.newPublication(pubname,dsname,tables); hub.publish(pub); // create two spokes and subscribe // to this publication for(int i=1;i<=2;i++) { String name="Spoke"+i; spoke=hub.createSpokeConfig(name); spoke.savePassword("pass"+i); sub = spoke.newSubscription(subname, SyncDataSource.DEFAULT,pubname); spoke.subscribe(sub); } // publish the namecard table; without // the picture column pubname="PubNameCardNoPicture"; pub=hub.newPublication(pubname,dsname,tables); SyncTable table=pub.getSyncTable(tablename); table.dropSyncColumns(new String[]{"PICTURE"}); hub.publish(pub); // create two spokes and subscribe to // this publication for(int i=3;i<=4;i++) { String name="Spoke"+i; spoke=hub.createSpokeConfig(name); spoke.savePassword("pass"+i); sub = spoke.newSubscription(subname, SyncDataSource.DEFAULT,pubname); spoke.subscribe(sub); } manager.close();
On the client side, since Contact Manager's database access layer is isolated, we mainly need to make changes to the DBManager class, and the rest of the application will automatically take advantage of the synchronization features. The following code snippet (Listing 13.7) from DBManager demonstrates how to obtain the spoke stub and process the synchronization on the device side. The comments embedded in the code illustrate the differences between the synchronized version and the local version of the application.Listing 13.7. Refactor the DBManager class in the Contact Manager example to take advantage of database synchronization
// Import proprietary classes for sync import com.pointbase.me.jdbc.*; class DBManager { // In addition to JDBC connection variables // we also need to define variables for sync // ... ... private Spoke spoke; private String spokename; private int spoke_id; private int spoke_range_start,spoke_range_end; final static int ROWS_PER_SPOKE=1<<16; private String syncurl; private String syncpassword; private DBManager() { // get DB connection parameters // ... ... // get sync parameters syncurl = properties.getProperty("syncurl", "http://localhost:8124"); String spokeid = properties.getProperty("spokeid", "1"); spokename = properties.getProperty("spoke", "Spoke"+spokeid); syncpassword = properties.getProperty("syncpassword", "pass"+spokeid); url = properties.getProperty("url", "jdbc:pointbase:micro:pbdemo"+spokeid); connect(); } // The complete connect method using // synchronization server private void connect() { try { // Connecting to the database... Class.forName(driver); // If the database doesn't exist, // create a new database. connection = DriverManager.getConnection(url, user, password); statement = connection.createStatement(); // Check sync metadata and create tables loadMeta(); // Creating prepared statements createStatement(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } // The complete newID method using the sync server private int getNewID() { try { ResultSet rs = statement.executeQuery( "SELECT MAX(ID)+1 FROM NameCard WHERE "+ "ID>=" + spoke_range_start + " AND ID<"+spoke_range_end); rs.next(); int id=rs.getInt(1); if(rs.wasNull()) { return spoke_range_start; } else { return id; } } catch (Exception e) { e.printStackTrace(); } return 0; } // Create table and load metadata // from the sync hub void loadMeta() { try { SyncManager manager = SyncManager.getInstance(connection); spoke=manager.getSpoke(spokename); if(spoke==null) { System.out.println( "Loading MetaData from url "+syncurl+ " for spoke "+spokename+ " using password "+syncpassword); spoke=manager.createSpoke(spokename); spoke.savePassword(syncpassword); spoke.saveHubURL(syncurl); spoke.loadConfig(); spoke.getSnapshot(); } spoke_id = spoke.getSpokeId(); System.out.println("SpokeID is "+spoke_id); spoke_range_start = ROWS_PER_SPOKE * spoke_id; spoke_range_end = spoke_range_start + ROWS_PER_SPOKE - 1; } catch (SyncException e) { e.printStackTrace(); } } // Synchronize spoke databases (mobile databases) // with the hub and backend databases void sync() { try { spoke.sync(); } catch (SyncException e) { e.printStackTrace(); } } // Other data access methods are the same as the // non-synced version. }
|