FANDOM


Description Edit

This framework lets web site administrators create forms which can be edited by multiple users concurrently. After logging in to a session, users can lock and unlock controls on a form, which causes controls for other users to become disabled and enabled, respectively. The value of an input is automatically saved to the server back-end when a field goes from a locked state to an unlocked state.

Users can join and leave in the middle of session before the form has been submitted, but every user must submit the form before it is processed by the server. In this demo, we addressed the consensus problem by making sure everyone has submitted the form (with valid input) at least once before it is processed. However, there are many other ways to achieve varying levels of consensus, so we did not focus too heavily on the problem.

Operating Model Edit

Described below is the flow of the interaction.

Updates Edit

  1. User Logs in
  2. Opens a form
  3. Receives the latest state of the form from the server
  4. Locks portions of the form (explicitly for now)
  5. A 'Lock' message is sent to server
  6. Server updates state
  7. Server sends response to users if the lock was successful
  8. For all other users currently editing the form, the locked element(s) will be un-editable
  9. Edit input values
  10. Unlock the portion of the form
  11. An 'UnLock' message to the server
  12. Server updates state
  13. Server sends response to all users (if the unlock was successful) saying that this particular element(s) are editable again.
  14. Server sends new values of the element to users
  15. All other users will have that group of controls re-enabled with the latest updated values and can lock (edit) them.

Submitting a form Edit

A form can be submitted only when every user editing the form has clicked the submit button.

The Communication protocol and Messages Edit

Each message sent to and received from the server is a JSON object(the full implementation is in the following section). There are four scenarios that we have identified to be possible for this interaction.

Case 1 User attempts to Lock an element and the server approves of it and sends a 'Success' response

  • Server sends a message to this user informing him of success
  • Server broadcasts a message to all other users informing them of the locked element and the user who has locked it
  • For the other users the element is disabled

Case 2 User attempts to Lock an element and the server does not approve of it and sends a 'Failure' response

  • Server sends a message only to this user(not a broadcast)informing him of failure.

Case 3 User finishes editing an element, UnLocks it and the server approves of it and sends a 'Success' response

  • Server broadcasts a message to all users informing them of the element which has been unlocked.
  • The latest values of the element(s) is also sent.
  • The users for whom this element was previously disabled can see the updated values and would be able to edit the element again.

Case 4 User attempts to UnLock an element which is either being locked by another user or has not been locked. The server does not approves of it and sends a 'Failure' response

  • Server sends a message only to this user(not a broadcast)informing him of failure.


Given below are the actual messages exchanged between the server and the user as JSON objects

Lock message from user to server Edit

Sent when to server from a user trying to lock 'elementID'

 {
   user: string  //The login name of the user who tried to lock the form
   elementID: string //The element which is being locked
   action: string  //  "lock"
 }

Lock response from server to user Edit

Sent from server to the user about the success or failure of his actions

 {
   user: string  //if this field matches user's name, the element can be edited by this user.
                 // Otherwise, it's a notification that the element has been locked by another user and should be disabled.
   elementID: string 
   action: string  // "lock"
   success: boolean //success or failure.
 }

Unlock message from user to server Edit

Sent when to server from a user trying to unlock 'elementID'

 {
   user: string 
   elementID: string
   elementValue: string // The updated value of the element.
   action: string  // "unlock"
 }

Unlock response from server to user Edit

Sent by server to a user informing of the success or failure of his unlock action

 {
   user: string //The user who has unlocked the field 
   elementID: string //The element that has been unlocked
   elementValue: string //The updated value of the element
   action: string  //"unlock"
   success: boolean //success or failure
 }

Update message from server to user Edit

Sent by the server to the user after he has just joined the session. Each such message depicts the current state of an elementID

 { 
   elementID: string 
   elementValue: string
   action: "update"
 }

Submit message from user to server Edit

 {
   user: string
   action: "submit"
 }

Submit response from server to user Edit

 {
   user: string
   action: "submit"
   success: string // one of "pending", "invalid", or "submitted"
 }

Implementation Edit

The interaction has an implementation on both client and server sides, which communicate using the Bayeux protocol. Bayeux is a protocol for routing JSON encoded events between clients and servers in a publish subscribe model. More details about the protocol can be found here : [1]

Client Edit

On the client side, there is the HTML form created by the webmaster, the Dojo web toolkit, and a script file that we wrote. The server side runs the jetty web server, with the Comet API (written in Java) provided by the cometd project. When a user performs an action in the browser, it invokes a Javascript function in our script, which interprets the action and calls the appropriate function. For example, if the user unlocks an element that he has edited the scripts reads the updated values from the HTML form. Now, using the Comet client in the Dojo web toolkit the client publishes a message to the server. The message is forwarded to the service subscribed to the particular channel that the client used. The message's contents are then processed, and a response is generated from the server to the client. The response message is parsed and interpreted by our script and triggers appropriate actions on the HTML form.

