Retrieving a Replica


In a normal Java application, new objects are created using the new operator to invoke a class's constructor, e.g.:
    ...
    TestBean myTestBean = new TestBean();
    ...
In a CORK application, new replicated objects must be created in such a way that the CORK server can create a master replica of the new object and make it available to other clients. This is done with the getNewObject(...) method in ReplicatedObjectClient. For example,
    ...
    ReplicatedObjectClient client = new InetClient(...);
    client.login(...);
    ...
    TestBean repTestBean = (TestBean) client.getNewObject(TestBean.class, null);
    ...
The first argument to getNewObject is the class of the new replicated object. The second argument is an object that controls access to the object. If this is null, any user connecting from any client will be able to retrieve, modify, or delete the replicated object. (Security is described in more detail in a later section.)

For multiple clients to collaborate using a replicated object, each client should not use getNewObject(...) to create new replicas. They should instead retrieve a copy of an existing replica. All replicated objects are identified by instances of edu.vt.cs.collab.cork.ObjectID. Given an ObjectID, the getObject(...) method in ReplicatedObjectClient. This object takes an ObjectID as an argument and retrieves a replica of the object from the server.

The exact means for discovering ObjectIDs will vary from application to application. For cases in which no other information is available to "bootstrap" replica retrieval, CORK provides a crude, brute-force query mechanism that can be used to retrieve the set of ObjectIDs that match a given criteria. Many types of queries can be done using this mechanism, but a common one is to simply retrieve the ids of all replicas of a given class of object that the current user can retrieve. An example of such a query might look like:
    import edu.vt.cs.collab.search.RetrievableCriteria;
    ...
    RetrievableCriteria crit = new RetrievableCriteria(
                client.getUser(), TestBean.class);
    ObjectID ids[] = client.getIdentifiers(crit);
    ...
The class below (Client2.java) shows an example of connecting to a server, logging in, and retrieving or creating a replicated TestBean:
     1  import edu.vt.cs.collab.cork.ObjectID;
     2  import edu.vt.cs.collab.cork.ReplicatedObjectClient;
     3  import edu.vt.cs.collab.cork.impl.inet.InetClient;
     4  import edu.vt.cs.collab.cork.search.RetrievableCriteria;
     5
     6  /**
     7   * Simple CORK client that retrieves or creates a replicated TestBean.
     8   * Should be executed with server host and port number as arguments.
     9   */
    10  public class Client2 {
    11      /**
    12       * Our replicated object client
    13       */
    14      private ReplicatedObjectClient client = null;
    15
    16      /**
    17       * Replicated TestBean instance
    18       */
    19      private TestBean testBean = null;
    20
    21      public Client2(String host, int port) {
    22          try {
    23              client = new InetClient(host, port, InetClient.SOCKET);
    24              client.login("my-id", "my-password");
    25
    26              // Connection and login succeeded if we got to this point. See
    27              // if a TestBean has already been created.
    28              RetrievableCriteria crit =
    29                  new RetrievableCriteria(client.getUser(), TestBean.class);
    30              ObjectID ids[] = client.getIdentifiers(crit);
    31
    32              if ((ids == null) || (ids.length == 0)) {
    33                  // The search didn't find TestBeans, so we create one
    34                  testBean = (TestBean) client.getNewObject(TestBean.class, null);
    35              }
    36              else {
    37                  // We have at least one TestBean replica in the server. We
    38                  // could do other tests if we had more than one, but for
    39                  // this demo we just take the first one.
    40                  testBean = (TestBean) client.getObject(ids[0]);
    41              }
    42          }
    43          catch(SecurityException se) {
    44              System.err.println("Login failed: ");
    45              se.printStackTrace();
    46          }
    47          catch(Exception e) {
    48              System.err.println("Client connection error: ");
    49              e.printStackTrace();
    50          }
    51      }
    52
    53      public static void main(String[] args) {
    54          int port = Integer.parseInt(args[1]);
    55          Client2 c = new Client2(args[0], port);
    56      }
    57  }
    58
In this example, the first client that connects to the server will create a TestBean instance. Any subsequent clients that connect (either while the first client is connected or after it has exited) will find and retrieve the TestBean
replica that the first client created.

Object replicas created or retrieved using getNewObject(...) or getObject(...) will be updated when modifications are made to remote replicas and Change objects are broadcast. To replicate local modifications to the replica, it is necessary to attach listeners like the one described in the previous section.

The example below (Client3.java) connects to the server, retrieves or creates a TestBean replica, and attaches a TestBeanListener to it. It then presents a simple UI for viewing and editing the replicated TestBean:
     1  import edu.vt.cs.collab.cork.ObjectID;
     2  import edu.vt.cs.collab.cork.ReplicatedObjectClient;
     3  import edu.vt.cs.collab.cork.impl.inet.InetClient;
     4  import edu.vt.cs.collab.cork.search.RetrievableCriteria;
     5  import javax.swing.*;
     6  import java.awt.*;
     7  import java.awt.event.*;
     8  import java.beans.*;
     9
    10  /**
    11   * Simple CORK client that retrieves or creates a replicated TestBean.
    12   * Should be executed with server host and port number as arguments.
    13   */
    14  public class Client3 {
    15      /**
    16       * Our replicated object client
    17       */
    18      private ReplicatedObjectClient client = null;
    19
    20      /**
    21       * Replicated TestBean instance
    22       */
    23      private TestBean testBean = null;
    24
    25      public Client3(String host, int port) {
    26          try {
    27              client = new InetClient(host, port, InetClient.SOCKET);
    28              client.login("my-id", "my-password");
    29
    30              // Connection and login succeeded if we got to this point. See
    31              // if a TestBean has already been created.
    32              RetrievableCriteria crit =
    33                  new RetrievableCriteria(client.getUser(), TestBean.class);
    34              ObjectID ids[] = client.getIdentifiers(crit);
    35
    36              if ((ids == null) || (ids.length == 0)) {
    37                  // The search didn't find TestBeans, so we create one
    38                  testBean = (TestBean) client.getNewObject(TestBean.class, null);
    39              }
    40              else {
    41                  // We have at least one TestBean replica in the server. We
    42                  // could do other tests if we had more than one, but for
    43                  // this demo we just take the first one.
    44                  testBean = (TestBean) client.getObject(ids[0]);
    45              }
    46
    47              // Attach a listener to ensure that remote replicas find
    48              // out about local changes:
    49              testBean.addPropertyChangeListener(new TestBeanListener(client));
    50          }
    51          catch(SecurityException se) {
    52              System.err.println("Login failed: ");
    53              se.printStackTrace();
    54          }
    55          catch(Exception e) {
    56              System.err.println("Client connection error: ");
    57              e.printStackTrace();
    58          }
    59      }
    60
    61      /**
    62       * Displays a simple UI for viewing and changing the replicated
    63       * TestBean's state.
    64       */
    65      public void showUI() {
    66          // Make a window
    67          JFrame f = new JFrame("TestBean demo");
    68
    69          // Kill the client when the window closes
    70          f.addWindowListener(new WindowAdapter() {
    71              public void windowClosing(WindowEvent evt) {
    72                  System.exit(0);
    73              }
    74          });
    75
    76          Container pane = f.getContentPane();
    77          pane.setLayout(new GridLayout(2, 1, 3, 3));
    78          JPanel top = new JPanel();
    79          pane.add(top);
    80          top.setLayout(new BorderLayout());
    81          top.add(new JLabel("value: "), BorderLayout.WEST);
    82          final JTextField current = new JTextField();
    83          top.add(current, BorderLayout.CENTER);
    84          current.setEditable(false);
    85
    86          // Initialize the current value field
    87          if (testBean.getValue() != null)
    88              current.setText(testBean.getValue());
    89          else
    90              current.setText("");
    91
    92          // Listen for changes to the "value" property, update the
    93          // field when changes occurr.
    94          testBean.addPropertyChangeListener(new PropertyChangeListener() {
    95              public void propertyChange(PropertyChangeEvent pce) {
    96                  if (testBean.getValue() != null)
    97                      current.setText(testBean.getValue());
    98                  else
    99                      current.setText("");
   100              }
   101          });
   102
   103          JPanel bottom = new JPanel();
   104          pane.add(bottom);
   105          bottom.setLayout(new BorderLayout());
   106
   107          // Add a field to the bottom for entering a new value
   108          final JTextField newValue = new JTextField();
   109          bottom.add(newValue, BorderLayout.CENTER);
   110          JButton button = new JButton("Set");
   111          bottom.add(button, BorderLayout.EAST);
   112
   113          // An action listener (for both the button and the field) that
   114          // updates the replica.
   115          ActionListener al = new ActionListener() {
   116              public void actionPerformed(ActionEvent evt) {
   117                  testBean.setValue(newValue.getText());
   118              }
   119          };
   120          button.addActionListener(al);
   121          newValue.addActionListener(al);
   122
   123          f.pack();
   124          f.setSize(300, f.getSize().height);
   125          f.show();
   126      }
   127
   128      public static void main(String[] args) {
   129          int port = Integer.parseInt(args[1]);
   130          Client3 c = new Client3(args[0], port);
   131          c.showUI();
   132      }
   133  }
   134
To run this example, first start a server, e.g.,
csh> java Server 1234
Then start several clients, e.g.,:
csh> java Client3 localhost 1234 &
csh> java Client3 localhost 1234 &
When you enter a value in the text field and press Enter or click the "Set" button, the upper field in all clients will be updated.


/public/chci/howto/cork/retrieving.html Login | Web Editor | Full Editor
Last modified 7/23/07 6:54 AM by guest (history)
Site contents