Server Edit

The BackerEdit

The service we wrote on the server side needs some sort of data back-end to store the state and form input. To deal with the varying kinds of back-end data stores (e.g., text file, database, big table), we created an interface to standardize data store actions called Backer. Each Backer must be able to set up, get data values, put data values, validate data and tear down. Each instance of our service is initialized with a Backer, which is called at various times to store or retrieve data.

Semaphore TableEdit

There is also a table which maps input fields to semaphores. This table is constructed on-the-fly, so the administrator does not need to specify the input fields to the service. Whenever an input field is locked by a user, its semaphore is acquired by the user and a broadcast is published to all clients. When the input field is unlocked (or the user leaves), the semaphore is unlocked and a broadcast is published to all clients again.

Various kinds of forms Edit

In the Demo we have demonstrated how text boxes in a form can be concurrently edited. However, it is not the case that our implementation is limited only to textboxes. Although our demo does not include other editable features of a form like radio-buttons, such an implementation is fairly straightforward as described in this section

One way to extend the UI is to add a control type to the lock and unlock messages - when the server discovers that the control is of a non-modifiable type (i.e., button), then it will not invoke the Backer.put() function when the control is unlocked. The server will also know how to encode/decode checkbox and radio button representations.

For aggregates of controls, such as a group radio buttons or check boxes, a DOM container can be specified as their container, and the control type field can indicate a group lock. The server associates one semaphore with the entire group, and the lock/unlock messages name which container has been locked/unlocked, so the Javascript code can disable/enable every form element within the DOM container.

To support containers of mixed control types, the message protocol can be modified such that a user can send a message first to lock an input group, then send individual update messages which are aggregated by the server, and then a group unlock message. The server then sends the aggregated update messages and group unlock message to the other clients.

Moreover, the UI shown in our demo can be modified to a more presentable form like a user choosing to lock/unlock an element by simply clicking on that element.

Access control implementation Edit

In this section we describe a simple way of imposing constraints on which users or groups of users can edit specific parts of the forms. The idea is for the server to keep a mapping of users to groups, and a mapping of groups to form instances. This would give us the ability, on the client or server side, to create and manage groups, and an ability to create a new form instance.

Encapsulation and Reusability Edit

The client side implementation is contained within a single Javascript file. To use it, it needs to be included with the page containing the form. In addition, controls must invoke the lock and unlock functions and provide the field names and values.

The server side implementation comes as a Java class and interface definition. The class is the Collaboration service, and the interface definition for Backer is for back-end data stores. The Backer implementation is left to the user to allow for flexibility in data store types. The class is self-contained and can be added to a servlet in jetty. This also leads to the constraint that each separate form must have a Backer associated with it and a service instantiation separate from different forms.

Strengths and Weaknesses Edit

Strengths Edit

  • One of the strengths of the interaction is there are practical uses for it, such as a group application where everyone needs to contribute something, like a housing contract or team application.
  • Scaling is relatively easy - each instance of our service handles only one form class (in other words, all of one form's instances), so theoretically one server can handle communication for just one form
  • It is also concurrent and in real time; one user locking a field will disable the field for other users; unlocking will re-enable the field for other users and update the field with its new value.
  • Another strength of the implementation is its flexibility in back-end data stores. Anything can be used, as long as it implements the Backer interface.
  • The implementation of our interaction is done in dojo, which is cross-browser, so our client side is cross-browser, as well.
  • The implementation allows for no race conditions to occur


Weaknesses Edit

  • One of the weaknesses of the interaction is the difficulty of getting consensus - when does a form submit? When one user clicks "submit"? When all users click "submit"? What happens if a user decides to submit but another user decides to continue editing? What if one user doesn't care about the edits that other users make? What if one user disappears for a week?
  • Also, in the interaction, if there are more active users than there are lockable fields, some users will be unable to do anything.
  • In the implementation, there is no chat room-like communication channel between users, so fine-grained coordination of interaction between users is difficult.
  • The flip side of using dojo is that its core file is 26k gzipped and cometd client is 19k minified.

Source Code Edit

The server side code can be found here

http://tentejswi.googlepages.com/Backer.java

http://tentejswi.googlepages.com/BayeuxStartupListener.java

http://tentejswi.googlepages.com/DummyBacker.java

The client side javascript file is here

http://tentejswi.googlepages.com/form.js

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.